这里写自定义目录标题
- 背景
- JAVA代码
- 解决思路
- PHP解密
背景
公司PHP开发对接一个Java项目接口,接口返回数据有用DESede/ECB/PKCS5Padding加密,并且key也使用了SHA1PRNG加密了,网上找了各种办法都不能解密,耗了一两天的时间,一度怀疑人生……
JAVA代码
public class DESUtil {
private static final String KEY_ALGORITHM = "DESede";
private static final String DEFAULT_CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";
/* DES加密 */
public static String encrypt(String content, final String key) {
try {
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
byte[] byteContent = content.getBytes(StandardCharsets.UTF_8.name());
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
byte[] result = cipher.doFinal(byteContent);
return Base64.encodeBase64String(result);
} catch (Exception ex) {
log.error("【DES加密失败】:", ex);
}
return null;
}
/* DES解密 */
public static String decrypt(String content, final String key) {
try {
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
byte[] result = cipher.doFinal(Base64.decodeBase64(content));
return new String(result, StandardCharsets.UTF_8.name());
} catch (Exception ex) {
log.error("【DES解密失败】:", ex);
}
return null;
}
public static SecretKeySpec getSecretKey(final String key) {
KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8.name()));
kg.init(secureRandom);
SecretKey secretKey = kg.generateKey();
return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);
} catch (NoSuchAlgorithmException ex) {
log.error("【DES生成秘钥失败】:", ex);
} catch (UnsupportedEncodingException e) {
log.error("【DES生成秘钥失败】:", e);
}
return null;
}
}
解决思路
终于找到了一个类似问题,可是要会员才能看,作为一名穷DS,哪有这么富有,灵机一动在某鱼花了1大洋看了解决思路,果然是金钱的力量,功夫不负有心人啊,终于寻到stackoverflow有个类似问题。
上面Java代码中的secretKey变量的比特值,使用Base64Utils.encode后得到base64字符串
然后在php中使用base64_decode解码串,得到密钥key
PHP解密
/* 3DES解密 */
public function desDecrypt($content) {
$key=$this->config['desKey'];
$key=base64_decode($key);
$content = base64_decode($content);
// 解密数据
$plaintext = openssl_decrypt($content, 'DES-EDE3', $key, OPENSSL_RAW_DATA);
return $plaintext;
}