J'ai installé et configuré SoftHSM avec succès sur CentOS. Afin de vérifier si je peux communiquer avec SoftHSM par programme, j'ai écrit un programme Java qui interagit avec le jeton logiciel et effectue le cryptage et le décryptage d'une chaîne d'entrée. Cependant, le programme a réussi à chiffrer l'entrée mais ne parvient pas à la déchiffrer. La méthode de déchiffrement échoue avec une erreur - Exception de taille de bloc illégale - CKR_ENCRYPTED_DATA_LEN_RANGE.
Voici le code partiel.
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 { } }
Erreur de sortie :
Alors, comment ai-je réussi à le faire fonctionner ? Voici la solution.
Comment réparer le Exception de taille de bloc illégale - Erreur CKR_ENCRYPTED_DATA_LEN_RANGE lors de l'accès à SoftHSM via le code Java ?
Comme je chiffre la chaîne avec l'algorithme AES, le retour attendu est un tableau d'octets. Donc, la conversion directe de ces octets en une chaîne comme indiqué ci-dessous était à l'origine du problème.
encryptedtext = outputBytes.toString();
Dans la ligne de code ci-dessus, le outputBytes
est de type bytes []
et le convertir directement en chaîne était le problème.
Pour résoudre ce problème, nous devons utiliser Base64
au lieu de le convertir directement en chaîne.
byte[] cipherText = cipher.doFinal(inputtext.getBytes("utf-8")); encryptedText = java.util.Base64.getEncoder().encodeToString(cipherText);
Les lignes ci-dessus sont légèrement réécrites pour encoder le cipherText
en utilisant Base64
et stocker le même dans encryptedText
.
De même lors du décryptage, nous devons convertir le Base64
chaîne dans un tableau d'octets avant de déchiffrer le tableau d'octets.
byte[] deciphered = cipher.doFinal(java.util.Base64.getDecoder().decode(encryptedText));
La ligne de code ci-dessus suggère que nous devons exécuter Base64
décode et passe-le comme argument à la méthode de déchiffrement.
C'est ça! Voici le code complet pour référence.
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 { } }
Merci à cette réponse de Stackflow qui m'a aidé à résoudre le problème.
Enfin, la capture d'écran de la sortie réussie.