I have two classes, one is main class and another is the implementation of AES.
However, in my AES class i have a method to decrypt a string, but whenever i run it, it gives an exception
My encryption method works just fine but my decryption method doesn't work as expected.
The code
private Cipher aesCipherForDecryption;
String strDecryptedText = new String();
public String decryptAES(final String ciphertext) {
try {
aesCipherForDecryption = Cipher.getInstance("AES/CBC/PKCS5PADDING");
aesCipherForDecryption.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iV));
byte[] byteDecryptedText = aesCipherForDecryption.doFinal(byteCipherText);
strDecryptedText = new String(byteDecryptedText);
} catch (IllegalBlockSizeException e) {
System.out.print("IllegalBlockSizeException " +e);
} catch (BadPaddingException e) {
System.out.print("BadPaddingException "+e);
} catch (NoSuchAlgorithmException e) {
System.out.print("NoSuchAlgorithmException "+ e);
} catch (NoSuchPaddingException e) {
System.out.print("NoSuchPaddingException "+e);
} catch (InvalidKeyException e) {
System.out.print("InvalidKeyException "+e);
} catch (InvalidAlgorithmParameterException e) {
System.out.print("InvalidAlgorithmParameterException "+e);
}
System.out.println("\nDecrypted Text message is " + strDecryptedText);
return strDecryptedText;
}
The error this method outputs is
InvalidKeyException java.security.InvalidKeyException: No installed provider supports this key: (null)
UPDATE #1:
So i have updated the code as the following
public String decryptAES(byte[] ciphertext) {
String strDecryptedText = new String();
try {
byte[] byteDecryptedText = aesCipherForDecryption.doFinal(ciphertext);
strDecryptedText = new String(byteDecryptedText);
} catch (IllegalBlockSizeException e) {
System.out.print("IllegalBlockSizeException "+e);
e.printStackTrace();
} catch (BadPaddingException e) {
System.out.print("BadPaddingException "+e);
e.printStackTrace();
}
System.out.println("\nDecrypted Text message is " + strDecryptedText);
return strDecryptedText;
}
and in the main class i have this line
byte [] byteciphertext = ciphertext.getBytes();
just to convert the string to bytes
is it correct? i'm still having
IllegalBlockSizeException javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipherjavax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
Could someone help me fix this issue?
Thank you.
secretKey is clearly null.
Other problems:
You aren't using the input parameter cipherText.
The input parameter cipherText should be a byte[], not a String: cipher text is binary, and String is not a container for binary data.
The result string strDecryptedText should be a local variable, not a member variable.
Related
I'm new to cryptography and this here is the code that I wrote filling in the skeleton code provided by my assigner(please don't mind the structure). I describe the problem below this code.
public class FileEncryptor {
private static final String progName = "FileEncryptor";
private static final int bufSize = 128;
public static void main(String[] args) {
BufferedInputStream in = null; // A buffered input stream to read from
BufferedOutputStream out = null; // And a buffered output stream to write to
SecretKeyFactory kf = null; // Something to create a key for us
KeySpec ks = null; // This is how we specify what kind of key we want it to generate
byte[] salt = new byte[20]; // Some salt for use with PBKDF2, only not very salty
SecretKey key = null; // The key that it generates
Cipher cipher = null; // The cipher that will do the real work
SecretKeySpec keyspec = null; // How we pass the key to the Cipher
int bytesRead = 0; // Number of bytes read into the input file buffer
// First, check the user has provided all the required arguments, and if they haven't, tell them then exit
if(args.length != 4) {
printUsageMessage(); System.exit(1);
}
// Open the input file
try {
in = new BufferedInputStream(new FileInputStream(args[1]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open input file: " + args[1], null);
System.exit(1);
}
// And then the output file
try {
out = new BufferedOutputStream(new FileOutputStream(args[2]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open output file: " + args[2], e);
System.exit(1);
}
// Create a PBKDF2 secret key factory
String algorithm = "PBKDF2WithHmacSHA256";
try {
kf = SecretKeyFactory.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
printErrorMessage("Specified algorithm could not be found: " + algorithm , e);
System.exit(1);
}
// Set up a KeySpec for password-based key generation of a 128-bit key
ks = new PBEKeySpec(args[3].toCharArray(),salt,4096, 128);
// Now run the passphrase through PBKDF2 to get the key
try {
key = kf.generateSecret(ks);
} catch (InvalidKeySpecException e) {
printErrorMessage("The key spec provided is invalid: " + keyspec, e);
System.exit(1);
}
// Get the byte encoded key value as a byte array
byte[] aeskey = key.getEncoded();
// Now generate a Cipher object for AES encryption in ECBC mode with PKCS #5 padding
// Use ECB for the first task, then switch to CBC for versions 2 and 3
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
printErrorMessage("No Such Algorithm Exception when creating main cipher", e);
System.exit(2);
} catch (NoSuchPaddingException e) {
printErrorMessage("No Such Padding Exception when creating main cipher",e);
System.exit(2);
}
// Set a variable to indicate whether we're in encrypt or decrypt mode, based upon args[0]
int cipherMode = -1;
char mode = Character.toLowerCase(args[0].charAt(0));
switch (mode) {
case 'e' : cipherMode = Cipher.ENCRYPT_MODE; break;
case 'd' : cipherMode = Cipher.DECRYPT_MODE; break;
default: printUsageMessage(); System.exit(1);
}
// Set up a secret key specification, based on the 16-byte (128-bit) AES key array previously generated
keyspec = new SecretKeySpec(aeskey, "AES");
// Now initialize the cipher in the right mode, with the keyspec and the ivspec
try {
cipher.init(cipherMode, keyspec);
} catch (InvalidKeyException e) {
printErrorMessage("Invalid Key Spec",e); System.exit(2);
}
// Set up some input and output byte array buffers
byte[] inputBuffer = new byte[bufSize];
byte[] outputBuffer = null;
// "Prime the pump" - we've got to read something before we can encrypt it
// and not encrypt anything if we read nothing.
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e1) {
printErrorMessage("Error reading input file " + args[1],e1); System.exit(1);
}
// As long as we've read something, loop around encrypting, writing and reading
// bytesRead will be zero if nothing was read, or -1 on EOF - treat them both the same
while (bytesRead > 0) {
byte[] input = inputBuffer;
// Now encrypt this block
outputBuffer = cipher.update(input);
// Write the generated block to file
try {
out.write(outputBuffer);
} catch (IOException e1) {
printErrorMessage("Error writing to output file " + args[2],e1); System.exit(1);
}
// And read in the next block of the file
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e1) {
printErrorMessage("Error reading input file " + args[1],e1); System.exit(1);
}
}
// Now do the final processing
try {
outputBuffer = cipher.doFinal(outputBuffer);
} catch (IllegalBlockSizeException e2) {
printErrorMessage("Illegal block size encountered while doing final processing: " + outputBuffer.length , e2);
System.exit(1);
} catch (BadPaddingException e2) {
printErrorMessage("Bad Padding found", e2);
System.exit(1);
}
// Write the final block of output
try {
out.write(outputBuffer);
} catch (IOException e1) {
printErrorMessage("Error on final write to output file " + args[2],e1); System.exit(1);
}
// Close the output files
try {
in.close();
out.close();
} catch (IOException e1) {
printErrorMessage("Error closing file", e1);
}
}
}
For convenience I omitted the printErrorMessage() and printUsageMessage() methods.
This here seems to be the problem; I am getting a BadPaddingException and though the code catches that exception I do not know how to handle that exception or what to do with it. I tried removing the System.exit(1) line from my code in final processing but then the output files comes out twice the size of my encrypted file which is 256 bytes regardless of the size of my input files(having size less than 256 bytes). So, if my input file contains:
hello there
And I encrypt it using key as the passphrase I get my output file containing something like this:
9`ÃLå7}
syXÀ¢Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`Èì´^¾Õn¾AXëC~9‹`0‹ó‚±G¸Y·IñåsòQœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoîœ ÙÞç„ò;uîðpoÄQé±uTö/ژͤ
And now when I decrypt this file using the same passphrase key I get something like this:
hello there 9`Ì巽
syXÀ¢Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`Ȭ´^¾ծ¾AX냾9`
How can I get rid of this shit-storm that's trailing my decrypted text?
All helps and suggestions will be appreciated. Thanks.
I get this warning:
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
Any ideas what causes this? Here are my encryption and decryption code. I have looked at a variety of different answers on StackOverflow but I was unable to find one that actually works.
private static Cipher ecipher;
private static Cipher dcipher;
private static SecretKey key;
public static void Menu() {
try {
// generate secret key using DES algorithm
key = KeyGenerator.getInstance("DES").generateKey();
ecipher = Cipher.getInstance("DES");
dcipher = Cipher.getInstance("DES");
// initialize the ciphers with the given key
ecipher.init(Cipher.ENCRYPT_MODE, key);
dcipher.init(Cipher.DECRYPT_MODE, key);
} catch (NoSuchAlgorithmException e) {
System.out.println("No Such Algorithm:" + e.getMessage());
return;
} catch (NoSuchPaddingException e) {
System.out.println("No Such Padding:" + e.getMessage());
return;
} catch (InvalidKeyException e) {
System.out.println("Invalid Key:" + e.getMessage());
return;
}
}
public static String encrypt(String WordToEncrypt) {
Menu();
try {
// encode the string into a sequence of bytes using the named charset
// storing the result into a new byte array.
byte[] utf8 = WordToEncrypt.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
// encode to base64
enc = BASE64EncoderStream.encode(enc);
System.out.println(new String(enc));
return new String(enc);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt(String WordToDecrypt) {
Menu();
try {
// decode with base64 to get bytes
byte[] dec = BASE64DecoderStream.decode(WordToDecrypt.getBytes());
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8, "UTF8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
You call Menu once in the encryption code and once in the decryption code. Since you generate the key randomly for both encryption and decryption, the key will differ and your code will fail.
Don't keep Cipher instances around, preferably not even in fields, but certainly not in class fields. DES is old; too old. Use AES - using DES isn't any easier than AES.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm having an issue with javax.crypto.Cipher during decryption. I have created a GitHub repository that demonstrates my problem.
Basically, I'm encrypting a short string of data, "foobar", and then immediately attempting to decrypt it. When the decryption occurs, cipher.doFinal(encryptedBytes), the result is 0 decrypted bytes. Clearly I'm missing something here, but I don't see it. Do you see my error? If so, what is it?
Here is the encryption routine:
public Optional<EncryptedData> encrypt(String data) {
Optional<EncryptedData> result = Optional.empty();
Optional<Cipher> cipherOptional = this.getEncryptCipher();
if (!cipherOptional.isPresent()) {
return result;
}
Cipher cipher = cipherOptional.get();
byte[] encryptedBytes = null;
try {
encryptedBytes = cipher.doFinal();
} catch (IllegalBlockSizeException e) {
log.error("Bad encryption block size: `{}`", e.getMessage());
log.debug(e.toString());
} catch (BadPaddingException e) {
log.error("Bad encryption padding size: `{}`", e.getMessage());
log.debug(e.toString());
}
if (encryptedBytes != null) {
Base64.Encoder base64 = Base64.getEncoder();
EncryptedData encryptedData = new EncryptedData(
cipher.getIV(),
encryptedBytes
);
result = Optional.of(encryptedData);
}
return result;
}
And the decryption routine:
public Optional<String> decrypt(EncryptedData data) {
Optional<String> result = Optional.empty();
Optional<Cipher> cipherOptional = this.getDecryptCipher(data.getIv());
if (!cipherOptional.isPresent()) {
return result;
}
Cipher cipher = cipherOptional.get();
byte[] decryptedBytes;
try {
decryptedBytes = cipher.doFinal(data.getData());
result = (decryptedBytes.length > 0) ?
Optional.of(new String(decryptedBytes)) : result;
} catch (BadPaddingException e) {
log.error("Bad encryption padding size: `{}`", e.getMessage());
log.debug(e.toString());
} catch (IllegalBlockSizeException e) {
log.error("Bad encryption block size: `{}`", e.getMessage());
log.debug(e.toString());
}
return result;
}
Both of which use the following routine to initialize the cipher:
private Optional<Cipher> getCipher(int mode, byte[] iv) {
// where mode is either 1 -> encrypt or 2 -> decrypt
Optional<Cipher> result = Optional.empty();
Cipher cipher = null;
try {
cipher = Cipher.getInstance(this.algorithmMode);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
AlgorithmParameters parameters =
AlgorithmParameters.getInstance(this.algorithm);
parameters.init(ivParameterSpec);
cipher.init(mode, this.key, parameters);
result = Optional.of(cipher);
} catch (NoSuchAlgorithmException e) {
log.error("Could not find cipher mode: `{}`", e.getMessage());
log.debug(e.toString());
} catch (NoSuchPaddingException e) {
log.error("Could not find padding type: `{}`", e.getMessage());
log.debug(e.toString());
} catch (InvalidKeyException e) {
log.error("Encryption key is invalid: `{}`", e.getMessage());
log.debug(e.toString());
} catch (InvalidParameterSpecException e) {
log.error("Algorithm parameter spec invalid: `{}`", e.getMessage());
log.debug(e.toString());
} catch (InvalidAlgorithmParameterException e) {
log.error("Algorithm parameters invalid: `{}`", e.getMessage());
log.debug(e.toString());
}
return result;
}
The error ends up being at line 38 in the actual code.
Do I miss something or do you ever supply the actual bytes for encryption. Or do you encrypt 0 bytes?
Don't see any cypher.update(byte[]) or cypher.final(byte[]) in the encryption function
You're not calling Cipher.doFinal(byte[]). You're calling Cipher.doFinal().
Try doing what you think you're doing.
I searched over the internet for a Triple Des Algorithm implementation for Java.
I found a lot of solutions and choosed one (The one with better documentation for me).
I tested and works Ok.
Then, I searched for an AES Algorithm implementation for Java. And found a good ones. Really similar to Triple Des Algorithm implementation, but not exactly the same.
So I think, what appends if I use the AES Algorithm implementation but changing the Cipher instance parameter from "AES" to "DESede"?
I made the change, tested the code and worked ok. But, the String returned it is different from the String returned on my previous Triple Des Algorithm implementation.
So, like the title say, how do I know if I'm using the right version of Triple Des Algorithm implementation?
This is the first implementation:
public String encrypt(SecretKey key, String stringIn){
String outString = "";
if (stringIn.isEmpty() || stringIn.toUpperCase().equals("NULL")){
return "";
}
try {
if (key == null)
key = this.key;
InputStream in = new ByteArrayInputStream(stringIn.getBytes("UTF-8"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Create and initialize the encryption engine
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, key);
// Create a special output stream to do the work for us
CipherOutputStream cos = new CipherOutputStream(out, cipher);
// Read from the input and write to the encrypting output stream
byte[] buffer = new byte[2048];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
cos.write(buffer, 0, bytesRead);
}
cos.close();
// For extra security, don't leave any plaintext hanging around memory.
java.util.Arrays.fill(buffer, (byte) 0);
outString = out.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
return outString;
}
}
This is the second one:
public String encrypt(SecretKey key, String stringIn){
String outString = "";
if (stringIn.isEmpty() || stringIn.toUpperCase().equals("NULL")){
return "";
}
try {
if (key == null)
key = this.key;
Cipher ecipher = Cipher.getInstance("DESede");
ecipher.init(Cipher.ENCRYPT_MODE, key);
byte[] bytes = stringIn.getBytes("UTF8");
byte[] encVal = ecipher.doFinal(bytes);
outString = new sun.misc.BASE64Encoder().encode(encVal);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
return outString;
}
}
This is the Test case:
String In: 6985475896580019
String Returned when I Encripted with First code: Kœ¼i …€‡ä«‘]<žéù âpU
String Returned when I Encripted with Second code: w1ujopasjH6ccFKgUtOgansFNBtxbWe8YwDhso2pZN8=
Sorry for my poor english.
Thanks for your help
cipher.init(mode,key) generates a random IV. This is actually the most secure way of using it; you should use .getIV() and return that with the encrypted text (which is also automatic; Java tacks it onto the first few bytes of the cryptostream, which is how they decrypt OK). Different IV changes the result just as much as a different key, but it doesn't need to be secret, it's just to make sure identical things don't encrypt identically.
To force an IV for comparing algorithms, or for decrypting with a known one not included, use cipher.init(mode,key,new IvParameterSpec(iv))
while converting a .net code of decryption to java I got an exception
Exception in thread "main" java.lang.IllegalArgumentException: Missing argument
at javax.crypto.spec.SecretKeySpec.<init>(DashoA13*..)
at com.motorola.gst.DecryptTest3.Decrypt(DecryptTest3.java:90)
at com.motorola.gst.DecryptTest3.main(DecryptTest3.java:36)
well I'm trying it for the first time both decryption and converting a .net code to java
here is the .net code that I'm trying to convert
private static string Decrypt(string encryptedText, string completeEncodedKey, int keySize)
{
RijndaelManaged aesEncryption = new RijndaelManaged();
aesEncryption.KeySize = keySize;
aesEncryption.BlockSize = 128;
aesEncryption.Mode = CipherMode.CBC;
aesEncryption.Padding = PaddingMode.PKCS7;
aesEncryption.IV = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(completeEncodedKey)).Split(',')[0]);
aesEncryption.Key = Convert.FromBase64String(ASCIIEncoding.UTF8.GetString(Convert.FromBase64String(completeEncodedKey)).Split(',')[1]);
ICryptoTransform decrypto = aesEncryption.CreateDecryptor();
byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length);
return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length));
}
I went through many posts and found Decrypting bytes encrypted by .NET's RijndaelManaged using Java is more related to my case.
I followed these and wrote my decrypt function as ::
private static String Decrypt(String encryptedText, String completeEncodedKey,int keySize) {
//get completeEncodedKey in bytes and then to string
String decodedcompleteEncodedKey = StringUtils.newStringUtf8(Base64.decodeBase64(completeEncodedKey));
System.out.println("Decoded completeEncodedKey Key :: "+decodedcompleteEncodedKey);
int indexComma = decodedcompleteEncodedKey.indexOf(',');
System.out.println("COmma Index :: "+indexComma);
String IV = decodedcompleteEncodedKey.substring(0, indexComma);
String Key = decodedcompleteEncodedKey.substring(indexComma+1,decodedcompleteEncodedKey.length());
System.out.println("IV::: "+IV);
System.out.println("Key::: "+Key);
byte[] sessionKey = null;
byte[] iv = null ;
byte[] plaintext = encryptedText.getBytes();
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext);
} catch (IllegalBlockSizeException e) {
System.out.println("IllegalBlockSizeException");
e.printStackTrace();
} catch (BadPaddingException e) {
System.out.println("BadPaddingException");
e.printStackTrace();
} catch (InvalidKeyException e) {
System.out.println("InvalidKeyException");
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
System.out.println("InvalidAlgorithmParameterException");
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
System.out.println("NoSuchAlgorithmException");
e.printStackTrace();
} catch (NoSuchPaddingException e) {
System.out.println("NoSuchPaddingException");
e.printStackTrace();
}
return null;
}
but now I'm getting Exception in thread "main" java.lang.IllegalArgumentException: Missing argument.
can anyone help me getting these errors fixed.
any help would be appreciated.
thanks!!
For me the problem was calling new SecretKeySpec(sessionKey, "AES") with sessionKey = null.