6

試したすべてのSunJDKで正常に動作するJCEテストがありますが、さまざまなIBM J9 JDK(1.6.0ビルドpwi3260sr8-20100409_01(SR8)など)では失敗します。以下の例外は、暗号が暗号化モードで初期化された場合に発生します。IBM JCEが独自の秘密鍵を使用できないのはなぜですか?コードに何かが欠けていますか?

  public void testBasicKeyGeneration() throws NoSuchAlgorithmException, 
      NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, 
      BadPaddingException, NoSuchProviderException, SignatureException {
      KeyPairGenerator generator = KeyPairGenerator.getInstance( "RSA" );
      generator.initialize( 2048 );
      KeyPair pair = generator.generateKeyPair();

      String data1 = "123456789012345678901234567890123456789012345678901234567890";
      Cipher cipher = Cipher.getInstance( "RSA" );
      cipher.init( Cipher.ENCRYPT_MODE, pair.getPrivate() );
      byte[] encrypted = cipher.doFinal( data1.getBytes() );

      cipher.init( Cipher.DECRYPT_MODE, pair.getPublic() );
      byte[] decrypted = cipher.doFinal( encrypted );
      String data2 = new String( decrypted );
      assertEquals( "en/decryption failed", data1, data2 );
  }

スタックトレースは次のとおりです。

java.security.InvalidKeyException: Private key cannot be used to encrypt.
at com.ibm.crypto.provider.RSA.engineInit(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.a(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at javax.crypto.Cipher.init(Unknown Source)
at test.Test.testBasicKeyGeneration(LicenseHelperTest.java:56)
4

6 に答える 6

9

解決策があります。http://www-01.ibm.com/support/docview.wss?uid=swg1IV18625を参照してください。

プロパティで

-Dcom.ibm.crypto.provider.DoRSATypeChecking=false

秘密鍵を使用してデータを暗号化できます。

于 2014-08-12T12:37:00.513 に答える
5

これは確かにはわかりませんが、JCEには、暗号化を公開鍵に、復号化を秘密鍵に制限するポリシーが組み込まれていると思います。

サンプルコードでは、暗号化は秘密鍵を使用して行われました。これには、復号化するための公開鍵が必要になります。つまり、公開鍵を持っている人は誰でも、エンコードされたデータにアクセスできます。これには用途がありますが、受け入れられているパターンではなく、IBMの実装により、公に読み取り可能な暗号化データを誤って作成することからユーザーを「保護」している可能性があります。

これらが逆にされたときにそれが適切にテストされたという事実は私の疑いを確認する傾向がありますが、私はまだ多くを述べている公式文書を見つけていません。

于 2011-02-02T17:39:44.857 に答える
3

IBMは、秘密鍵を暗号化に使用したり、公開鍵を復号化に使用したりすることはできないと主張しているため、この人為的な制限を機能と見なすか、誰かがここで深刻な混乱を招きます。

この問題を回避する方法は次のとおりです。

RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) ks.getKey(keyAlias, ksPassword.trim().toCharArray());
RSAPublicKeySpec spec = new RSAPublicKeySpec(privateKey.getModulus(),privateKey.getPrivateExponent());
Key fakePublicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
encryptCipher.init(Cipher.ENCRYPT_MODE, fakePublicKey);

基本的に、私は秘密鍵の暗号素材を使用して公開鍵オブジェクトを作成しました。「公開鍵は復号化に使用できません」という例外を回避したい場合は、逆の操作を行い、公開鍵の暗号素材を使用して秘密鍵オブジェクトを作成し、公開鍵を使用して復号化する必要があります。

于 2011-11-12T05:56:08.967 に答える
3

私は最近同じ問題に遭遇しました。これは、弾力がある城の実装を使用し、この行をjava.securityファイルに追加することで最終的に解決されました

security.provider.1 = org.bouncycastle.jce.provider.BouncyCastleProvider

于 2014-03-31T13:24:37.787 に答える
2

@ T.Robは、秘密鍵を使用した暗号化を間違えた可能性があるとコメントしました。「全員」が公開鍵を知っていれば、誰でもあなたのファイルを復号化できます。したがって、IBMのJCEの振る舞いは、この間違いから人々を保護しています。

その論理がわかります。

ただし、実際に秘密鍵で暗号化する必要がある場合があります。たとえば、公開された公開鍵に対応する秘密鍵を知っていることを証明する必要があるプロトコルの一部として。

これが本当にやりたいことである場合は、おそらく最近のSun JCE実装(古いSun JCEはRSAを実装していません)またはBouncyCastleを使用する必要があります。

于 2011-02-02T05:22:59.677 に答える
2

@Stephen C / @FelixM:IBMは、RSA暗号化がどのように機能し、どのように使用されるのかについて完全に無知なようです。基本的に、両方の操作(暗号化/復号化)が公開鍵と秘密鍵で使用可能である必要があります。

SSL / TLSハンドシェイクでプリマスターシークレットのクライアント側部分を送信するには、公開鍵で暗号化する必要があります。サーバーは秘密鍵で復号化する必要があります。ただし、ECDHE_RSAのようなものをネゴシエートする場合、サーバーはハンドシェイクの一部を秘密鍵で署名する必要があります。これは、秘密鍵で暗号化します。逆に、クライアントは、署名のハッシュ値を検証するために、サーバーの証明書からの公開鍵を使用して復号化する必要があります。(メッセージの信憑性を証明する)

したがって、最新のIBM JDK 7でECDHE_RSA(サーバー側)を実行しようとすると、次のようになります。

java.security.InvalidKeyException: Private key cannot be used to encrypt.
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
   at java.lang.Thread.run(Thread.java:777)
   at com.ibm.crypto.provider.RSASSL.engineInit(Unknown Source)
   at javax.crypto.Cipher.init(Unknown Source)
   at javax.crypto.Cipher.init(Unknown Source)
   at java.security.Signature$CipherAdapter.engineInitSign(Signature.java:1239)
   at java.security.Signature$Delegate.init(Signature.java:1116)
   at java.security.Signature$Delegate.chooseProvider(Signature.java:1076)
   at java.security.Signature$Delegate.engineInitSign(Signature.java:1140)
   at java.security.Signature.initSign(Signature.java:522)
   at net.vx4.lib.tls.core.TLSSignature.createSignature(TLSSignature.java:120)

ご覧のとおり、「Signature」を使用して「initSign」を呼び出しています。これには、実際にPrivateKeyが必要です。これは、IBMがこの事実について無知であり、明らかに有効な回帰テストさえ持っていないことを証明しています。

別の暗号プロバイダーを使用し、気が変わるまでIBMを信じないでください。

よろしく、クリスチャン

于 2013-02-20T17:34:19.413 に答える