0

我正在尝试实现一个接收字符串并返回 CAST-256 中字符串的编码值的函数。以下代码是我按照 BoncyCastle 官方网页(http://www.bouncycastle.org/specifications.html,第 4.1 点)上的示例实现的。

import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.engines.CAST6Engine;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;


public class Test {

    static{
        Security.addProvider(new BouncyCastleProvider());
    }

    public static final String UTF8 = "utf-8";
    public static final String KEY = "CLp4j13gADa9AmRsqsXGJ";

    public static byte[] encrypt(String inputString) throws UnsupportedEncodingException {
        final BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CAST6Engine());
        byte[] key = KEY.getBytes(UTF8);
        byte[] input = inputString.getBytes(UTF8);
        cipher.init(true, new KeyParameter(key));

        byte[] cipherText = new byte[cipher.getOutputSize(input.length)];

        int outputLen = cipher.processBytes(input, 0, input.length, cipherText, 0);
        try {
            cipher.doFinal(cipherText, outputLen);
        } catch (CryptoException ce) {
            System.err.println(ce);
           System.exit(1);
        }
        return cipherText;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        final String toEncrypt = "hola";
        final String encrypted = new String(Base64.encode(test(toEncrypt)),UTF8);
        System.out.println(encrypted);
    }

}

但是,当我运行我的代码时,我得到了

QUrYzMVlbx3OK6IKXWq1ng==

如果你hola用相同的密钥在 CAST-256 中编​​码(如果你想要http://www.tools4noobs.com/online_tools/encrypt/试试这里)我应该得到

w5nZSYEyA8HuPL5V0J29Yg==.

怎么了?为什么我得到一个错误的加密字符串?

我厌倦了在互联网上找到它并没有找到答案。

4

2 回答 2

0

这并不能真正回答您的问题,但确实提供了一些指示。

您需要进行一些挖掘以确保您以与 PHP 完全相同的方式进行解密mcrypt()。您需要确保您的密钥生成、编码/解码和密码算法完全匹配。

钥匙

"CLp4j13gADa9AmRsqsXGJ".getBytes("UTF-8");

可能不是创建关键源字节的正确方法。文档似乎表明,如果它的大小不合适,则mcrypt()用它填充键和数据。\0请注意,您的方法会生成一个 168 位密钥,这不是有效的密钥大小,我不确定 java 将对此做什么。

算法
确保密码模式和填充相同。是否mcrypt()使用ECB,CBC,其他东西?

编码
密码适用于字节,而不是字符串。确保两者之间的转换在 java 和 PHP 中是相同的。

这是使用来自https://www.rfc-editor.org/rfc/rfc2612#page-10的测试向量的 CAST6 参考测试。注意密钥、密文和明文是十六进制编码的。

import java.security.Provider;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class Cast6 {

    static final String KEY_ALGO = "CAST6";
    static final String CIPHER_ALGO = "CAST6/ECB/NOPADDING";
    
    static String keytext = "2342bb9efa38542c0af75647f29f615d";
    static String plaintext = "00000000000000000000000000000000";
    static String ciphertext = "c842a08972b43d20836c91d1b7530f6b";
    
    static Provider bc = new BouncyCastleProvider();
    
    public static void main(String[] args) throws Exception {
        
        System.out.println("encrypting");
        String actual = encrypt();
        System.out.println("actual: " + actual);
        System.out.println("expect: " + ciphertext);

        System.out.println("decrypting");
        actual = decrypt();
        System.out.println("actual: " + actual);
        System.out.println("expect: " + plaintext);
    }

    static String encrypt() throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGO, bc);
        
        byte[] keyBytes = Hex.decodeHex(keytext.toCharArray());
        SecretKeySpec key = new SecretKeySpec(keyBytes, KEY_ALGO);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        
        byte[] input = Hex.decodeHex(plaintext.toCharArray());
        byte[] output = cipher.doFinal(input);
        String actual = Hex.encodeHexString(output);
        return actual;
    }
    

    static String decrypt() throws Exception {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGO, bc);
        
        byte[] keyBytes = Hex.decodeHex(keytext.toCharArray());
        SecretKeySpec key = new SecretKeySpec(keyBytes, KEY_ALGO);
        cipher.init(Cipher.DECRYPT_MODE, key);
        
        byte[] output = cipher.doFinal(Hex.decodeHex(ciphertext.toCharArray()));
        
        String actual = Hex.encodeHexString(output);
        return actual;  
    }

}
于 2013-07-31T16:04:22.683 回答
0

Bouncy Castle 默认使用 PKCS #7 填充,而 PHP 的 mcrypt(以及您链接的网站)默认使用零填充。这导致了不同的密文。

请注意,此处使用的 ECB 模式对于几乎所有用途来说都不安全。另外,我希望您发布的密钥不是真正的密钥,因为现在它不再是秘密,所有这些加密都是无用的。

于 2013-07-31T14:08:18.170 回答