我在PHP中有这个遗留代码,我希望用Java重现:
function enCrypt($data = null) {
$key = 'thisismysupersecretkeyglhf1';
$encoded=mcrypt_encrypt(MCRYPT_CAST_256,
$key,
$data,
MCRYPT_MODE_ECB
);
$encoded = base64_encode($encoded);
return $encoded;
}
function deCrypt($data = null) {
$key = 'thisismysupersecretkeyglhf1';
$decrypted= mcrypt_decrypt(
MCRYPT_CAST_256,
$key,
base64_decode($data),
MCRYPT_MODE_ECB
);
return $decrypted;
}
我正在以下列方式使用Bouncy Castle CAST-6引擎:
public static final String KEY = "thisismysupersecretkeyglhf1";
public static String encrypt(String toDecrypt) throws NoSuchPaddingException,
NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException, DecoderException, UnsupportedEncodingException {
Cipher cipher = Cipher.getInstance("CAST6/ECB/NoPadding");
SecretKeySpec key=new SecretKeySpec(KEY.getBytes(),"CAST6");
cipher.init(Cipher.ENCRYPT_MODE, key);
String decoded=org.apache.commons.codec.binary.Base64.encodeBase64String(cipher.doFinal(toDecrypt.getBytes()));
return decoded;
}
public static String decrypt(String toDecrypt) throws NoSuchPaddingException,
NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException,
InvalidKeyException, BadPaddingException, IllegalBlockSizeException, DecoderException, UnsupportedEncodingException {
Cipher cipher = Cipher.getInstance("CAST6/ECB/NoPadding");
SecretKeySpec key=new SecretKeySpec(KEY.getBytes(),"CAST6");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decoded=org.apache.commons.codec.binary.Base64.decodeBase64(toDecrypt);
return new String(cipher.doFinal(decoded));
}
但是,我无法使用JAVA生成相同的加密结果或解密在PHP中加密的任何内容。
我缺少什么?
这是填充问题吗?通过mcrypt文档阅读,他们似乎对密钥和数据进行了大量填充。我的密钥(遗留密钥)长27chars,我认为应该用mcrypt填充到32字节,因为mcrypt_get_key_size(MCRYPT_CAST_256,MCRYPT_MODE_ECB)导致32。
有关详细信息,我尝试加密的字符串是" 1111111111111111"。我不知道这是否被PHP填充,但我认为它不会因为,mcrypt_get_block_size(MCRYPT_CAST_256,MCRYPT_MODE_ECB)返回16,这正是Im使用的长度。
我对密码学缺乏经验,所以我有点迷失。也许如果我可以调试mcrypt内部,我可以更好地了解发生了什么。
非常感谢任何用Java实现这些功能的帮助。
PD。我知道这个算法不是最好的,并且不使用IV以及使用ECB在某种程度上是令人担忧的,但这仅适用于遗留代码集成。
答案 0 :(得分:1)
所以我终于想通了。
显然,似乎Cast6算法的PHP实现不是标准的。
起初,由于无法复制与算法test vectors中的值相同的值,因此我精神崩溃了。所以是时候看看PHP的来源了。
我下载了Ryan Gilfether的PhpCrypt Library,它产生了与php的mcrypt lib完全相同的结果。并开始调试。
我注意到php的实现,在将密钥和数据分成4个字节块后,它会反转这些块的内容。这对于Masking和Round Keys的生成尤其重要,因为它们因此而发生了很大的变化。
因此,一旦发现问题,从Java端重新创建流程是一件简单的事情,我创建了一个新的Bouncy Castle Engine,扩展了CAST5Engine并取代了setKey和encryptBlock方法。您可以查看this gist以查看其工作原理。
键是reverseByteArrayByBlock,它被多次调用。与PHP完全相同。
在Gist中,您还可以查看如何在PHPCast256Crypter.java文件中使用该类,以防您对Bouncy Castle的工作方式不太熟悉(加密/解密函数假设您的密钥是十六进制编码的)。
祝你好运!