Java BouncyCastle Cast6Engine(CAST-256)加密

时间:2013-07-31 13:39:47

标签: java encryption bouncycastle

我正在尝试实现一个接收字符串的函数,并返回CAST-256中String的编码值。以下代码是我在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==

如果您使用相同的密钥在CAST-256中编码hola(如果您需要http://www.tools4noobs.com/online_tools/encrypt/,请尝试此处)我应该

w5nZSYEyA8HuPL5V0J29Yg==

发生了什么事?为什么我得到一个wront加密字符串?

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

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

这并没有真正回答你的问题,但确实提供了一些指示。

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

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

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

<强>算法
确保密码模式和填充是相同的。 mcrypt()是否使用ECB,CBC,还有其他什么?

<强>编码
密码工作在字节上,而不是字符串。确保你在两者之间的转换在java和PHP中是相同的。

以下是使用来自http://tools.ietf.org/html/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;  
    }

}