Java/PHP 加密 CAST-256
Java/PHP Encryption CAST-256
我在 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 文档,他们似乎正在对密钥和数据进行大量填充。我的密钥(遗留密钥)长 27 个字符,我认为 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) returns 16 , 这正是我使用的长度。
我在密码学方面非常缺乏经验,所以我有点迷茫。也许如果我可以调试 mcrypt 内部,我可以更好地了解发生了什么。
如能在 Java 中实现这些功能,我们将不胜感激。
PD。我知道这个算法不是最好的,不使用 IV 和使用 ECB 在某种程度上令人担忧,但这仅适用于遗留代码集成。
所以我终于想通了。
显然 PHP Cast6 算法的实现不标准。
起初,我什至无法重现与算法 test vectors 中相同的值,这让我精神崩溃了。所以是时候查看 PHP 的来源了。
我下载了 Ryan Gilfether 的 PhpCrypt Library,它产生的结果与 php 的 mcrypt 库完全相同。并开始调试。
我注意到 php 的实现,在将密钥和数据拆分为 4 个字节的块后,它反转了这些块的内容。这在Masking和Round Keys的生成中尤为重要,因为它们因此发生了很大的变化。
因此,一旦发现问题,从 Java 端重新创建过程就很简单了,我创建了一个新的 Bouncy Castle 引擎,扩展了 CAST5Engine 并替换了 setKey 和 encryptBlock 方法。您可以查看 this gist 以查看其工作原理。
关键是reverseByteArrayByBlock,多次调用。与 PHP 完全相同。
如果您不太熟悉 Bouncy Castle 的工作原理,您还可以在 Gist 中查看如何使用 PHPCast256Crypter.java 文件中的 class(encrypt/decrypt 函数假设您的密钥是十六进制编码的)。
祝你好运!
我在 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 文档,他们似乎正在对密钥和数据进行大量填充。我的密钥(遗留密钥)长 27 个字符,我认为 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) returns 16 , 这正是我使用的长度。
我在密码学方面非常缺乏经验,所以我有点迷茫。也许如果我可以调试 mcrypt 内部,我可以更好地了解发生了什么。
如能在 Java 中实现这些功能,我们将不胜感激。
PD。我知道这个算法不是最好的,不使用 IV 和使用 ECB 在某种程度上令人担忧,但这仅适用于遗留代码集成。
所以我终于想通了。
显然 PHP Cast6 算法的实现不标准。
起初,我什至无法重现与算法 test vectors 中相同的值,这让我精神崩溃了。所以是时候查看 PHP 的来源了。
我下载了 Ryan Gilfether 的 PhpCrypt Library,它产生的结果与 php 的 mcrypt 库完全相同。并开始调试。
我注意到 php 的实现,在将密钥和数据拆分为 4 个字节的块后,它反转了这些块的内容。这在Masking和Round Keys的生成中尤为重要,因为它们因此发生了很大的变化。
因此,一旦发现问题,从 Java 端重新创建过程就很简单了,我创建了一个新的 Bouncy Castle 引擎,扩展了 CAST5Engine 并替换了 setKey 和 encryptBlock 方法。您可以查看 this gist 以查看其工作原理。
关键是reverseByteArrayByBlock,多次调用。与 PHP 完全相同。
如果您不太熟悉 Bouncy Castle 的工作原理,您还可以在 Gist 中查看如何使用 PHPCast256Crypter.java 文件中的 class(encrypt/decrypt 函数假设您的密钥是十六进制编码的)。
祝你好运!