Java / PHP加密CAST-256

Java / PHP加密CAST-256

问题描述:

I have this legacy Code in PHP that I want to reproduce in 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;
}

I am using Bouncy Castle CAST-6 Engine in the following way:

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

However, I'm not being able to produce the same encrypted results or decrypt anything encrypted in PHP using JAVA.

What am I lacking?

Is this a Padding Issue? Reading through mcrypt documentation, they seem to be doing a lot of padding to keys and data. My Key (legacy key) is 27chars long, which I believe should be padded to 32 bytes by mcrypt, since mcrypt_get_key_size(MCRYPT_CAST_256,MCRYPT_MODE_ECB) results in 32.

For further info the string I'm trying to encrypt is "1111111111111111". I don't know if this get padded by PHP , but I would think it wouldn't because, mcrypt_get_block_size(MCRYPT_CAST_256,MCRYPT_MODE_ECB) returns 16, which is exactly the length Im using.

I am very inexperienced in cryptography, so I'am a little bit lost. Maybe if I could debug mcrypt internals, I could have a better idea of what's happening.

Any help implementing these functions in Java would be greatly appreciated.

PD. I know this algorithm is not the best, and not using an IV as well as using ECB is somehow alarming, but this is only for legacy code integration.

So I finally figured this out.

Apparently it seems PHP implementation of the Cast6 Algorithm is not standard.

At first I had a nervous breakdown by not being able to even reproduce the same value as the ones in the test vectors for the algorithm. So it was time to look at PHP's source.

I downloaded the PhpCrypt Library by Ryan Gilfether, which produces the exact same result as php's mcrypt lib. And started debugging.

I noticed that php's implementation, after splitting the key and data into 4 bytes blocks, it reverses the contents of these blocks. This is particularly important in the generation of the Masking and Round Keys, because they change a lot because of this.

So, once the problem was spotted , it was a simple matter to recreate the process from the Java side, I created a new Bouncy Castle Engine extending the CAST5Engine and replaced the setKey and encryptBlock method. You can check out this gist to see how it works.

The key is the reverseByteArrayByBlock, which is called multiple times. In the exact same way as PHP does it.

In the Gist you can also check out how to use the class in the PHPCast256Crypter.java file in case you are not too familiar with how Bouncy Castle works (the encrypt/decrypt functions assume your keys are hex encoded).

Good Luck!