我有一個基於Java(基於JAX-WS)的SOAP客戶端,我試圖與基於WCF的(第三方)服務器交談。我發現sentiment expressed here是相當準確的。但目標依然存在。我可以從服務器中哄騙一個有效的「安全上下文令牌」,但是在消息簽名問題上我掛了(我相信)。SOAP,WCF和消息簽名
服務器似乎希望使用客戶端/服務器密鑰(PSHA1
算法)使用hmac-sha1
認證碼對消息進行簽名。很公平。然而,JAX-WS似乎想要使用rsa-sha1
和X509證書籤署出站消息(服務器不喜歡),並且似乎只使用hmac-sha1
如果提供了UsernameToken
(服務器也不喜歡) 。
所以我試圖從SOAPHandler
實現中手動簽署出站SOAP消息。在客戶端,以獲取安全上下文令牌發送請求如下:
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:Entropy>
<t:BinarySecret Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce">NzM1MDZjYWVkMTEzNDlkNGEyODY0ZDBlMjlkODEyMTM=</t:BinarySecret>
</t:Entropy>
<t:KeySize>256</t:KeySize>
</t:RequestSecurityToken>
,以及服務器發回的令牌是這樣的:
<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestedSecurityToken>
<c:SecurityContextToken xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc" u:Id="uuid-106bdbae-76e5-4195-b5d0-cc1c1a7a813e-13">
<c:Identifier>urn:uuid:c0be4929-da8d-4955-8e13-b25aa7a37217</c:Identifier>
</c:SecurityContextToken>
</t:RequestedSecurityToken>
<t:RequestedAttachedReference>
<o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" URI="#uuid-106bdbae-76e5-4195-b5d0-cc1c1a7a813e-13" />
</o:SecurityTokenReference>
</t:RequestedAttachedReference>
<t:RequestedUnattachedReference>
<o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:Reference URI="urn:uuid:c0be4929-da8d-4955-8e13-b25aa7a37217" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
</o:SecurityTokenReference>
</t:RequestedUnattachedReference>
<t:RequestedProofToken>
<t:ComputedKey>http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1</t:ComputedKey>
</t:RequestedProofToken>
<t:Entropy>
<t:BinarySecret u:Id="uuid-106bdbae-76e5-4195-b5d0-cc1c1a7a813e-14" Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce">dssunihZGy2dnnDHV9PMe3vU3lg/kKKZQkFohvGvCAk=</t:BinarySecret>
</t:Entropy>
<t:Lifetime>
<u:Created>2016-04-08T04:11:54.392Z</u:Created>
<u:Expires>2016-04-08T19:11:54.392Z</u:Expires>
</t:Lifetime>
<t:KeySize>256</t:KeySize>
</t:RequestSecurityTokenResponse>
我結合了客戶端並使用PSHA1
服務器BinarySecret
密鑰如下:
private byte[] getSharedKey() {
try {
//FIXME: client key first, or server key first?
P_SHA1 algo = new P_SHA1();
return algo.createKey(getBinaryClientEntropy(), getBinaryServerEntropy(), 0, getSharedKeySize()/8);
}
catch (Throwable e) {
LOG.error("Unable to compute shared key!", e);
}
return null;
}
我然後使用該密鑰來計算一個MAC的消息,如:
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec key = new SecretKeySpec(getSharedKey(), "HmacSHA1");
mac.init(key);
byte[] signatureBytes = mac.doFinal(content);
String signature = Base64.encodeBytes(signatureBytes);
然後進入出站請求(以及大量其他樣板文件),如SignatureValue
。最後,我最終的東西,如:
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Header xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:scon="http://schemas.xmlsoap.org/ws/2005/02/sc" xmlns:sec="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<sec:Security xmlns:env="http://www.w3.org/2003/05/soap-envelope" env:mustUnderstand="true">
<scon:SecurityContextToken xmlns:util="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" util:Id="uuid-106bdbae-76e5-4195-b5d0-cc1c1a7a813e-55">
<scon:Identifier>urn:uuid:3ab0f3fb-edd4-4880-af77-d700dda371bb</scon:Identifier>
</scon:SecurityContextToken>
<sig:Signature xmlns:sig="http://www.w3.org/2000/09/xmldsig#">
<sig:SignedInfo>
<sig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<sig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
</sig:SignedInfo>
<sig:SignatureValue>ohqViTbUYBG2E3hLldUA1AsPBJM=</sig:SignatureValue>
<sig:KeyInfo>
<sec:SecurityTokenReference>
<sec:Reference URI="#uuid-106bdbae-76e5-4195-b5d0-cc1c1a7a813e-55" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
</sec:SecurityTokenReference>
</sig:KeyInfo>
</sig:Signature>
</sec:Security>
</S:Header>
<S:Body>
<ns2:HelloWorld xmlns:ns2="http://tempuri.org/" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/">
<ns2:name>Test</ns2:name>
</ns2:HelloWorld>
</S:Body>
</S:Envelope>
這導致未來從服務器返回的響應「爲消息驗證安全性時發生錯誤」。
使用wcf-storm來發送請求並且Fiddler2檢查發送的數據包,我知道我應該關閉。以下要求正常工作:
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Header xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:scon="http://schemas.xmlsoap.org/ws/2005/02/sc" xmlns:sec="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
<u:Timestamp u:Id="_0">
<u:Created>2016-04-05T23:48:06.110Z</u:Created>
<u:Expires>2016-04-05T23:53:06.110Z</u:Expires>
</u:Timestamp>
<c:SecurityContextToken xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc" u:Id="uuid-8085da33-b25c-4f09-b5a9-110635a3ae39-2005">
<c:Identifier>urn:uuid:91349027-cb32-4c46-9f16-74a6bcb11126</c:Identifier>
</c:SecurityContextToken>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
<Reference URI="#_0">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>AvRXi7pyjulsfdg9afInSFMM+5k=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>TQup7BBN43b8CefrdSRd+X8MBgg=</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" URI="#uuid-8085da33-b25c-4f09-b5a9-110635a3ae39-2005" />
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</S:Header>
<S:Body>
<ns2:HelloWorld xmlns:ns2="http://tempuri.org/" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/">
<ns2:name>Test</ns2:name>
</ns2:HelloWorld>
</S:Body>
</S:Envelope>
的主要區別是:
- 我省略了
Timestamp
元素(雖然我試過,包括它,似乎沒有任何區別) 。我不知道DigestValue
是如何計算的。
所以,畢竟這一點,我想主要問題是:
什麼是簽訂出站郵件的實際算法?如在,如果我有:
<Envelope>
<Header>
HHH...
</Header>
<Body>
BBB...
</Body>
</Envelope>
...我的意思是計算<Envelope>...</Envelope>
(整個事情)或<Body>...</Body>
,甚至是BBB...
部分的簽名值?如果我打算使用整個事物,那麼我如何協調這一點,即將簽名信息添加到標題時會更改在計算簽名時用作輸入的內容?
是否有一種更直接的方式讓JAX-WS使用我忽略的必需簽署約定來生成請求?
然後也有一些小的獎金問題:
是否有針對一個既定的標準,其中爲了在使用
PSHA1
結合他們我通過客戶端和服務器BinarySecret
值?Timestamp
和SignedInfo/Reference
是否有意義,如果是這樣,那麼計算DigestValue
的正確方法是什麼?
實際上,作爲'P_SHA1'參數的熵的順序由WS-Trust正式指定。在你的特定情況下,'ComputedKey' URI是'http:// schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1',它表示2005年2月WS-Trust的修訂版(http:// specs .xmlsoap.org/WS/2005/02 /信賴/ WS-Trust.pdf)。根據規範:「使用來自TLS規範的P_SHA1計算密鑰以使用來自雙方的熵生成比特流。確切的形式是:key = P_SHA1(Ent_REQ,Ent_RES)' –
我希望我可以upvote這1000倍。你在這裏跟隨你的發現是一個英雄。 – Jonathan