Securing Web Services with X.509 Certificates - Signing with a Certificate (Page 2 of 4 ) Once you have the certificates installed on your computer, you can begin using them to sign and encrypt messages. In this step, you're going to sign messages sent from the client application using the client certificate (found in the Current User store).
- Return to Visual Studio .NET 2003.
- Click File | Open | Project.
- Navigate to C:\Microsoft Hands-on-Lab\DEV-HOL34\VB \ Exercises\B\before.
- Select SecureInvoiceB.sln and click Open.
Note: this solution is equivalent to the one you implemented in the last exercise. It uses a UsernameToken to authenticate, sign, and encrypt message.
- Open the code view of InvoiceManagerForm.vb in the SecureInvoiceClient project.
- Add an Imports statement for Microsoft.Web.Services2. Security.X509:
' InvoiceManagerForm.vb ... Imports Microsoft.Web.Services2. Security. X509 ...
- Add a new method to the InvoiceManagerForm class named GetX509Token. The method should take two strings (one to represent certificate's key identifier and another to represent the certificate store name that you're going to retrieve the certificate from), and return an X509SecurityToken as illustrated here:
... Private Function GetX509Token(ByVal keyId As String, ByVal storeId As String) As X509SecurityToken ... End Function 'GetX509Token ...
- Within the GetX509Token method, you need to retrieve an X509CertificateStore object for the specified store, open the store for reading, and find the certificate based on its key identifier. Then, return the identified certificate as a new X509SecurityToken object. Here's one way to write this code:
... Private Function GetX509Token(ByVal keyId As String, ByVal storeId As String) As X509SecurityToken Dim store As X509CertificateStore = X509CertificateStore.Current UserStore(storeId) store.OpenRead() Dim certs As X509CertificateCollection = store.FindCertificate ByKeyIdentifier( Convert.FromBase64 String(keyId)) store.Close() Return New X509SecurityToken(CType(certs(0), X509Certificate)) End Function 'GetX509Token ...
- Go to the ConfigureProxy method in InvoiceManagerForm. This is where we need to modify the code to use the client certificate (found in the Current User store) for signing the message.
- Within ConfigureProxy, remove all code within the function. You'll be replacing this code with certificate signing and encryption. You'll be replacing this code with certificate signing and encryption.
- Within ConfigureProxy, call your new GetX509Token method. For the key identifier, specify "gBfo0147lM6cKnTbbMSuMVvm FY4=", and for the store name, specify X509CertificateStore.MyStore as illustrated here:
... ' Retreive client certificate for signing Dim clientToken As X509SecurityToken = GetX509Token( "gBfo0147lM6cKnTbbMSuMVvm FY4=", X509CertificateStore.MyStore) ...
Note: You can use the X509 Certificate Tool (called WseCertificate2.exe) to determine the key identifier for a given certificate. This tool ships with WSE 2.0. You can find it in the following directory: C:\Program Files\Microsoft WSE\v2.0\Tools\Certificates. Here's what it looks like:
- Add the returned X509SecurityToken to the proxy's RequestSoapContext.Security.Tokens collection as illustrated here:
... ' Retreive client certificate for signing Dim clientToken As X509SecurityToken = GetX509Token( _ "gBfo0147lM6cKnTbbMSuMVvm FY4=", X509CertificateStore.MyStore) ' Add UsernameToken for authentication purposes proxy.RequestSoapContext. Security.Tokens.Add(login. Token) ' Must add client token to message for signature processing proxy.RequestSoapContext. Security.Tokens.Add(client Token) ...
Note: You should continue to send the UsernameToken as well. The UsernameToken will still be used for authentication and authorization purposes. Now you're going to use the certificate for signing the message.
- Instantiate a new MessageSignature based on the X509SecurityToken and add it to the proxy's RequestSoapContext.Security. Elements collection as illustrated here:
... ' Retreive client certificate for signing Dim clientToken As X509SecurityToken = GetX509Token( _ "gBfo0147lM6cKnTbbMSuMVvm FY4=", X509CertificateStore.MyStore) ' Add UsernameToken for authentication purposes proxy.RequestSoapContext. Security.Tokens.Add(login. Token) ' Must add client token to message for signature processing proxy.RequestSoapContext. Security.Tokens.Add(client Token) proxy.RequestSoapContext. Security.Elements.Add( _ new MessageSignature(clientToken)) ...
- Open WseSecurityHelpers.vb in the SecureInvoiceServiceB project and comment out the call to CheckForEncryption in GetUsernameToken. This makes it so the service doesn't require encryption for the time being.
Note: you'll add X.509-based encryption in the next step and add this line of code back in.
- Right-click on the SecureInvoiceServiceB project in Solution Explorer and click WSE Settings 2.0. Navigate to the Security tab and check Allow Test Roots in the X.509 Certificate Settings section.
- Click Yes to confirm the enabling of test roots.
- Press OK to close the tool.
- Build the solution and run the client application. Verify that if everything works as before (except for requiring encryption).
- Open OutputTrace.webinfo in the SecureInvoiceClient output directory (bin).
Notice that the message now contains a BinarySecurityToken element in addition to the UsernameToken from before.
Next: Encrypting the Body with a Certificate >>
More Visual Basic.NET Articles More By MSDN Virtual Labs |