Java BouncyCastle Cast6Engine (CAST-256) encryptin

2019-04-02 17:05发布

问题:

I'm trying to implement a function that receives a string and returns the encoded values of the String in CAST-256. The following code is what i implement following the example on BoncyCastle official web page (http://www.bouncycastle.org/specifications.html , point 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);
    }

}

But , when i run my code i get

QUrYzMVlbx3OK6IKXWq1ng==

and if you encode hola in CAST-256 with the same key ( try here if you want http://www.tools4noobs.com/online_tools/encrypt/) i should get

w5nZSYEyA8HuPL5V0J29Yg==.

What is happening? Why im getting a wront encrypted string?

I'm tired of find that on internet and didnt find a answer.

回答1:

Bouncy Castle uses PKCS #7 padding by default, while PHP's mcrypt (and the web site you linked) uses zero padding by default. This causes the different ciphertexts.

Please note that the ECB mode used here is not secure for almost any use. Additionally, I hope the secret key you posted is not the real key, because now that it's not secret anymore, all this encryption is useless.



回答2:

This doesn't really answer your question, but it does provide some pointers.

You need to do a little digging to ensure you are decrypting in exactly the same way as PHP's mcrypt(). You need to make sure your key generation, encoding/decoding and cipher algorithm match exactly.

Keys

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

is probably not the right way to create the key source bytes. The docs seem to indicate that mcrypt() pads the key and data with \0 if it isn't the right size. Note that your method produces a 168 bit key, which is not a valid key size and I'm not sure what java is going to do about it.

Algorithm
Make sure the cipher mode and padding are the same. Does mcrypt() use ECB, CBC, something else?

Encoding
Ciphers work on bytes, not Strings. Make sure your conversion between the two is the same in java and PHP.

Here is a reference test for CAST6 using test vectors from http://tools.ietf.org/html/rfc2612#page-10. Note the key, ciphertext and plaintext are hex encoded.

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

}