128ビットのAES暗号化を設定しようとしていますが、Cipher.initで例外がスローされます。
No installed provider supports this key: javax.crypto.spec.SecretKeySpec
次のコードを使用して、クライアント側でキーを生成しています。
private KeyGenerator kgen;
try {
kgen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
kgen.init(128);
}
SecretKey skey = kgen.generateKey();
次に、このキーはヘッダーとしてサーバーに渡されます。この関数を使用してBase64でエンコードされます。
public String secretKeyToString(SecretKey s) {
Base64 b64 = new Base64();
byte[] bytes = b64.encodeBase64(s.getEncoded());
return new String(bytes);
}
サーバーはヘッダーをプルし、
protected static byte[] encrypt(byte[] data, String base64encodedKey) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher;
try {
cipher = Cipher.getInstance("AES");
} catch (NoSuchAlgorithmException ex) {
//log error
} catch (NoSuchPaddingException ex) {
//log error
}
SecretKey key = b64EncodedStringToSecretKey(base64encodedKey);
cipher.init(Cipher.ENCRYPT_MODE, key); //THIS IS WHERE IT FAILS
data = cipher.doFinal(data);
return data;
}
private static SecretKey b64EncodedStringToSecretKey(String base64encodedKey) {
SecretKey key = null;
try {
byte[] temp = Base64.decodeBase64(base64encodedKey.getBytes());
key = new SecretKeySpec(temp, SYMMETRIC_ALGORITHM);
} catch (Exception e) {
// Do nothing
}
return key;
}
これをデバッグするために、クライアント側でのキー生成の後で、サーバー側でのcipher.initの直前にブレークポイントを設定しました。 Netbeansによると、SecretKeysを構成するバイトは同一であり、長さは16バイトです(実際、私が知る限り、オブジェクトは同一です)。
私は無制限の強度のJCEのものを知っていますが、128ビットAESにそれが必要だったという印象を受けていません。
クライアント側:Javaバージョン "1.6.0_26"
サーバー側:Javaバージョン "1.6.0_20"
何か案は?
コードをさまざまな方法で実行しました。Java 1. {5,6,7}(AESを使用);さまざまなBase64コーデック(Apache Commons Codec、DatatypeConverted、Base64);さまざま文字セット;異なるJVM間(ソケット経由)…役に立たない。エラーは発生しなかった。
問題を絞り込むために、次のコードを両方終了で実行できますか?
static {
System.out.println(System.getProperty("Java.version"));
for (Provider provider : Security.getProviders())
System.out.println(provider);
}
public static void main(String[] args) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
}
(使用しているJDKのバージョンなどについてはすでに説明していると思いますが、問題はありません。)
クライアントからサーバーに(またはその逆に)転送するときにキーが破損しないことを考えると、次の場合:
いずれにせよ、エラーがスローされた場合は、wholeスタックトレースをどこかに投稿してください。エラー No installed provider supports this key: javax.crypto.spec.SecretKeySpec
は何も教えてくれません(少なくとも私にとってはそうではなく、この特定のエラーを再現することもできませんでした)。
このエラーは、JCE(Java Cryptography Extension)をインストールする必要があることを示している可能性があります。
このファイル(または新しいバージョン)をダウンロードし、jarをJDK_FOLDER/jre/lib/securityにコピーします http://www.Oracle.com/technetwork/pt/Java/javase/downloads/jce-6-download-429243 .html
このエラーは、SecretKeySpec
コンストラクターに誤ったキーを指定したときに発生します。