web-dev-qa-db-ja.com

Java AES:インストールされているプロバイダーはこのキーをサポートしていません:javax.crypto.spec.SecretKeySpec

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"

何か案は?

12
Cody S

コードをさまざまな方法で実行しました。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は何も教えてくれません(少なくとも私にとってはそうではなく、この特定のエラーを再現することもできませんでした)。

7

このエラーは、JCE(Java Cryptography Extension)をインストールする必要があることを示している可能性があります。

このファイル(または新しいバージョン)をダウンロードし、jarをJDK_FOLDER/jre/lib/securityにコピーします http://www.Oracle.com/technetwork/pt/Java/javase/downloads/jce-6-download-429243 .html

6

このエラーは、SecretKeySpecコンストラクターに誤ったキーを指定したときに発生します。

1
Ahmed Ashour