How to: Encrypt a SOAP Message Using an X.509 Certificate
The Web Services Enhancements for Microsoft .NET (WSE) allows a sender, which can either be an XML Web service or its client, to encrypt portions of the SOAP message by using the public key for the recipient's X.509 certificate. A receiver, which can be either a Web service or its client, then decrypts the message by using the private key for its X.509 certificate. If the recipient is the only one with the private key, it is highly likely that only the recipient can decrypt the message. Therefore, to encrypt the message, the sender must have access to the public key for the recipient's X.509 certificate and the recipient must have access to the private key for the recipient's X.509 certificate.
Optionally, the SOAP message can be signed before or after encrypting the SOAP message. If the SOAP message is signed, the sender signs the SOAP message with an X.509 certificate that it owns and has the private key for. This allows the recipient Web service to verify that the client really sent the message through the use of the public key for the sender's X.509 certificate. If the signature can be verified using the public key, the recipient can assume that the message came from the client. Therefore, to sign the message, the sender must have access to the sender's X.509 certificate and private key and the recipient must have access to the sender's X.509 certificate and public key.
For information about specifying which parts of the SOAP message are encrypted, see How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted.
The following procedures detail how to use Policy or code to encrypt a SOAP message using an X.509 certificate.
To use Policy to encrypt a SOAP message with an X.509 certificate
Add a <Policy> Element (WSE for Microsoft .NET) (1) element to the policy file for the application. Add the <Policy> Element (WSE for Microsoft .NET) (1) element as a child element of the <policies> Element element.
Use the <Policy> Element (WSE for Microsoft .NET) (1) element to define criteria that a SOAP message must meet. The criteria are specified as child elements of the <Policy> element. The Id attribute is used to name the policy assertion, which is used by the <request> Element (WSE for Microsoft .NET), <response> Element (WSE for Microsoft .NET), and <fault> Element elements to refer to a policy assertion when applying the policy to an endpoint.
The following code example defines a policy assertion named
policy-c0a22319-6b89-49ff-9b82-bdbac5f04618
.<wsp:Policy wsu:Id="policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy" xmlns:wsa="https://schemas.xmlsoap.org/ws/2004/03/addressing" >
Add a <Confidentiality> Element child element to the <Policy> Element (WSE for Microsoft .NET) (1) element.
Use the <Confidentiality> Element element to define encryption requirements. The requirements are specified in child elements.
The following code example specifies that there are encryption requirements.
<wsp:Policy wsu:Id="policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0" xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy"> <wssp:Confidentiality wsp:Usage="wsp:Required" xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
Add a <KeyInfo> Element (WSE for Microsoft .NET) (1) child element to the <Confidentiality> Element element.
Use the <KeyInfo> Element (WSE for Microsoft .NET) (1) element to define requirements for security tokens used to encrypt SOAP messages.
The following code example specifies that there are requirements on security tokens used to encrypt SOAP messages.
<wssp:Confidentiality wsp:Usage="wsp:Required" xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext"> <wssp:KeyInfo>
Add a <SecurityToken> Element child element to the <KeyInfo> Element (WSE for Microsoft .NET) (1) element.
Use the <SecurityToken> Element element to define requirements on security tokens used to encrypt SOAP messages.
The following code example specifies that there are requirements on security tokens used to encrypt SOAP messages.
<wssp:KeyInfo> <wssp:SecurityToken>
Add a <TokenType> Element child element to the <SecurityToken> Element element and set its value to
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3
.Use the <TokenType> Element element to specify the type of security token that must be used to encrypt SOAP messages.
The following code example specifies that an X509SecurityToken must be used to encrypt SOAP messages.
<wssp:SecurityToken> <wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3</wssp:TokenType>
Optionally, add a <Claims> Element child element to the <SecurityToken> Element element.
Use the <Claims> Element element to specify requirements specific to an X.509 certificate. The requirements are specified in the <Role> Element or <SubjectName> Element child elements.
The following code example specifies that there are specific requirements on the X.509 certificate used to encrypt the SOAP message.
<wssp:SecurityToken> <wssp:Claims>
Optionally, add a <SubjectName> Element child element to the <Claims> Element element.
Use the <SubjectName> Element element to specify that the SOAP message must be encrypted using an X.509 certificate with a specific subject name.
Note
When the <SubjectName> element is used to specify the subject name for an X.509 certificate, the value of the element is formatted differently than what appears in the MMC. The value that must be placed in the <SubjectName> element maps to the Subject field that appears on the Details tab of the Certificates snap-in within the MMC. If you copy the value of the Subject field from the MMC, the value has to be reversed prior to placement in the <SubjectName> element. For example, if the value of the Subject field is
CN=WSE2QuickStartServer, O=Coho Winery, L=Woodinville, S=WA, C=US
, the value that must be added to the <SubjectName> element isC=US, S=WA, L=Woodinville, O=Contoso, CN=Coho Winery
.The following code example specifies that the SOAP message must be encrypted using the X.509 certificate with a subject name of
CN=WSE2QuickStartClient
.<wssp:Claims> <wssp:SubjectName>CN=WSE2QuickStartClient</wssp:SubjectName>
Optionally, add a <TokenIssuer> Element (WSE for Microsoft .NET) (1) child element to the <SecurityToken> Element element.
Use the <TokenIssuer> Element (WSE for Microsoft .NET) (1) element to specify the certification authority that issued the X.509 certificate.
Note
The value of the <TokenIssuer> element is formatted differently than what appears in the MMC. The value that must be placed in the <TokenIssuer> element maps to the Issuer field that appears on the Details tab of the Certificates snap-in within the MMC. If you copy the value of the Issuer field from the MMC, the value has to be reversed prior to placement in the <TokenIssuer> element. For example, if the value of the Issuer field is
CN=CertServer DC=corp DC=contoso DC=com
, the value that must be added to the <TokenIssuer> element isDC=com DC=contoso DC=corp CN=CertServer
.The following code example specifies that the X.509 certificate that is used to encrypt SOAP messages must have been issued by the
DC=com DC=contoso DC=corp CN=CertServer
certification authority.<wssp:SecurityToken> <wssp:TokenIssuer>DC=com DC=contoso DC=corp CN=CertServer</wssp:TokenIssuer>
Add a <MessageParts> Element for <Confidentiality> Element element to the <Confidentiality> Element element.
Use the <MessageParts> element to specify the XML elements that must be encrypted.
The following code example specifies that the <Body> element is encrypted.
<wssp:MessageParts Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part"> wsp:Body() </wssp:MessageParts>
Add an <endpoint> Element element to the <mappings> Element element.
Use the <endpoint> Element element to apply a policy assertion to an endpoint.
The following code example sets the default policy for all SOAP messages to the
policy-c0a22319-6b89-49ff-9b82-bdbac5f04618
policy assertion.<mappings xmlns:wse="https://schemas.microsoft.com/wse/2003/06/Policy"> <endpoint uri="http://www.cohowinery.com/Service1.asmx"> <defaultOperation> <request policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" /> <response policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" /> <fault policy="#policy-c0a22319-6b89-49ff-9b82-bdbac5f04618" /> </defaultOperation> </endpoint> </mappings>
Optionally, add an X509SecurityToken that meets the policy requirements to the PolicyEnforcementSecurityTokenCache to the code where you are sending the SOAP message.
This step is optional, as WSE will look through the following caches or stores in the specified order to find an X.509 certificate that matches the Policy:
The Tokens collection of the SoapContext associated with the SOAP message.
- The PolicyEnforcementSecurityTokenCache token cache.
- The certificate store specified in the application's configuration file.
WSE uses the first X.509 certificate that it finds that matches the policy. Therefore, if you would like to use a specific X.509 certificate to encrypt the SOAP message, add an <SubjectName> Element element that specifies the specific X.509 certificate.
The following code example adds an X509SecurityToken to the PolicyEnforcementSecurityTokenCache.
To use code to encrypt a SOAP message by using an X.509 certificate
Obtain the recipient's X.509 certificate. If you are signing the X.509 certificate, obtain the receiver's X.509 certificate.
- Export the recipient's certificate on their computer.
To export the certificate, open the Certificates snap-in of the MMC, and then run the Certificate Export Wizard. - Obtain the client X.509 certificate in one of the following ways:
- Purchase a certificate from a certification authority (CA), such as VeriSign, Inc.
- Set up your own certificate service and have a CA sign the certificates. Windows 2000 Server, Windows 2000 Advanced Server, and Windows 2000 Datacenter Server all include certificate services that support public key infrastructure (PKI).
- Set up your own certificate service. In this case, the certificate will not be signed.
Whichever approach you take, the recipient of the SOAP request containing the X.509 certificate must trust the certificate. This means that the X.509 certificate or an issuer in the certificate chain is in the Trusted People certificate store and that the X.509 certificate is not in the Untrusted Certificates store.
For more information, see Managing X.509 Certificates.
In order to use the X.509 certificate for encryption, the Key Usage property of the certificate must include the Data Encipherment attribute.
- Export the recipient's certificate on their computer.
Install the recipient's X.509 certificate in a sender-accessible certificate store on the sender's computer.
- To import the certificate, open the Certificates snap-in of the MMC, and then run the Certificate Import Wizard.
The code example that follows (in step 6) assumes that the certificate is imported into the CurrentUser certificate store.
- To import the certificate, open the Certificates snap-in of the MMC, and then run the Certificate Import Wizard.
Open the XML Web service client project in Visual Studio .NET 2003.
Add references to the Microsoft.Web.Services2 and System.Web.Services assemblies.
- On the Project menu, click Add Reference.
- Click the .NET tab, select Microsoft.Web.Services2.dll, and then click Select.
- On the .NET tab, select System.Web.Services.dll, and then click Select.
- Click OK.
Add a Web reference to the Web service that is to receive the SOAP message signed with the X.509 certificate.
- On the Project menu, click Add Web Reference.
- In the Add Web Reference dialog box, type the URL for the Web service in the Address box, and then click the arrow icon.
- Verify that the items in the Available references box are the items you want to reference in your project, and then click Add Reference.
Edit the proxy class to derive from the WebServicesClientProtocol class.
In Solution Explorer, right-click the Reference.cs file for the Web reference just added, and then click View Code.
Note
If the Reference.cs file containing the proxy class is not visible, click the show all files icon on the Solution Explorer toolbar, and then expand the Reference.map node.
Change the base class of the proxy class to the Microsoft.Web.Services2.WebServicesClientProtocol class.
This modifies the proxy class to emit routing and security SOAP headers when communicating with the Web service. The following code example modifies a proxy class namedService1
to derive from the Microsoft.Web.Services2.WebServicesClientProtocol class.Public Class Service1 Inherits Microsoft.Web.Services2.WebServicesClientProtocol
public class Service1 : Microsoft.Web.Services2.WebServicesClientProtocol {
Note
If you select the Update Web Reference option in Visual Studio .NET 2003, the proxy class is regenerated, the base class is reset to the SoapHttpClientProtocol class, and you must change the class that the proxy class derives from again.
Add Imports or using directives to the top of the file that communicates with the Web service.
In Solution Explorer, right-click the file containing the client code, and then click View Code.
At the top of the file, add the Imports or using directives as shown in the following code example.
Imports Microsoft.Web.Services2 Imports Microsoft.Web.Services2.Security Imports Microsoft.Web.Services2.Security.Tokens Imports Microsoft.Web.Services2.Security.X509 Imports System.Security.Cryptography
using Microsoft.Web.Services2; using Microsoft.Web.Services2.Security; using Microsoft.Web.Services2.Security.Tokens; using Microsoft.Web.Services2.Security.X509; using System.Security.Cryptography;
Add code to get an X.509 certificate.
Open the certificate store containing the certificate that will be used to sign the SOAP message.
The following code example opens the certificate store for the currently logged-in user.Dim store As X509CertificateStore store = X509CertificateStore.CurrentUserStore( _ X509CertificateStore.MyStore) Dim open As Boolean = store.OpenRead()
X509CertificateStore store; store = X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore); bool open = store.OpenRead();
Select a certificate from the certificate store.
The certificate can be chosen programmatically by iterating over the X509CertificateStore.Certificates collection or by invoking one of the "Find" methods. The X509CertificateStore class supports the methods listed in the following table for finding a certificate.Method Description Finds an X.509 certificate in the store by using the certificate's (SHA-1) hash value.
Finds an X.509certificate in the store by using the certificate's authority key identifier.
Finds an X.509 certificate in the store by using the certificate's name value.
Finds an X.509 certificate in the store by using the certificate's name value. This search uses substring matching.
The QuickStart Samples contain sample code that shows how to display a dialog box for the user to select the certificate. For more information, see the X509CertificateStoreDialog.cs file in the Samples\QuickStart folder in WSE installation folder.
The following code example retrieves the certificate from the certificate store by using the hash for the certificate. The hash is the certificate's thumbprint. To obtain a certificate's thumbprint, open the Certificates snap-in of the MMC, and then click the Details tab.Dim certHash As Byte() = {&H98, &HEC, &H8, &H4B, &HA5, &H7A, _ &H6C, &H2F, &H39, &H26, &HB3, &HA, &H58, &HBF, &H65, &H25, _ &H61, &HC5, &H64, &H59} Dim certs As X509CertificateCollection = _ store.FindCertificateByHash(certHash); Dim cert As Microsoft.Web.Services2.Security.X509.X509Certificate _ = CType(certs(0), _ Microsoft.Web.Services2.Security.X509.X509Certificate)
byte[] certHash = {0x98, 0xec, 0x08, 0x4b, 0xa5 ,0x7a, 0x6c, 0x2f, 0x39 ,0x26 ,0xb3 ,0x0a ,0x58, 0xbf ,0x65 ,0x25, 0x61, 0xc5, 0x64 ,0x59}; X509CertificateCollection certs = store.FindCertificateByHash(certHash); Microsoft.Web.Services2.Security.X509.X509Certificate cert = ((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]);
Verify that the certificate can be used for signing or encryption, depending on how the certificate will be used.
When the certificate is used to encrypt the SOAP message, the certificate must support data encryption. To support data encryption, the Key Usage property of the X.509 certificate must include the Data Encipherment attribute. The SupportsDataEncryption property of the X509SecurityToken class indicates whether an X.509 certificate's Key Usage attributes include Data Encipherment.The following code example determines whether the certificate supports data encryption or key encipherment.
If cert.SupportsDataEncryption Then
if (cert.SupportsDataEncryption)
The following code example defines a
GetSecurityToken
method that finds the X.509 certificate based on its thumbprint.Public Function GetSecurityToken(IsTokenForSigning As Boolean) As X509SecurityToken Dim store As X509CertificateStore Dim securityToken As X509SecurityToken = Nothing ' Open the certificate store for the currently ' logged-in user. store = X509CertificateStore.CurrentUserStore( _ X509CertificateStore.MyStore) Dim open As Boolean = store.OpenRead() Try ' Retrieve the certificate by using its SHA-1 hash. Dim certHash As Byte() = {&H98, &HEC, &H8, &H4B, &HA5, _ &H7A, &H6C, &H2F, &H39, &H26, &HB3, &HA, &H58, &HBF, _ &H65, &H25, &H61, &HC5, &H64, &H59} Dim certs As X509CertificateCollection = _ store.FindCertificateByHash(certHash) Dim cert As _ Microsoft.Web.Services2.Security.X509.X509Certificate = _ CType(certs(0), _ Microsoft.Web.Services2.Security.X509.X509Certificate) If cert Is Nothing Then MessageBox.Show("Could not find X.509 certificate.") securityToken = Nothing ' If the requested token is for signing, verify that ' the certificate supports digital signatures and has ' a private key available. ElseIf ((IsTokenForSigning) And (Not cert.SupportsDigitalSignature Or (cert.Key Is Nothing))) Then MessageBox.Show("The certificate must support " + _ "digital signatures and have a private key" + _ "available.") securityToken = Nothing ' If the requested token is for encryption, verify ' that the certificate supports data encryption. ElseIf (Not IsTokenForSigning) And _ (Not cert.SupportsDataEncryption) Then MessageBox.Show("The certificate must support " + _ "data encryption.") securityToken = Nothing ' Else securityToken = New X509SecurityToken(cert) End If Finally If Not (store Is Nothing) Then store.Close() End If End Try Return securityToken End Function
public X509SecurityToken GetSecurityToken(bool IsTokenForSigning) { X509CertificateStore store; X509SecurityToken securityToken = null; // Open the certificate store for the currently // logged-in user. store = X509CertificateStore.CurrentUserStore( X509CertificateStore.MyStore); bool open = store.OpenRead(); try { // Retrieve the certificate by using its SHA-1 hash. byte[] certHash = {0x98, 0xec, 0x08, 0x4b, 0xa5, 0x7a, 0x6c, 0x2f, 0x39, 0x26, 0xb3, 0x0a, 0x58, 0xbf, 0x65, 0x25, 0x61, 0xc5, 0x64, 0x59}; X509CertificateCollection certs = store.FindCertificateByHash(certHash); Microsoft.Web.Services2.Security.X509.X509Certificate cert = ((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]); if (cert == null) { MessageBox.Show("Could not find the X.509 certificate."); securityToken = null; } // If the requested token is for signing, verify that // the certificate supports digital signatures and has // a private key available. else if ((IsTokenForSigning) && (!cert.SupportsDigitalSignature || (cert.Key == null))) { MessageBox.Show("The certificate must support " + "digital signatures and have a private key available."); securityToken = null; } // If the requested token is for encryption, verify // that the certificate supports data encryption. else if (!IsTokenForSigning) && !(cert.SupportsDataEncryption) { MessageBox.Show("The certificate must support data encryption."); securityToken = null; } else { securityToken = new X509SecurityToken(cert); } } finally { if (store != null) { store.Close(); } } return securityToken; }
Edit the method that communicates with the Web service to get the X.509 certificate and specify that the SOAP request be encrypted and optionally signed by the X.509 certificate.
For information about encrypting portions of the SOAP message other than the defaults, see How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted.
Note
Even though you typically sign the SOAP message when encrypting it, this is not required. Therefore, steps b through e are optional.
Get the SoapContext method for the SOAP request that is being made to the Web service.
The following code example gets the SoapContext method for a proxy class namedService1
.Dim svc As New Service1() Dim requestContext As SoapContext = svc.RequestSoapContext
Service1 svc = new Service1(); SoapContext requestContext = svc.RequestSoapContext;
If the SOAP message is being signed, get an X.509 certificate to sign the SOAP message.
The following code example calls the method defined in the previous step to get the client's X.509 certificate, which has a private key, to sign the SOAP message.Dim signatureToken As X509SecurityToken = GetSecurityToken(True)
X509SecurityToken signatureToken = GetSecurityToken(true);
If the SOAP message is being signed, add the sender's X.509 certificate to the WS-Security SOAP header.
requestContext.Security.Tokens.Add(signatureToken)
requestContext.Security.Tokens.Add(signatureToken);
If the SOAP message is being signed, create a new instance of the MessageSignature class by using the X.509 certificate just added to the WS-Security SOAP header.
Dim sig As New MessageSignature(signatureToken)
MessageSignature sig = new MessageSignature(signatureToken);
If the SOAP message is being signed, add the MessageSignature class to the WS-Security SOAP header.
requestContext.Security.Elements.Add(sig)
requestContext.Security.Elements.Add(sig);
Get an X.509 certificate to encrypt the SOAP message.
The following code example calls the method defined in the previous step to get the server's X.509 certificate, which has only a public key, to encrypt the SOAP message.Dim encryptionToken As X509SecurityToken = _ GetSecurityToken(False)
X509SecurityToken encryptionToken = GetSecurityToken(false);
Create a new instance of the EncryptedData class by using the X.509 certificate just added to the WS-Security SOAP header.
Dim enc As New EncryptedData(encryptionToken)
EncryptedData enc = new EncryptedData(encryptionToken);
Add the EncryptedData class to the WS-Security SOAP header.
requestContext.Security.Elements.Add(enc)
requestContext.Security.Elements.Add(enc);
Specify the time-to-live (TTL) for the SOAP message to minimize the chance of someone intercepting the message and replaying it.
The following code example sets the TTL to 1 minute.requestContext.Security.Timestamp.TtlInSeconds = 60
requestContext.Security.Timestamp.TtlInSeconds = 60;
Call the Web service.
svc.sayHello()
svc.sayHello();
Example
The following code example is a policy file specifying that all SOAP messages sent to the http://www.cohowinery.com/Service1.asmx
endpoint must be encrypted using then X.509 certificate that with a subject name WSE2QuickStart
.
Note
This code example is designed to demonstrate WSE features and is not intended for production use.
<?xml version="1.0" encoding="utf-8"?>
<policyDocument xmlns="https://schemas.microsoft.com/wse/2003/06/Policy">
<mappings xmlns:wse="https://schemas.microsoft.com/wse/2003/06/Policy">
<endpoint uri="http://www.cohowinery.com/Service1.asmx">
<defaultOperation>
<request policy="#policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0" />
<response policy="#policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0" />
<fault policy="#policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0" />
</defaultOperation>
</endpoint>
</mappings>
<policies xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:Policy wsu:Id="policy-08b0e1ca-9428-44fd-93f4-b11de6fa08e0"
xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy">
<wssp:Confidentiality wsp:Usage="wsp:Required"
xmlns:wssp="https://schemas.xmlsoap.org/ws/2002/12/secext">
<wssp:KeyInfo>
<SecurityToken xmlns="https://schemas.xmlsoap.org/ws/2002/12/secext">
<wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3</wssp:TokenType>
<!-- By specifying the SubjectName claim here, Policy can look for a certificate with this subject name in the certificate store indicated in the application's configuration. --> <wssp:SubjectName>CN=WSE2QuickStart</wssp:SubjectName>
</SecurityToken>
</wssp:KeyInfo>
<wssp:MessageParts
Dialect="https://schemas.xmlsoap.org/2002/12/wsse#part">wsp:Body()</wssp:MessageParts>
</wssp:Confidentiality>
</wsp:Policy>
</policies>
</policyDocument>
The following code example signs and encrypts a SOAP request to a Web service.
Try
' Get an X.509 certificate for signing the SOAP message.
Dim signatureToken As X509SecurityToken = GetSecurityToken(True)
If signatureToken Is Nothing Then
Return
End If
Dim svc As New Service1()
Dim requestContext As SoapContext = svc.RequestSoapContext
' Add the X.509 certificate to the header.
requestContext.Security.Tokens.Add(signatureToken)
' Specify that the SOAP message is signed using this X.509
' certifcate.
Dim sig As New MessageSignature(signatureToken)
requestContext.Security.Elements.Add(sig)
' Get an X.509 certificate for encrypting the SOAP message.
Dim encryptionToken As X509SecurityToken = _
GetSecurityToken(False)
If encryptionToken Is Nothing Then
Return
End If
' Add the X.509 certificate to the WS-Security header.
requestContext.Security.Tokens.Add(encryptionToken)
' Specify that the SOAP message is encrypted using
' this X.509 certificate.
Dim enc As New EncryptedData(encryptionToken)
requestContext.Security.Elements.Add(enc)
' Set the TTL to 1 minute.
requestContext.Security.Timestamp.TtlInSeconds = 60
' Make the SOAP request to the Web service.
svc.sayHello()
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
Public Function GetSecurityToken(IsTokenForSigning As Boolean) As X509SecurityToken
Dim store As X509CertificateStore
Dim securityToken As X509SecurityToken = Nothing
' Open the certificate store for the currently
' logged-in user.
store = X509CertificateStore.CurrentUserStore( _
X509CertificateStore.MyStore)
Dim open As Boolean = store.OpenRead()
Try
' Retrieve the certificate by using its SHA-1 hash.
Dim certHash As Byte() = {&H98, &HEC, &H8, &H4B, &HA5, _
&H7A, &H6C, &H2F, &H39, &H26, &HB3, &HA, &H58, &HBF, _
&H65, &H25, &H61, &HC5, &H64, &H59}
Dim certs As X509CertificateCollection = _
store.FindCertificateByHash(certHash)
Dim cert As _
Microsoft.Web.Services2.Security.X509.X509Certificate = _
CType(certs(0), _
Microsoft.Web.Services2.Security.X509.X509Certificate)
If cert Is Nothing Then
MessageBox.Show("Could not find X.509 certificate.")
securityToken = Nothing
' If the requested token is for signing, verify that
' the certificate supports digital signatures and has
' a private key available.
ElseIf ((IsTokenForSigning) And
(Not cert.SupportsDigitalSignature Or
(cert.Key Is Nothing))) Then
MessageBox.Show("The certificate must support " + _
"digital signatures and have a private key" + _
"available.")
securityToken = Nothing
' If the requested token is for encryption, verify
' that the certificate supports data encryption.
ElseIf (Not IsTokenForSigning) And _
(Not cert.SupportsDataEncryption) Then
MessageBox.Show("The certificate must support " + _
"data encryption.")
securityToken = Nothing '
Else
securityToken = New X509SecurityToken(cert)
End If
Finally
If Not (store Is Nothing) Then
store.Close()
End If
End Try
Return securityToken
End Function
try
{
// Get an X.509 certificate for signing the SOAP message.
X509SecurityToken signatureToken = GetSecurityToken(true);
if (signatureToken == null)
{
return;
}
Service1 svc = new Service1();
SoapContext requestContext = svc.RequestSoapContext;
// Add the X.509 certificate to the header.
requestContext.Security.Tokens.Add(signatureToken);
// Specify that the SOAP message is signed using this X.509
// certifcate.
MessageSignature sig = new MessageSignature(signatureToken);
requestContext.Security.Elements.Add(sig);
// Get an X.509 certificate for encrypting the SOAP message.
X509SecurityToken encryptionToken = GetSecurityToken(false);
if (encryptionToken == null)
{
return;
}
// Add the X.509 certificate to the WS-Security header.
requestContext.Security.Tokens.Add(encryptionToken);
// Specify that the SOAP message is encrypted using
// this X.509 certificate.
EncryptedData enc = new EncryptedData(encryptionToken);
requestContext.Security.Elements.Add(enc);
// Set the TTL to 1 minute.
requestContext.Security.Timestamp.TtlInSeconds = 60;
// Make the SOAP request to the Web service.
svc.sayHello() ;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
public X509SecurityToken GetSecurityToken(bool IsTokenForSigning)
{
X509CertificateStore store;
X509SecurityToken securityToken = null;
// Open the certificate store for the currently
// logged-in user.
store = X509CertificateStore.CurrentUserStore(
X509CertificateStore.MyStore);
bool open = store.OpenRead();
try
{
// Retrieve the certificate by using its SHA-1 hash.
byte[] certHash = {0x98, 0xec, 0x08, 0x4b, 0xa5, 0x7a,
0x6c, 0x2f, 0x39, 0x26, 0xb3, 0x0a,
0x58, 0xbf, 0x65, 0x25, 0x61, 0xc5,
0x64, 0x59};
X509CertificateCollection certs =
store.FindCertificateByHash(certHash);
Microsoft.Web.Services2.Security.X509.X509Certificate cert =
((Microsoft.Web.Services2.Security.X509.X509Certificate) certs[0]);
if (cert == null)
{
MessageBox.Show("Could not find the X.509 certificate.");
securityToken = null;
}
// If the requested token is for signing, verify that
// the certificate supports digital signatures and has
// a private key available.
else if ((IsTokenForSigning) &&
(!cert.SupportsDigitalSignature ||
(cert.Key == null)))
{
MessageBox.Show("The certificate must support " +
"digital signatures and have a private key available.");
securityToken = null;
}
// If the requested token is for encryption, verify
// that the certificate supports data encryption.
else if (!IsTokenForSigning) &&
!(cert.SupportsDataEncryption)
{
MessageBox.Show("The certificate must support data
encryption.");
securityToken = null;
}
else
{
securityToken = new X509SecurityToken(cert);
}
}
finally
{
if (store != null) { store.Close(); }
}
return securityToken;
}
See Also
Tasks
How to: Decrypt a SOAP Message Encrypted with an X.509 Certificate
How to: Specify the Parts of a SOAP Message That Are Signed or Encrypted