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 函数假设您的密钥是十六进制编码的)。

祝你好运!