0

cxf と sprint を使用して、発信 SOAP ヘッダーを暗号化しようとしています。春の構成の結果として、クライアントに outInterceptor を使用することになります。

'

 <bean id="encryptOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">

  <constructor-arg>
     <map>
        <entry key="action" value="UsernameToken Timestamp Encrypt" />
        <entry key="passwordCallbackRef" value-ref="passwordCallback" />
        <entry key="user" value="mykey" />
        <entry key="encryptionPropFile" value="keystore.properties" />

     </map>
  </constructor-arg>
  </bean>

`

そして、この結果として、それは呼び出すことになります

`org.apache.ws.security.message.WSSecEncryptedKey.prepareInternal()`  

メソッド、私はデバッガーをそのソースにステップスルーしました:

try {
        **cipher.init(Cipher.ENCRYPT_MODE, remoteCert);**
    } catch (InvalidKeyException e) {
        throw new WSSecurityException(
            WSSecurityException.FAILED_ENCRYPTION, null, null, e
        );
    }

その時点で、「無効なキーの使用法」例外がスローされます。

私は手動で証明書を読んでいるテストJavaクラスを書いてしまい、Cipher.ENCRYPT_MODEパラメータでCipherを初期化しようとしましたが、結局同じ例外が発生しました.hereは特定のスニペットです:

        InputStream inStream = new FileInputStream("our_cert.cer");
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert =(X509Certificate)cf.generateCertificate(inStream);
        inStream.close();

        // Read the public key from certificate file
        RSAPublicKey pubkey = (RSAPublicKey) cert.getPublicKey();
        cipher.init(Cipher. ENCRYPT_MODE, certif);  // it breaks at this point

最後の行を次のように置き換えました

cipher.init(Cipher. PRIVATE_KEY, certif);

そして無事通過。

ただし、それは正しいキーの使用法ではないと思います。また、ENCRYPT_MODEも機能するはずだと思います。

証明書のキー使用法セクションを見ると、キー使用法が次のように定義されていることに気付きました。

ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
  DigitalSignature
  Key_Encipherment
]

他のクリティカル セクションはありません。

それが動作する方法から、Cipher.init(..)DigitalSignature (つまりCipher. PRIVATE_KEY ) に対してのみ機能し、 Key_Encipherment (つまりCipher. ENCRYPT_MODE ) に対しては機能しないようです。

私の質問は、その証明書に対してKeyUsageが正しく定義されていない可能性があるということです。私は暗号化の専門家ではありませんが、私が読んでいた掲示板では、keyUsage が重要な場合は DATA_ENCIPHERMENT も使用する必要があるかもしれないと示唆されて ました…</p>

ご協力ありがとうございました!

4

2 に答える 2

1

ソース コードを調べてみると、その例外をスローする条件が 2 つあります。1 つは発生しないエラーで、もう 1 つは問題の証明書が問題の操作をサポートしていることを確認するためのチェックです。

if (critSet != null && !critSet.isEmpty()
    && critSet.contains(KEY_USAGE_EXTENSION_OID)) {
  boolean[] keyUsageInfo = cert.getKeyUsage();
  // keyUsageInfo[2] is for keyEncipherment;
  // keyUsageInfo[3] is for dataEncipherment.
  if ((keyUsageInfo != null) &&
      (((opmode == Cipher.ENCRYPT_MODE) &&
      (keyUsageInfo.length > 3) &&
      (keyUsageInfo[3] == false)) ||
      ((opmode == Cipher.WRAP_MODE) &&
      (keyUsageInfo.length > 2) &&
      (keyUsageInfo[2] == false)))) {
      throw new InvalidKeyException("Wrong key usage");
    }
}

これは、暗号化に有効でない証明書を使用していることを示しています。おそらく、暗号化に公開鍵証明書を使用しようとしましたか?

コードは、PRIVATE_KEY のように常に無効な opmode をチェックしていないように見えますが、ENCRYPT_MODE のように無効な場合があるため、おそらくテスト コードで問題ありません。

于 2012-07-15T05:53:12.697 に答える
1

最近これに遭遇しました。公開鍵証明書が正しく作成されていれば、それを使用して暗号化できます。証明書には、基本的にデータ暗号化ビットが有効になっている「b0」(10110000) に設定されたキー使用オブジェクト ID (ObjectId: 2.5.29.15 Criticality=true) が必要です。そうしないと、間違ったキーの使用エラーが発生します。CA が発行した証明書はすべて、キー使用の重要度が true になります。自己署名証明書 (dev/sandbox 環境など) では、重要度が true に設定されていないため、もちろん信頼するように設定されていれば機能します。サーバーからの公開鍵証明書を使用しようとしましたが、このエラーに苦労していました。その後、IT 部門がデータ暗号化用の適切な公開鍵証明書を受け取り、それが機能し始めました。

于 2013-07-11T15:00:09.660 に答える