Instalé y configuré SoftHSM con éxito en CentOS. Para verificar si puedo comunicarme con SoftHSM mediante programación, escribí un programa Java que interactúa con el token de software y realiza el cifrado y descifrado de una cadena de entrada. Sin embargo, el programa pudo cifrar la entrada con éxito, pero no logra descifrarla. El método de descifrado falla con un error:Excepción de tamaño de bloque ilegal:CKR_ENCRYPTED_DATA_LEN_RANGE.
Aquí está el código parcial.
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 { } }
Error de salida:
Entonces, ¿cómo lo hice funcionar? Aquí está la solución.
Cómo arreglar el Excepción de tamaño de bloque ilegal:¿error CKR_ENCRYPTED_DATA_LEN_RANGE al acceder a SoftHSM a través del código Java?
Como estoy encriptando la cadena con el algoritmo AES, el retorno esperado es una matriz de bytes. Entonces, convertir esos bytes directamente en una cadena como se muestra a continuación estaba causando el problema.
encryptedtext = outputBytes.toString();
En la línea de código anterior, outputBytes
es de tipo bytes []
y convertirlo a cadena directamente fue el problema.
Para solucionar este problema, necesitamos usar Base64
en lugar de convertirlo directamente en una cadena.
byte[] cipherText = cipher.doFinal(inputtext.getBytes("utf-8")); encryptedText = java.util.Base64.getEncoder().encodeToString(cipherText);
Las líneas anteriores se reescribieron ligeramente para codificar el cipherText
usando Base64
y almacenar lo mismo en encryptedText
.
De manera similar, mientras desciframos, necesitamos convertir el Base64
cadena de nuevo en una matriz de bytes antes de descifrar la matriz de bytes.
byte[] deciphered = cipher.doFinal(java.util.Base64.getDecoder().decode(encryptedText));
La línea de código anterior sugiere que necesitamos realizar Base64
decodificar y pasarlo como argumento al método de descifrado.
¡Eso es todo! Aquí está el código completo como referencia.
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 { } }
Gracias a esta respuesta de Stackflow que me ayudó a solucionar el problema.
Finalmente, la captura de pantalla de la salida exitosa.