2015-07-03 34 views
1

我在PHP这个遗留代码,我想在Java中重现:的Java/PHP加密CAST-256

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; 
} 

我用的充气城堡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文档,他们似乎在为密钥和数据做了很多填充。我的钥匙(传统密钥)是在32

27chars长,我相信会被填充到由mcrypt的32个字节,因为mcrypt_get_key_size(MCRYPT_CAST_256,MCRYPT_MODE_ECB)结果为进一步的信息我想加密的字符串为“ 1111111111111111" 。我不知道这是否被PHP填充,但我认为这不会因为,mcrypt_get_block_size(MCRYPT_CAST_256,MCRYPT_MODE_ECB)返回16,这正是我使用的长度。

我在密码学中非常缺乏经验,所以我'一点点丧失。也许如果我可以调试mcrypt内部,我可以更好地了解发生了什么。

任何用Java实现这些功能的帮助,将不胜感激。

PD。我知道这个算法不是最好的,不使用IV以及使用ECB也是令人担忧的,但这只是遗留代码集成。

+0

我有与PHP <=>德尔福和AES-256相同的问题。这也是一些填充问题,所以我们在Webservice的两端做了一个前缀处理,以获得相同的结果。在对称密码学方面更熟练的人将能够帮助你更多。祝你好运 ! –

+0

你能发布一个PHP密文(十六进制)吗? –

回答

1

所以我终于明白了这一点。

显然,这似乎Cast6算法的PHP执行不规范。

起初我因神经衰弱,甚至无法重现与算法中的test vectors相同的值。所以现在是查看PHP源代码的时候了。

我下载了Ryan Gilfether的PhpCrypt Library,它产生与php的mcrypt lib完全相同的结果。并开始调试。

我注意到php的实现,在将密钥和数据分割成4个字节块后,它将这些块的内容反转。这在生成Masking和Round Keys中尤为重要,因为它们因此而改变很多。

因此,一旦发现问题,从Java端重新创建过程是一件简单的事情,我创建了一个新的Bouncy Castle引擎,扩展了CAST5Engine并替换了setKey和encryptBlock方法。您可以查看this gist以了解它的工作原理。

关键是reverseByteArrayByBlock,它被多次调用。与PHP完全一样。

在Gist中,您还可以查看如何在PHCast256Crypter.java文件中使用该类,以便您不太熟悉Bouncy Castle的工作方式(加密/解密函数假定您的密钥是十六进制编码)。

祝你好运!

+0

你刚刚救了我的一天!非常感谢你 –