Ho installato e configurato correttamente SoftHSM su CentOS. Per verificare se posso comunicare con SoftHSM a livello di codice, ho scritto un programma Java che interagisce con il soft token ed esegue la crittografia e la decrittografia di una stringa di input. Tuttavia, il programma è stato in grado di crittografare correttamente l'input ma non riesce a decrittografarlo. Il metodo di decrittografia non riesce con un errore – Eccezione dimensione blocco non valida – CKR_ENCRYPTED_DATA_LEN_RANGE.
Ecco il codice parziale.
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 { } }
Errore di output:
Allora come ho fatto a farlo funzionare? Ecco la soluzione.
Come risolvere il Eccezione relativa alla dimensione del blocco illegale:errore CKR_ENCRYPTED_DATA_LEN_RANGE durante l'accesso a SoftHSM tramite codice Java?
Poiché sto crittografando la stringa con l'algoritmo AES, il ritorno previsto è un array di byte. Quindi la conversione di quei byte direttamente in una stringa come mostrato di seguito stava causando il problema.
encryptedtext = outputBytes.toString();
Nella riga di codice sopra, outputBytes
è di tipo bytes []
e convertirlo direttamente in stringa era il problema.
Per risolvere questo problema, dobbiamo utilizzare Base64
invece di convertirlo direttamente in una stringa.
byte[] cipherText = cipher.doFinal(inputtext.getBytes("utf-8")); encryptedText = java.util.Base64.getEncoder().encodeToString(cipherText);
Le righe precedenti sono leggermente riscritte per codificare il cipherText
utilizzando Base64
e salva lo stesso in encryptedText
.
Allo stesso modo, durante la decrittazione, dobbiamo convertire il Base64
stringa in un array di byte prima di decrittografare l'array di byte.
byte[] deciphered = cipher.doFinal(java.util.Base64.getDecoder().decode(encryptedText));
La riga di codice sopra suggerisce che dobbiamo eseguire Base64
decodificalo e passalo come argomento al metodo di decrittazione.
Questo è tutto! Ecco il codice completo per riferimento.
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 { } }
Grazie a questa risposta di Stackflow che mi ha aiutato a risolvere il problema.
Infine, lo screenshot dell'output riuscito.