CentOSにSoftHSMを正常にインストールして構成しました。 SoftHSMとプログラムで通信できるかどうかを確認するために、ソフトトークンと対話し、入力文字列の暗号化と復号化を実行するJavaプログラムを作成しました。ただし、プログラムは入力を正常に暗号化できましたが、復号化できませんでした。復号化メソッドが次のエラーで失敗します– 不正なブロックサイズの例外–CKR_ENCRYPTED_DATA_LEN_RANGE。
これが部分的なコードです。
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 { } }
出力エラー:
では、どうやってそれを機能させたのですか?これが解決策です。
修正方法不正なブロックサイズの例外– Javaコードを介してSoftHSMにアクセスしているときにCKR_ENCRYPTED_DATA_LEN_RANGEエラーが発生しましたか?
AESアルゴリズムを使用して文字列を暗号化しているため、期待される戻り値はバイトの配列です。したがって、以下に示すように、これらのバイトを直接文字列に変換すると、問題が発生していました。
encryptedtext = outputBytes.toString();
上記のコード行で、outputBytes
タイプはbytes []
です それを直接文字列に変換することが問題でした。
この問題を修正するには、Base64
を使用する必要があります 文字列に直接変換する代わりに。
byte[] cipherText = cipher.doFinal(inputtext.getBytes("utf-8")); encryptedText = java.util.Base64.getEncoder().encodeToString(cipherText);
上記の行は、cipherText
をエンコードするために少し書き直されています Base64
を使用する 同じものをencryptedText
に保存します 。
同様に、復号化中に、Base64
を変換する必要があります バイト配列を復号化する前に、文字列をバイト配列に戻します。
byte[] deciphered = cipher.doFinal(java.util.Base64.getDecoder().decode(encryptedText));
上記のコード行は、Base64
を実行する必要があることを示しています。 デコードして、引数として復号化メソッドに渡します。
それでおしまい!参照用の完全なコードは次のとおりです。
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 { } }
問題の修正に役立ったStackflowからのこの回答に感謝します。
最後に、成功した出力のスクリーンショット。