2012-07-15 291 views
0

我想使用cxf和sprint加密傳出的SOAP頭。正如我configutaion的春天有個結果,我最終使用outInterceptor爲我的客戶:證書KeyUsage和密碼加密模式

'

<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參數初始化密碼, 和我最終得到相同exception.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(即密碼。PRIVATE_KEY),但不是Key_Encipherment工程(即密碼。ENCRYPT_MODE)。

所以我的問題是,有可能是KeyUsage沒有正確定義該證書。 我不是專家密碼學,但有些留言板我讀認爲,如果執行keyUsage是至關重要的,它可能需要使用 DATA_ENCIPHERMENT,以及...

感謝您對您的幫助!

回答

1

通過source code的嗅探,有兩種情況會引發該異常,其中一種是從未發生的錯誤,另一種是檢查以查看相關證書是否支持有問題的操作。

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"); 
    } 
} 

這表明您使用的是無效的加密證書。也許你試圖使用公鑰證書進行加密?

它看起來像代碼不檢查opmode總是無效像PRIVATE_KEY,只是那些有時無效像ENCRYPT_MODE,這可能是爲什麼你的測試代碼很好。

+0

是,通過調試Cipher.init()我沒有看到,第一個條件得到滿足,即: '(!keyUsageInfo = NULL)&& (((OPMODE == Cipher.ENCRYPT_MODE)&& (keyUsageInfo.length > 3)&& (keyUsageInfo [3] == FALSE)' 的KeyUsage證書中應該支持加密,因爲它具有本節: '的ObjectId:2.5.29.15臨界=真 的KeyUsage [ 的DigitalSignature Key_Encipherment ]' 還是我誤讀了? 非常感謝! – user1526437 2012-07-17 02:34:43

+0

我相信你正在尋找「數據加密」而不是「密鑰加密」。我想這將是Cipher.WRAP_MODE。 – tbroberg 2012-07-17 07:59:40

1

最近跑進去了。只要正確創建了公鑰證書,就可以使用公鑰證書進行加密。該證書應該具有密鑰使用對象ID(ObjectId:2.5.29.15 Criticality = true),設置爲'b0'(10110000),基本上啓用數據加密位。否則,您將遇到錯誤密鑰使用錯誤。任何CA頒發的證書都將使密鑰使用嚴重性變爲真實。自簽名證書(如在開發/沙箱環境中)不會將該重要性設置爲true,因此這些將起作用,當然您會設置爲信任它們。 我嘗試使用服務器的公鑰證書,並正在努力解決此錯誤。然後我們的IT部門拿回了適用於Data Encipherment的正確公鑰證書,並開始爲我工作。