使用.NET,我需要使用模式传输绑定调用第三方API,该API使用相互身份验证和双重加密。他们已成功收到并解密我的请求,处理并发送了回复。
SOAP响应的标头是一个安全元素。它包含EncryptedKey和Signature元素。正文是单独加密的。
解密正文的密钥包含在上面的EncryptedKey元素中,但其中的实际密钥也是加密的。在同一元素中是X509Data元素,提供证书详细信息(IssuerName和SerialNumber)来解密该密钥,该密钥可用于解密Body。
收到加密响应
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="TS-ba9edb63-214d-4d6b-8040-ed715a1326c7"></wsu:Timestamp>
<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EK-fede8959-6d80-4166-9e79-4a4229efee4f">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"></xenc:EncryptionMethod>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference>
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=Their Name,O=Their Organisation</ds:X509IssuerName>
<ds:X509SerialNumber>1234567*************************987654</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>K+l28afn3i8e..Encrypted...Key....4gnOHW0kxK7aL6l7Q==</xenc:CipherValue>
</xenc:CipherData>
<xenc:ReferenceList></xenc:ReferenceList>
</xenc:EncryptedKey>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-77d3082f-2668-4347-9582-83d1ba9f0f8d">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> </ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="#TS-ba9edb63-214d-4d6b-8040-ed715a1326c7">
<ds:Transforms> </ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>yKJziO....SrJPNE=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_2d4d85db-41d7-446b-87f1-0a839b9b3e7f">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>9PNS98w.....KMWU0=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>EaqS4/iiXybpMe6r........RFM2NM6D3X/zpQ==</ds:SignatureValue>
<ds:KeyInfo Id="KI-a6793d90-a124-4960-ae17-f07c43248f53">
<wsse:SecurityTokenReference wsu:Id="STR-1d682670-9dde-40e1-ad14-e29c9c62c474">
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=Their Name,O=Their Organisatio</ds:X509IssuerName>
<ds:X509SerialNumber>7654321*************************456789</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</SOAP-ENV:Header>
<soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="_2d4d85db-41d7-446b-87f1-0a839b9b3e7f">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-3900ed5b-952f-4d4a-976b-6a3e86967010" Type="http://www.w3.org/2001/04/xmlenc#Content">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"></xenc:EncryptionMethod>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">
<wsse:Reference URI="#EK-fede8959-6d80-4166-9e79-4a4229efee4f"></wsse:Reference>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>7KCEA0yCcd.....Encrypted....Body....O0AIbjdJ3gKQy8=</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</soap:Body>
</soap:Envelope>
问题: 如何配置.NET客户端:读取x509SerialNumber以获取证书以解密EncryptedKey.CipherValue(加密...密钥)然后使用它来解密正文????
当我尝试在代码中获取响应时:
Try
Dim response As TheirService.TheirMethodResponse = client.DoMethodAction(request)
Catch ex As Exception
Dim test As String = ex.Message
End Try
我得到以下异常(取自跟踪日志):
<Exception>
<ExceptionType>System.ServiceModel.Security.MessageSecurityException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>
Cannot resolve KeyInfo for unwrapping key: KeyInfo 'SecurityKeyIdentifier
(
IsReadOnly = False,
Count = 1,
Clause[0] = X509IssuerSerialKeyIdentifierClause(Issuer = 'CN=Their Name,O=Their Organisation', Serial = '1234567*************************987654')
)
', available tokens 'SecurityTokenResolver
(
TokenCount = 1,
TokenEntry[0] = (AllowedReferenceStyle=External, Token=System.ServiceModel.Security.Tokens.WrappedKeySecurityToken, Parameters=System.ServiceModel.Security.Tokens.WrappedKeySecurityTokenParameters:
InclusionMode: Once
ReferenceStyle: Internal
RequireDerivedKeys: True)
)
'.
</Message>
<StackTrace>
at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.CreateWrappedKeyToken(String id, String encryptionMethod, String carriedKeyName, SecurityKeyIdentifier unwrappingTokenIdentifier, Byte[] wrappedKey, SecurityTokenResolver tokenResolver)
at System.ServiceModel.Security.WSSecurityJan2004.WrappedKeyTokenEntry.ReadTokenCore(XmlDictionaryReader reader, SecurityTokenResolver tokenResolver)
at System.ServiceModel.Security.WSSecurityTokenSerializer.ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)
at System.IdentityModel.Selectors.SecurityTokenSerializer.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
at System.ServiceModel.Security.WSSecurityOneDotZeroReceiveSecurityHeader.DecryptWrappedKey(XmlDictionaryReader reader)
at System.ServiceModel.Security.ReceiveSecurityHeader.ReadEncryptedKey(XmlDictionaryReader reader, Boolean processReferenceListIfPresent)
at System.ServiceModel.Security.ReceiveSecurityHeader.ExecuteFullPass(XmlDictionaryReader reader)
at System.ServiceModel.Security.StrictModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPasses(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader)
at System.ServiceModel.Security.ReceiveSecurityHeader.Process(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy)
at System.ServiceModel.Security.MessageSecurityProtocol.ProcessSecurityHeader(ReceiveSecurityHeader securityHeader, Message& message, SecurityToken requiredSigningToken, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.SymmetricSecurityProtocol.VerifyIncomingMessageCore(Message& message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at SIA_Test_Project.SiaSetupCard.SetupCardService.setupCard2(setupCard2Request request)
at SIA_Test_Project.SiaSetupCard.SetupCardServiceClient.SiaSetupCard_SetupCardService_setupCard2(setupCard2Request request)
at SIA_Test_Project.Module1.Main()
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
</StackTrace>
<ExceptionString>
System.ServiceModel.Security.MessageSecurityException: Cannot resolve KeyInfo for unwrapping key: KeyInfo 'SecurityKeyIdentifier
(
IsReadOnly = False,
Count = 1,
Clause[0] = X509IssuerSerialKeyIdentifierClause(Issuer = 'CN=Their Name,O=Their Organisation', Serial = '1234567*************************987654')
)
', available tokens 'SecurityTokenResolver
(
TokenCount = 1,
TokenEntry[0] = (AllowedReferenceStyle=External, Token=System.ServiceModel.Security.Tokens.WrappedKeySecurityToken, Parameters=System.ServiceModel.Security.Tokens.WrappedKeySecurityTokenParameters:
InclusionMode: Once
ReferenceStyle: Internal
RequireDerivedKeys: True)
)
'.
</ExceptionString>
</Exception>
我如何设置客户端:
Dim binding As New Channels.CustomBinding
Dim securityBE As SymmetricSecurityBindingElement = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
securityBE.MessageProtectionOrder = Security.MessageProtectionOrder.SignBeforeEncrypt
securityBE.RequireSignatureConfirmation = False
securityBE.EnableUnsecuredResponse = False
binding.Elements.Add(securityBE)
binding.Elements.Add(New TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8))
Dim http As New HttpsTransportBindingElement()
http.RequireClientCertificate = True
binding.Elements.Add(http)
Dim endPoint As New EndpointAddress(New Uri("https://blar/blar/services/TheirMethodService"), EndpointIdentity.CreateDnsIdentity("Their Name"))
Dim client As New TheirService.TheirServiceServiceClient(binding, endPoint)
Dim credentials As New ClientCredentials
'Their cert where we have the public key only
credentials.ServiceEncryptingCert = GetCert("c40ca927................c94640cdb7")
'our their company's mutual auth cert where we have the private key
credentials.ClientEncryptingCert = GetCert("e3debd49................e9a6cd39c5")
'our their company's digital signing cert where we have the private key
credentials.ClientSigningCert = GetCert("40091641................d622761b")
client.ChannelFactory.Endpoint.EndpointBehaviors.Remove(GetType(Description.ClientCredentials))
client.ChannelFactory.Endpoint.EndpointBehaviors.Add(credentials)
'only sign the message do not encrypt it
client.Endpoint.Contract.ProtectionLevel = ProtectionLevel.EncryptAndSign
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls Or System.Net.SecurityProtocolType.Tls12
Dim request As New TheirService.TheirMethodRequest
request.ProductRequestItem = New TheirService.ProductRequestItem
'Construct Request
Try
Dim response As TheirService.TheirMethodResponse = client.DoMethodAction(request)
Catch ex As Exception
Dim test As String = ex.Message
End Try
调试时,以下函数中的requirement.GetProperty在查询响应时抛出异常:
Public Overrides Function CreateSecurityTokenProvider(requirement As SecurityTokenRequirement) As SecurityTokenProvider
Dim result As SecurityTokenProvider
If requirement.TokenType = System.IdentityModel.Tokens.SecurityTokenTypes.X509Certificate Then
Dim direction As MessageDirection
Dim noDirection As Boolean = False
Try
direction = requirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
Catch ex As Exception
noDirection = True
End Try
'this may be the client cert
If noDirection Then
result = New X509SecurityTokenProvider(Me.credentials.ClientEncryptingCert)
Else
If direction = MessageDirection.Output Then
If requirement.KeyUsage = IdentityModel.Tokens.SecurityKeyUsage.Signature Then
result = New X509SecurityTokenProvider(Me.credentials.ClientSigningCert)
Else
result = New X509SecurityTokenProvider(Me.credentials.ServiceEncryptingCert)
End If
Else
If requirement.KeyUsage = IdentityModel.Tokens.SecurityKeyUsage.Signature Then
result = New X509SecurityTokenProvider(Me.credentials.ServiceEncryptingCert)
Else
result = New X509SecurityTokenProvider(Me.credentials.ClientSigningCert)
End If
End If
End If
Else
result = MyBase.CreateSecurityTokenProvider(requirement)
End If
Return result
End Function
令人难以置信的是令人沮丧。任何帮助都感激不尽。提前谢谢。
答案 0 :(得分:0)
找到解决方案 - 我非常接近:使用非对称 SecurityBindingElement和CreateMutualCertificate Duplex BindingElement对象。
我如何设置客户端:
我正在使用它导致异常......
Dim securityBE As SymmetricSecurityBindingElement = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
替换为这一行,一切都会起作用:
Dim securityBE As AsymmetricSecurityBindingElement = SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)