I have a little test that passes but doesn't actually do any encryption. How shall I proceed?
Since I know nothing about this space, I do a bit of searching on the web to find out what I need to do to get started. Let's just see what might come up. Hey! That stack overflow entry looks to be just the ticket. What can I do with that?
After copying the code fragment from the posting, it doesn't compile. IntelliJ is giving me warnings about exceptions. Here is what I have for my encrypt function after adding try/catch to the sample:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private String encrypt(String plainText) { | |
byte[] sessionKey = null; //Where you get this from is beyond the scope of this post | |
byte[] iv = null; //Ditto | |
byte[] ciphertext = null; | |
Cipher cipher; | |
try { | |
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
//You can use ENCRYPT_MODE or DECRYPT_MODE | |
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv)); | |
ciphertext = cipher.doFinal(plainText.getBytes()); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} catch (IllegalBlockSizeException e) { | |
e.printStackTrace(); | |
} catch (BadPaddingException e) { | |
e.printStackTrace(); | |
} | |
return ciphertext.toString(); | |
} |
Running the test doesn't work. It is complaining about a 'Missing argument' in the SecretKeySpec constructor. Well, there are those caveats about we'll need a byte array for the key and the vector. I can make up a vector, but how should I initialize the key buffer (sessionKey) with something realistic? It looks like there is a KeyGenerator class. So, with initializing the vector and using the KeyGenerator class to set my byte array looks like:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
byte[] sessionKey = null; | |
byte[] iv = new byte[] { 0x7F, 0x6E, 0x5D, 0x4C, 0x3B, 0x2A, 0x19, 0x08 }; | |
byte[] ciphertext = null; | |
Cipher cipher; | |
try { | |
KeyGenerator kGen = KeyGenerator.getInstance("AES"); | |
kGen.init(128); | |
sessionKey = kGen.generateKey().getEncoded(); | |
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
//You can use ENCRYPT_MODE or DECRYPT_MODE | |
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv)); | |
ciphertext = cipher.doFinal(plainText.getBytes()); | |
} catch (NoSuchAlgorithmException e) { |
When I run the test, however, I get a useful error message:
java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes longThat is easy enough to fix, I'll just add some more bytes to my array....
And, I get another good error message!
org.junit.ComparisonFailure: Expected :Original Plaintext Actual :[B@5e7808b9
Can it really be that easy? Do I just have to reverse the process in my decrypt and I'll have end to end decryption?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class JCEExampleTest { | |
private byte[] sessionKey = null; | |
private final byte[] iv = new byte[] { 0x7F, 0x6E, 0x5D, 0x4C, 0x3B, 0x2A, 0x19, 0x08, | |
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 }; | |
@Test | |
public void decryptingCiphertextShouldReturnOriginalPlaintext() { | |
assertEquals("Original Plaintext", decrypt(encrypt("Original Plaintext"))); | |
} | |
private String decrypt(String cipherText) { | |
byte[] plaintext = null; | |
Cipher cipher; | |
try { | |
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
//You can use ENCRYPT_MODE or DECRYPT_MODE | |
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv)); | |
plaintext = cipher.doFinal(cipherText.getBytes()); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} catch (IllegalBlockSizeException e) { | |
e.printStackTrace(); | |
} catch (BadPaddingException e) { | |
e.printStackTrace(); | |
} | |
return plaintext.toString(); | |
} | |
private String encrypt(String plainText) { | |
byte[] ciphertext = null; | |
Cipher cipher; | |
try { | |
KeyGenerator kGen = KeyGenerator.getInstance("AES"); | |
kGen.init(128); | |
sessionKey = kGen.generateKey().getEncoded(); | |
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
//You can use ENCRYPT_MODE or DECRYPT_MODE | |
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv)); | |
ciphertext = cipher.doFinal(plainText.getBytes()); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} catch (IllegalBlockSizeException e) { | |
e.printStackTrace(); | |
} catch (BadPaddingException e) { | |
e.printStackTrace(); | |
} | |
return ciphertext.toString(); | |
} | |
} |
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
Well, I guess I know what to do--another search!
And I see some things in this post. Hmm. UTF-8 and base64 encoding. That suggests another post from that search. (The one about Base64 on stack overflow).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private String decrypt(String cipherText) { | |
byte[] plaintext = null; | |
Cipher cipher; | |
try { | |
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
//You can use ENCRYPT_MODE or DECRYPT_MODE | |
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv)); | |
plaintext = cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(cipherText)); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} catch (IllegalBlockSizeException e) { | |
e.printStackTrace(); | |
} catch (BadPaddingException e) { | |
e.printStackTrace(); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. | |
} catch (IOException e) { | |
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. | |
} | |
return plaintext.toString(); | |
} | |
private String encrypt(String plainText) { | |
byte[] ciphertext = null; | |
Cipher cipher; | |
try { | |
KeyGenerator kGen = KeyGenerator.getInstance("AES"); | |
kGen.init(128); | |
sessionKey = kGen.generateKey().getEncoded(); | |
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); | |
//You can use ENCRYPT_MODE or DECRYPT_MODE | |
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv)); | |
ciphertext = cipher.doFinal(plainText.getBytes("utf-8")); | |
} catch (NoSuchAlgorithmException e) { | |
e.printStackTrace(); | |
} catch (NoSuchPaddingException e) { | |
e.printStackTrace(); | |
} catch (InvalidKeyException e) { | |
e.printStackTrace(); | |
} catch (InvalidAlgorithmParameterException e) { | |
e.printStackTrace(); | |
} catch (IllegalBlockSizeException e) { | |
e.printStackTrace(); | |
} catch (BadPaddingException e) { | |
e.printStackTrace(); | |
} catch (UnsupportedEncodingException e) { | |
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. | |
} | |
return new BASE64Encoder().encode(ciphertext).toString(); | |
} |
OK. So at this point I'm closer but still have a problem. The decryption is not working. But that is enough for this post. I'll mull on it for a bit. I think first I should clean up the code some and that may make it easier to spot my issue.
Stay tuned.
No comments:
Post a Comment