2
votes

I've implemented AES encryption with certain task-specific parameters using standard Java tools and BouncyCastle provider for specific AES algorithm.

Here is the code:

private byte[] aesEncryptedInfo(String info) throws UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidParameterSpecException, InvalidAlgorithmParameterException, NoSuchProviderException {
    Security.addProvider(new BouncyCastleProvider());
    SecretKey secret = new SecretKeySpec(CUSTOMLONGSECRETKEY.substring(0, 32).getBytes(), "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
    cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(VECTOR_SECRET_KEY.getBytes()));
    return cipher.doFinal(info.getBytes("UTF-8"));
}

In some environments this code requires special policy files. See related question: InvalidKeyException Illegal key size

My goal is to reimplement it using third-party library, ideally I would use bouncy castle which is already used as provider. The library should have no restictions of standard java policy files. In other words there should be no restrictions.

Please suggest in your answers how to reimplement it using BouncyCastle or other third-party library which can work without restrictions mentioned. Ideally I would see the code :-)

Thank you very much for reading!

After a delay I now happy to post a solution. Hope that someone can benefit from it because Bouncy Castle documentation is not filled with a lot of examples :-)

private byte[] aesEncryptedInfo(String info)
// Creating AES/CBC/PKCS7Padding cipher with specified Secret Key and Initial Vector
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()), new PKCS7Padding());
cipher.init(true, new ParametersWithIV(new KeyParameter(CUSTOMLONGSECRETKEY.getBytes()), VECTOR_SECRET_KEY.getBytes()));

byte[] inputData = info.getBytes("UTF-8");
int outBlockSize = cipher.getOutputSize(inputData.length);
byte[] outputData = new byte[outBlockSize];

int outLength = cipher.processBytes(inputData, 0, inputData.length, outputData, 0);
outLength += cipher.doFinal(outputData, outLength);
if (outLength != outBlockSize) {
    return Arrays.copyOf(outputData, outLength);
}
else {
    return outputData;
}    

}

By the way I found two differences between Java API and Bouncy Castle API: 1. Bouncy Castle uses composition of objects to create needed cipher. While Java API uses string to identify needed cipher. 2. BC encryption code slightly bigger, while Java API code is more compact.

The solution is full replacement for original Java API implementation - the proof is a custom unit test that I made.

3

3 Answers

3
votes

Use the Bouncycastle lightweight crypto API directly, rather than through Java JCE interface. Bouncycastle includes its own crypto API accessible through various classes in org.bouncycastle.* packages. It also implements the JCE provider interface to make some of its crypto implementations available through standard JCE classes like Cipher, KeyGenerator, etc.

The cryptography policy restrictions are enforced by the JCE classes, not by bouncycastle. Therefore if you do not use these classes you'll will not encounter any restrictions. On the downside you will sacrifice some portability. To get started, take a look at the javadocs for the AESEngine class, and the rest of the javadocs for the bouncycastle.

1
votes

Why isn't it possible to just add the necessary policy files?

That would be the easiest thing to do. If you live in the US and you export your software to other (maybe "unallowed") countries, you will (theoretically) get trouble either way (including policy files/doing the encryption yourself).

If you live outside the US, why even bother about it, just include the policy files, no one cares.

0
votes

No option for buying a toolkit? RSA BSAFE