Illegal block size exception – CKR_ENCRYPTED_DATA_LEN_RANGE [SoftHSM]

Updated on September 29, 2021

I have installed and configured SoftHSM successfully on CentOS. In order to check if I can communicate with SoftHSM programmatically, I wrote a Java program that interacts with the soft token and performs encryption and decryption of an input string.  However, the program was able to encrypt the input successfully but fails to decrypt it. The decryption method fails with an error – Illegal block size exception – CKR_ENCRYPTED_DATA_LEN_RANGE. 

Here’s the partial code.

String pkcs11ConfigData = "softhsm.cfg";
Provider pkcs11Provider = Security.getProvider("SunPKCS11");
pkcs11Provider = pkcs11Provider.configure(pkcs11ConfigData);

if (-1 == Security.addProvider(pkcs11Provider)) {
throw new RuntimeException("could not add security provider");
} else {
System.out.println("provider initialized !!!");
}

Security.addProvider(pkcs11Provider);

char[] pin = "abcdef123".toCharArray();
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance("PKCS11", pkcs11Provider);
keyStore.load(null, pin);
SecretKeySpec secretKeySpec = new SecretKeySpec("0123456789ABCDEF".getBytes(), 0, 16, "AES");
Key key = new SecretKeySpec(secretKeySpec.getEncoded(), 0, 16, "AES");
keyStore.setKeyEntry("AA", key, "abcdef123".toCharArray(), null);
keyStore.store(null);
SecretKey key1 = (SecretKey) keyStore.getKey("AA", "abcdef123".toCharArray());
System.out.println("the algorithm: "+key1.getAlgorithm()+", the key: "+key1.toString()+", format: "+key1.serialVersionUID);

doCrypto(Cipher.ENCRYPT_MODE, key1, inputtext);

doCrypto(Cipher.DECRYPT_MODE, key1, encryptedtext);

} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

private static void doCrypto(int cipherMode, Key key, String inputtext) throws Exception {
Key secretKey = key;
Cipher cipher;
try {
cipher = Cipher.getInstance(TRANSFORMATION);

cipher.init(cipherMode, secretKey);
byte[] inputBytes = inputtext.getBytes();
byte[] outputBytes;
outputBytes = cipher.doFinal(inputBytes);
if(cipherMode == Cipher.ENCRYPT_MODE) {
encryptedtext = outputBytes.toString();
System.out.println("==========================================");
System.out.println("encrypted text: "+outputBytes.toString());
System.out.println("==========================================");
}
if(cipherMode == Cipher.DECRYPT_MODE) {
System.out.println("*****************************************");
System.out.println("decrypted text: "+outputBytes.toString());
System.out.println("*****************************************");
}

} catch (NoSuchAlgorithmException e) {
System.out.println("No such algorithm exception");
e.printStackTrace();
} catch (NoSuchPaddingException e) {
System.out.println("No such padding exception");
e.printStackTrace();
} catch (InvalidKeyException e) {
System.out.println("Invalid key exception");
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
System.out.println("Illegal block size exception");
e.printStackTrace();
} catch (BadPaddingException e) {
System.out.println("Bad padding exception");
e.printStackTrace();
} finally {

}
}

Output error:

CKR_ENCRYPTED_DATA_LEN_RANGE

So how did I make it work? Here’s the solution.

How to fix the Illegal block size exception – CKR_ENCRYPTED_DATA_LEN_RANGE error while accessing SoftHSM via Java code?

As I’m encrypting the string with the AES  algorithm, the expected return is an array of bytes.  So converting those bytes directly to a string as shown below was causing the issue.

encryptedtext = outputBytes.toString();

In the above line of code, the outputBytes is of type bytes [] and converting it to string directly was the issue.

To fix this issue, we need to use Base64 instead of directly converting it to a string.

byte[] cipherText = cipher.doFinal(inputtext.getBytes("utf-8"));
encryptedText = java.util.Base64.getEncoder().encodeToString(cipherText);

The above lines are slightly rewritten to encode the cipherText using Base64 and store the same in encryptedText.

Similarly while decrypting, we need to convert the Base64 string back into a byte array before decrypting the byte array.

byte[] deciphered = cipher.doFinal(java.util.Base64.getDecoder().decode(encryptedText));

The above line of code suggests that we need to perform Base64 decode and pass it as an argument to the decryption method.

That’s it! Here’s the complete code for reference.

private static String performEncryption(Key secretKey, String inputtext) throws Exception {
String encryptedText = new String();
Cipher cipher;
try {
cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherText = cipher.doFinal(inputtext.getBytes("utf-8"));
encryptedText = java.util.Base64.getEncoder().encodeToString(cipherText);
} catch (NoSuchAlgorithmException e) {
System.out.println("No such algorithm exception");
e.printStackTrace();
} catch (NoSuchPaddingException e) {
System.out.println("No such padding exception");
e.printStackTrace();
} catch (InvalidKeyException e) {
System.out.println("Invalid key exception");
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
System.out.println("Illegal block size exception");
e.printStackTrace();
} catch (BadPaddingException e) {
System.out.println("Bad padding exception");
e.printStackTrace();
} finally {

}
return encryptedText;
}

private static void performDecryption(Key key, String encryptedString) throws Exception {
Key secretKey = key;
Cipher cipher;
try {
cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] deciphered = cipher.doFinal(java.util.Base64.getDecoder().decode(encryptedString));
System.out.println("decrypted text: "+new String(deciphered));
} catch (NoSuchAlgorithmException e) {
System.out.println("No such algorithm exception");
e.printStackTrace();
} catch (NoSuchPaddingException e) {
System.out.println("No such padding exception");
e.printStackTrace();
} catch (InvalidKeyException e) {
System.out.println("Invalid key exception");
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
System.out.println("Illegal block size exception");
e.printStackTrace();
} catch (BadPaddingException e) {
System.out.println("Bad padding exception");
e.printStackTrace();
} finally {

}
}

Thanks to this answer from Stackflow that helped me fix the issue.

Finally, the screenshot of the successful output.

SoftHSM access

Was this article helpful?

Related Articles

Leave a Comment