Wednesday, August 6, 2014

Xml Web Services and Soap

Xml Web Services and Soap

Background

So how do I get off claiming that there is no security in SOAP? HOW TO: Secure XML Web Services with SSL, Authentication and Authorization, and Building Secure Web Services with Microsoft SOAP Toolkit 2.0 are just a few articles on MSDN alone that tout the security of SOAP. The key point to realize is that these articles mostly speak of HTTP security and not SOAP security. Relying on transport-level security can have its benefits, particularly when the infrastructure for the transport is as widespread as it is in the case of HTTP. Very secure applications can be created based upon the underlying transport security mechanisms—but there are limitations to what HTTP can provide to a SOAP application.
SOAP is a message format and is not tied to a single protocol. If you rely on HTTP to perform the authentication for your XML Web Service, then you restrict yourself to that protocol. It is conceivable, however, that a single SOAP message could be routed over a number of protocols. Similarly, it may make sense that a message is encrypted in such a manner that no one can read the message between the sender and the final receiver. If you use the standard mechanism for encrypted SOAP today, which is to send a message using HTTP over SSL, then each node along your SOAP message's route will be able to read your data—obviously not the desired result.
But now we can ring the church bells in celebration of SOAP security, because Microsoft has made a proposal for standardized SOAP Security as part of their Global XML Web Services Architecture. The new standard will allow for passing authentication credentials, insuring message integrity, and allowing for message privacy—all within the SOAP messaging schema.

Keys, Encryption, Signatures, and Certificates

Before we dig into SOAP Security, let's talk about some fundamental security concepts. We'll start with encryption schemes. There are two common categories of encryption schemes, both involving keys.
  • Symmetric encryption schemes use the same key to both encrypt and decrypt a message. A symmetric key is often called a session key.
  • Asymmetric encryption schemes have two different keys: a public key and a private key. A message encrypted with a public key can be decrypted with the private key. A message encrypted with the private key can be decrypted with the public key. Private/Public key encryption mechanisms provide a lot of power for performing authentication and insuring data integrity.
A couple of other terms you should be familiar with: A hash is an algorithm that takes any data as input and creates a fixed length output. A digest is a hash with a couple other features. First, the algorithm for creating a digest must be such that it is statistically improbable for the results of one input to match the results of a different input. Secondly, it must be impossible to determine the input given the output.
Okay, now let's consider the case where Bob computes a digest for a message, then encrypts his digest with his private key. Bob then sends the message to Alice along with the encrypted digest. Alice wonders if some evil person got a hold of the message and tampered with its contents. First of all, Alice decrypts the digest using Bob's public key. She then uses the same digest algorithm that Bob used on the message. If it matches the decrypted digest, she knows that 1) the message has not changed since Bob computed his digest, and 2) no one else but Bob could have encrypted the digest, since his public key was able to decrypt it. Bob's encrypted digest is called a digital signature.
certificate is the standard way to pass around public or symmetric keys. The message format for a certificate includes a digital signature from a Certificate Authority. Trusting a Certificate Authority in effect means you trust that any certificates created by that authority properly identify the owner for whom the certificate was issued. Therefore the private key that corresponds to the public key in the certificate is deemed to be known only by the specified owner. The most common way for representing certificates is to use a standard format referred to as X.509.

XML Signatures

The Web Services Security Language draft that defines security mechanisms for SOAP messages relies heavily on work done for XML messages in general. The XML-Signature Syntax and Processing proposed recommendation by the World Wide Web Consortium (W3C) defines a mechanism for creating and verifying digital signatures for all or part of an XML message. It also indicates an XML-compliant mechanism for holding a digital signature within an XML document.
Consider the following XML document for placing an order from Bob's Pencil Manufacturing Company.
<bp:pencilOrder xmlns:bp="http://bobspencils.com/pencilOrders">
  <bp:pencilType>bp:StandardNumberTwo</bp:pencilType>
  <bp:quantity>100,000</bp:quantity>
</bp:pencilOrder>

If a customer, Alice's Retail Office Supply, sent this order to Bob's Pencil Manufacturing, how would the people at Bob's Pencil Manufacturing know that it came from Alice's Retail Office Supply?
One solution is for Alice's Retail Office Supply to first digitally sign the above XML document. Using the W3C XML-signature syntax, the above document signed by Alice's Retail Office Supply might look like this:
<bp:signedPencilOrder xmlns:bp="http://bobspencils.com/pencilOrders">
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference URI=""/> 
        <Transforms> 
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms> 
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>aiYECAxNqK2PivQaRweWajXup5zJa...</SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>MIIH1zCCBr+gAwIBA...</X509Certificate>
      </X509Data>
    </KeyInfo> 
  </Signature>
  <bp:pencilOrder>
    <bp:OrderID>64B4A0D1-814E-4FF6-918A-DD7E7E1AECEA</bp:OrderID>
    <bp:pencilType>bp:StandardNumberTwo</bp:pencilType>
    <bp:quantity>100,000</bp:quantity>
  </bp:pencilOrder> 
</bp:signedPencilOrder>

The original pencilOrder element, in blue, is now a child element of the root signedPencilOrders element. More importantly, the signedPencilOrders element now also has another child, the Signature element. This is the element that holds the digital signature information. Included in the Signature element is the algorithm used to canonicalize the data, any transforms performed on the data, the digest algorithm, and the signature algorithm itself. Also included with the signature information is the Reference element, in red, which indicates the data we are interested in validating. In this case, a null URI means that the entire XML document containing the Signature element should be signed. Among other things, the URI attribute could have also included an XPointer reference to indicate a specific portion of this document for which to compute the signature. In our case we are creating a signature for the whole document.
This leads to an interesting problem. If we sign the entire document that envelopes this signature, wouldn't that change when we stick the actual signature value into the SignatureValue node? The DigestValue is also computed as part of the signing process. How can you compute a digest if the data you are computing the digest for will change when you include the digest? The way to avoid such a problem is to use a transform to remove the entire Signature element from the data to be digested and signed. The Transforms element, in green, allows you to perform any transform, but the transform we are using, indicated by the "http://www.w3.org/2000/09/xmldsig#enveloped-signature" algorithm identifier, performs an XPath transform that removes the Signature element. Therefore, changing the DigestValue and SignatureValue elements within the Signature element will not cause recursion problems.
It is good practice to use explicit transforms with the transform code listed in a Transform node. This way you can explicitly include the precise data that you want to sign, instead of relying on exclusion rules to cut out particular nodes. If a message is being passed around to different applications, new nodes could be added that would break an exclusive approach to defining your integrity area. If you use an inclusive approach, you will not run into this problem.
The actual algorithm for creating the digital signature goes something like this: First, grab the data indicated by the Reference element, run it through the specified canonicalization algorithm, send it through any transforms specified, and then compute the digest based on the results. The digest of the reference information is stored in the DigestValue element inside the SignedInfo element. Because tampering with the information (such as our digest algorithm, or our transforms) would invalidate our signing process, the data in the SignedInfo element is now digested and encrypted with the appropriate key to create the final signature, which is placed in the SignedValue element. Notice that the DigestValue of the reference is also within the SignedInfo node, so the SignedValue not only verifies that no one has tampered with our algorithm selections, but it also verifies that the data indicated by our Reference has not been tampered with.
Finally, there is one more optional element within the Signature element that we have not yet mentioned. That is the KeyInfo element indicated in Orange. This is simply a container for holding the key information required to validate the signature. In this case it would hold an X.509 certificate that caries the public key for Alice's Retail Office Supply. Thus, Bob's Pencil Manufacturing Company can easily verify that the order did in fact come from Alice, and that it has not been tampered with along the way.
It is important to note that the initial pencilOrder node, in blue, has one new child element, the OrderID element. A key vulnerability for message protocols that rely on digital signatures is the vulnerability to replay attacks. A malicious person could conceivably empty Alice's bank by resending Alice's signed message over and over again to Bob's Pencil Manufacturing. If Alice includes an identifier, which could take the form of a timestamp, Bob's SOAP message handler could detect whether it had already processed Alice's order or not, and if it had, it would throw out any additional copies it might receive. If SOAP messages are being routed through various paths, it is conceivable that through no malicious action whatsoever, multiple copies of the same order might arrive at Bob's Pencil Manufacturing. Again, the OrderID would allow Bob to realize it had a duplicate, and it could throw out any such requests after the initial order was processed.

XML Encryption

One option for our transaction discussed earlier is that Alice's Retail Office Supply may have wanted to include payment information with the order: Perhaps a credit card number or a purchase order number need to be included, so that Bob's Pencil Manufacturing can get its money. More than likely, Alice's Retail Office Supply does not want the payment information publicly available. Therefore, it makes a lot of sense to encrypt the payment information, so that only Bob's Pencil Manufacturing Company can read it. Let's take a look at what this might look like. We will start by looking at an XML document before encryption or signatures are applied:
<bp:pencilOrder xmlns:bp="http://bobspencils.com/pencilOrders">
  <bp:pencilType>bp:StandardNumberTwo</bp:pencilType>
  <bp:quantity>100,000</bp:quantity>
  <bank:paymentInfo xmlns:bank="http://www.megabank.com/payspec/1.0">
    <bank:PaymentAmount>$999.95</bank:PaymentAmount>
    <bank:CreditCardNumber>1234123412341234</bank:CreditCardNumber>
  </bank:paymentInfo>
</bp:pencilOrder>

In this case, there is a payment amount and a credit card number included with the order. Alice probably doesn't want her credit card number available to anyone who might see this document, so she will want to encrypt it. Using the W3C's XML Encryption Syntax and Processing working draft as a guideline, an encrypted version of this XML document might look like this:
<bp:pencilOrder xmlns:bp="http://bobspencils.com/pencilOrders">
  <bp:OrderID>64B4A0D1-814E-4FF6-918A-DD7E7E1AECEA</bp:OrderID>  
  <bp:pencilType>bp:StandardNumberTwo</bp:pencilType>
  <bp:quantity>100,000</bp:quantity>
  <bank:paymentInfo xmlns:bank="http://www.megabank.com/payspec/1.0"> 
    <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#"
                   Type="http://www.w3.org/2001/04/xmlenc#Content">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tipledes-cbc"/>
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:RetrievalMethod URI="#SessKey"
            Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey"/>
      </ds:KeyInfo>
      <CipherData>
        <CipherValue>9oATk2hDK2+HcTVHg...</CipherValue>
      </CipherData>
    </EncryptedData> 
    <EncryptedKey Id="SessKey" xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:KeyName>Bob's Pencil Manufacturing Company's Public/Private Key</ds:KeyName>
      </ds:KeyInfo> 
      <CipherData>
        <CipherValue>CCBPowCwYDVR0PBA...</CipherValue>
      </CipherData>
      <ReferenceList>
        <DataReference URI="#SessKey"/>
      </ReferenceList>
    </EncryptedKey> 
  </bank:paymentInfo>
</bp:pencilOrder> 

The elements from the previous document are highlighted in blue. The difference now is that the credit card number and payment amount has been replaced with an EncryptedData node, highlighted in red. The encrypted data is stored in the CipherValue subelement (it has been truncated here for readability reasons). The data was encrypted with a symmetric triple-DES algorithm. The session key used for encrypting and decrypting the payment data is also included in the document under the EncryptedKey node, in green. The EncryptedKey node has a copy of the session key encrypted with a Public Key for Bob's Pencil Manufacturing. Bob can then use the corresponding private key to decrypt the session key, and once he has the session key, he can decrypt the rest of the payment data.
Using asymmetric encryption algorithms to encode data is computationally expensive, so usually asymmetric methods are only used to encrypt a symmetric key—which is then used to encrypt the majority of the data. Note that there is a KeyInfo element used to describe the Private/Public keys used to encrypt the session key. In this case, it will take the private key to decrypt the information, so it doesn't make sense to send a certificate to Bob's Pencil Manufacturing. Therefore, Bob just has to know how to identify the public key that might have been used. This is why the name associated with the key pair is used.
If we were going to take our order one more step, we would probably now digitally sign the document listed above using the digital signature mechanism we talked about earlier. That way, not only would the parts of the order that should remain private stay that way, but Bob's Pencil Manufacturing would be able to verify that this order did in fact come from Alice's Retail Office Supply.

SOAP Security

Now that we have a feel for how signatures and encryption can work within a generic XML document, how does this differ from what is done with SOAP messages? Further, how can we use the mechanisms provided by the XML signature and encryption specifications to enhance the capabilities of SOAP?
The key to understanding how this can all fit together is to understand what exactly SOAP is. As mentioned earlier in this article, SOAP is simply a message format, but it has some interesting characteristics. First of all, the SOAP message is broken up into two portions: the SOAP header and the SOAP body. The header is used to hold any potential metadata associated with the request, while the body is used to hold the basic data contents that go along with the message.
The fact that we can send metadata with an XML message should actually turn on some light bulbs over the heads of those of you who are more security aware. As far as security is concerned, there is always meta-information that needs to go along with a document. Authentication information is metadata that would accompany a message. Similarly, digital signatures naturally fall into the "meta" field as well. So most of the security data we have looked at so far could easily live in the SOAP headers.
If privacy is a concern, the encrypted data will typically live in the SOAP body. There are certainly cases where some SOAP headers may need to be encrypted, but in most cases, when we speak of privacy issues, we are talking about encrypting part or all of a SOAP body. Even though encrypted XML elements may live in the SOAP body, the corresponding session keys may still be transmitted in the SOAP headers.
At this point, I imagine wheels are spinning in your head about how SOAP signatures and encryption might fall together. So let's take a look at the Web Services Security Language draft and see how it actually defines some of the SOAP security mechanisms. The draft is broken up into three areas: Credential Transfer, Message Integrity, and Message Privacy.

Credential Transfer

The idea of identifying the person who is sending a SOAP message is obviously a key part of any sort of security solution. If you are used to seeing HTTP authentication, the mechanism for passing credentials is a bit different than HTTP's basic authentication. Simply sending a username and password with a request does not usually provide enough security to meet any legitimate need. Usually we talk in terms of sending a certificate, or possibly a Kerberos ticket, as the mechanism for identifying an individual.
The Web Services Security Language draft defines a credentials element that would be passed in the SOAP headers with a SOAP request. The credentials element, like SOAP in general, is very flexible and can hold almost any sort of information. It will often be used to carry X.509 certificates and Kerberos tickets.
Be aware that the credentials header can hold any number of credentials, and they may be used for any number of reasons beyond just authenticating the sender of the message. For instance, you may want to include the certificate that holds the public key used to encrypt a session key. Additional certificates may be included to identify the Certificate Authority chain for a particular certificate. You may want to simply forward a certificate for the sake of including it with the attached message, even if it is not used for performing any encryption whatsoever. But more than likely, you will want to include a certificate for the sake of identifying who sent the message. So here is what this might look like:
<?xml version="1.0" encoding="utf-8"?>
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SOAP:Header>
    <wssec:credentials xmlns:wssec="http://schemas.xmlsoap.org/ws/2001/10/security">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
          <ds:X509Certificate>MIIH1zCCBr+gAwIBA...</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </wssec:credentials> 
  </SOAP:Header>
  <SOAP:Body>
    <bp:pencilOrder xmlns:bp="http://bobspencils.com/pencilOrders">
      <bp:OrderID>64B4A0D1-814E-4FF6-918A-DD7E7E1AECEA</bp:OrderID>  
      <bp:pencilType>bp:StandardNumberTwo</bp:pencilType>
      <bp:quantity>100,000</bp:quantity>
      <bank:paymentInfo xmlns:bank="http://www.megabank.com/payspec/1.0">
        <bank:PaymentAmount>$999.95</bank:PaymentAmount>
        <bank:CreditCardNumber>1234123412341234</bank:CreditCardNumber>
      </bank:paymentInfo>
    </bp:pencilOrder>
  </SOAP:Body>
</SOAP:Envelope>

The credentials node, highlighted in blue, holds an X.509 certificate. Notice that we use the KeyInfo element defined by the XML signature syntax that we discussed earlier. The Web Services Security Language draft allows for a lot of flexibility in the format of credential information, but it accepts the XML Signature KeyInfo schema for passing certificates or other key data. It also defines a number of its own mechanisms for passing certificates that are basically equivalent to the KeyInfo approach. Microsoft recommends using the licensing schemas defined in the Web Service License Language draft because they are more flexible and can be strongly typed, providing better schema validation. I use KeyInfo in these examples in order to avoid introducing too many new concepts.

Message Integrity

Simply passing credentials with a message doesn't necessarily achieve a whole lot, since a certificate could be passed with any message from anyone. Because certificates are publicly available, any person could include a certificate with their message, and claim to be that person. Even though HTTP basic authentication is not especially secure, at least it requires knowledge of a user's password, which is better than simply shipping a certificate with a request.
To the credit of the Web Services Licensing Language draft, you can easily include an encrypted username and password in the credentials header, and gain an authentication mechanism significantly better than HTTP basic authentication. We will use XML signature capabilities, however, to extend the ability of sending a public certificate with a SOAP message, so as to achieve an even greater authentication capability than can almost any HTTP authentication scheme. So let's take a look at how this is done in the following example message:
<?xml version="1.0" encoding="utf-8"?>
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SOAP:Header>
    <m:path xmlns:m="http://schemas.xmlsoap.org/rp">
      <m:action>http://bobspencils.com/orders</m:action>
      <m:to>soap://bobspencils.com/orders</m:to>
      <m:from>mailto:alice@alicesretail.com</m:from>
      <m:id>uuid:E52F4B79-F37A-47fd-8B2E-F36AFA87D3E6</m:id>
    </m:path> 
    <wssec:credentials xmlns:wssec="http://schemas.xmlsoap.org/ws/2001/10/security">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SigningCertificate">
        <ds:X509Data>
          <ds:X509Certificate>MIIH1zCCBr+gAwIBA...</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </wssec:credentials> 
    <wssec:integrity xmlns:wssec="http://schemas.xmlsoap.org/ws/2001/10/security">
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/xml-exc-c14n#"/>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI=""/>
            <ds:Transforms>
              <ds:Transform Algorithm="http://schemas.xmlsoap.org/2001/10/security                  #RoutingSignatureTransform"/>               <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>aiYECAxNqK2PivQaRweWajXup5zJa...</ds:SignatureValue>
        <ds:KeyInfo>
          <wssec:licenseLocation>               #SigningCertificate           </wssec:licenseLocation>
        </ds:KeyInfo>
      </ds:Signature>
    </wssec:integrity> 
  </SOAP:Header>
  <SOAP:Body>
    <bp:pencilOrder xmlns:bp="http://bobspencils.com/pencilOrders">
      <bp:OrderID>64B4A0D1-814E-4FF6-918A-DD7E7E1AECEA</bp:OrderID>  
      <bp:pencilType>bp:StandardNumberTwo</bp:pencilType>
      <bp:quantity>100,000</bp:quantity>
      <bank:paymentInfo xmlns:bank="http://www.megabank.com/payspec/1.0">
        <bank:PaymentAmount>$999.95</bank:PaymentAmount>
        <bank:CreditCardNumber>1234123412341234</bank:CreditCardNumber>
      </bank:paymentInfo>
    </bp:pencilOrder>
  </SOAP:Body>
</SOAP:Envelope>

The credentials node, highlighted in blue, is still in the SOAP headers, as it was in our credential example. There is one key change however. The KeyInfo element now has an ID attribute that indicates that this key can be referenced with the "#SigningCertificate" XPointer. We will see how this is used later.
The big change between this example and the previous example is the new integrity node, shown in red, which has been added to the SOAP headers. The integrity node contains our old friend the signature node from the XML signature syntax. For the most part, this is exactly like the signature syntax that we looked at before. There are a couple differences, however.
First of all, notice that the algorithm for the CanonicalizationMethod element is not the same as what we looked at before. The reason is that there becomes some namespace ambiguity when you start enveloping XML documents in other XML documents. In order to avoid ambiguity so that signatures work out correctly, it is important that we use exclusive XML canonicalization, which is defined by the W3C Exclusive XML Canonicalization draft. SOAP messages could potentially fall into this trap quite frequently, since XML documents will often be wrapped in other XML documents during the processing of SOAP messages.
Also, notice that we have a different transform listed for our signature than we had in the XML signature example. This is because SOAP messages are designed to be able to be routed from one location to another. In order to verify the route that our message intends, the RoutingSignatureTransform signs not only the body of the request, but also the routing information located in the path node (shown in green), located in the SOAP headers. The second transform listed above helps to address the exclusive XML canonicalization issue. Finally, the last difference is simply that the KeyInfo node now refers back to the credentials node that contains the key we assigned the "SigningCertificate" ID. This way, the certificate information is all in one place in the SOAP message, and has the added distinction of being considered a license.
The result of our example is that now the integrity of the SOAP message is guaranteed. Not only will Bob's Pencil Manufacturing know that this SOAP message came from Alice's Retail Office Supply, but it can verify that the message has not been altered, since Alice's Retail Office Supply signed it. We have message authentication and integrity, without knowledge of the underlying transport.

Message Privacy

Finally, we need to get back to the fact that Alice doesn't want her credit card information to be visible to anyone who might see her SOAP order message. The need for privacy is obviously a critical component of many security requirements. The beauty of XML encryption is that it allows for encrypting only what needs to be encrypted. Extra processing cycles are not burnt by encrypting every byte sent between two applications. More importantly, particularly in the vision of SOAP messaging for the future, all or part of a SOAP message may need to be processed by multiple nodes.
For instance, in the case of an order like Alice is sending, part of the message may need to go to the shipping department for fulfilling the order, part may need to go to accounts payable for the financial transaction, and the whole message may need to be forwarded to an auditing system for historical storage. The shipping department needs to know the details of the actual pencils ordered, but does not need to know the payment details. They may still, however, need to verify that the message came from Alice's Retail Office Supply.
If we were encrypting the entire message, then the entire message would have to be decrypted in order for anyone to process it. This would expose Alice's financial information to people who do not need to know it. And if you consider the previous methods of providing privacy by using SSL encryption to only encrypt the underlying transport channel, then every point through which the message was routed would be able to see all of the payment details.
The power of XML encryption even makes it conceivable that Alice could encrypt her payment information, plus a few additional details, with a banking institution's public key. Bob's Pencil Manufacturing Company would simply forward the encrypted payment info to the banking institution where it would be decrypted, and funds would be transferred to Bob's Pencil Manufacturing according Alice's encrypted directions. Bob would simply get verification that the funds transfer took place from the bank, and he would ship the order without knowing any of Alice's account details.
The additional details in the encrypted message would have to include information indicating that the funds need to be transferred to Bob's Pencil Manufacturing (so others couldn't forward the same encrypted data to the bank and expect to receive payment), and a transfer ID of some sort, so that if the bank received the same message multiple times from Bob's Pencil Manufacturing, it would realize it had already transferred the funds for that transfer ID, and would not debit Alice's account multiple times.
So let's take a look at what a SOAP message that uses encryption might look like.
<?xml version="1.0" encoding="utf-8"?>
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SOAP:Header>
    <wssec:credentials xmlns:wssec="http://schemas.xmlsoap.org/ws/2001/10/security">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SigningCertificate">
        <ds:X509Data>
          <ds:X509Certificate>MIIH1zCCBr+gAwIBA...</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </wssec:credentials>
    <wssec:integrity xmlns:wssec="http://schemas.xmlsoap.org/ws/2001/10/security">
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/xml-exc-c14n#"/>
          <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI=""/>
            <ds:Transforms>
              <ds:Transform Algorithm="http://schemas.xmlsoap.org/2001/10/security
                 #RoutingSignatureTransform"/>
              <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>aiYECAxNqK2PivQaRweWajXup5zJa...</ds:SignatureValue>
        <ds:KeyInfo>
          <wssec:licenseLocation>
              #SigningCertificate
          </wssec:licenseLocation>
        </ds:KeyInfo>
      </ds:Signature>
    </wssec:integrity>
  </SOAP:Header>
  <SOAP:Body>
    <bp:pencilOrder xmlns:bp="http://bobspencils.com/pencilOrders">
      <bp:OrderID>64B4A0D1-814E-4FF6-918A-DD7E7E1AECEA</bp:OrderID>  
      <bp:pencilType>bp:StandardNumberTwo</bp:pencilType>
      <bp:quantity>100,000</bp:quantity>
      <bank:paymentInfo xmlns:bank="http://www.megabank.com/payspec/1.0">
        <enc:EncryptedData xmlns:enc="http://www.w3.org/2001/04/xmlenc#"
                       Type="http://www.w3.org/2001/04/xmlenc#Content">
          <enc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tipledes-cbc"/>
          <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:RetrievalMethod URI="#SessKey"
                Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey"/>
          </ds:KeyInfo>
          <enc:CipherData>
            <enc:CipherValue>9oATk2hDK2+HcTVHg...</enc:CipherValue>
          </enc:CipherData>
        </enc:EncryptedData>
        <enc:EncryptedKey Id="SessKey" xmlns="http://www.w3.org/2001/04/xmlenc#">
          <enc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
          <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
           <ds:KeyName>Bob's Pencil Manufacturing Company's Public/Private Key</ds:KeyName>
          </ds:KeyInfo> 
          <enc:CipherData>
            <enc:CipherValue>CCBPowCwYDVR0PBA...</enc:CipherValue>
          </enc:CipherData>
          <enc:ReferenceList>
            <enc:DataReference URI="#SessKey"/>
          </enc:ReferenceList>
        </enc:EncryptedKey> 
      </bank:paymentInfo>
    </bp:pencilOrder>
  </SOAP:Body>
</SOAP:Envelope>
The message above is really a trivial combination of the SOAP signing example we just looked at, along with the XML encryption sample we looked at earlier. The EncryptedData element and the EncryptedKey element, highlighted in blue, are basically in the same format as our XML encryption example. Often, session keys will be passed in a license within the credentials header. You would then use the wssec:licenseLocation tag to refer to the certificate in the credentials header, just like we do in the ds:Signature node. Other than that, you are basically talking about normal XML encryption.

Conclusion

With the groundbreaking work done in the XML signature and encryption standards, SOAP is now able to take the next step of providing world-class security for SOAP messaging. This is not to say that protocol-level security is a thing of the past, and there are many instances where protocol-level security may make more sense, even when tools come to fruition that would make using SOAP-level security easy to implement. Yet the world-class security, and the flexibility provided by the SOAP security mechanisms, will enable applications to be created, the likes of which have only been envisioned in the past.

UDDI

Configure UDDI Services Security


You can configure UDDI Services security options by using the UDDI Services snap-in. You can change the default authentication, encryption, and cryptography settings for a UDDI Services site.

Authentication


UDDI Services supports two basic types of authentication: UDDI publisher authentication and Windows authentication. Understanding the differences between these modes of authentication is an important part of determining which method to use for a specific UDDI Services deployment.
  • UDDI Publisher Authentication: Supports authenticated publications using UDDI Publisher authentication, as defined in section 5.3 of the UDDI v3 Specification. All interaction with UDDI Services that uses this style of authentication occurs under the http://<server name>/uddipublic or https://<server name>/uddipublic virtual directory in IIS. The UDDI Services ASP.NET user interface supports only anonymous searching with this authentication mode.
  • Windows Authentication: Supports authenticated publications using Windows Integrated Authentication. In this mode, any message passed to UDDI Services is authenticated based on the security context of the user that is generated by Windows at login. All interaction with UDDI Services that uses this type of authentication occurs under the http://<server name>/uddi or https://<servername>/uddi virtual directory in IIS. The UDDI Services ASP.NET user interface supports all functions with this authentication mode including searching, publishing, subscribing, and coordination.
To configure the authentication setting for a site, select one of the following:
  • Windows Integrated and UDDI publisher authentication: Supports both Windows Integrated Authentication and UDDI Publisher authentication for publications. This is the default selection. Publication SOAP requests sent to http://<servername>/uddi or https://<servername>/uddi should use Windows Integrated Authentication and publication SOAP requests sent to http://<servername>/uddipublic or https://<servername>/uddipublic should use UDDI Publisher Authentication.
  • UDDI publisher authentication: Supports UDDI Publisher authentication only for publications. If this option is selected, publication SOAP requests should be sent to http://<servername>/uddipublic or https://<servername>/uddipublic.
  • Windows Integrated publisher authentication: Supports Windows Integrated Authentication only for publications. If this option is selected, publication SOAP requests should be sent to http://<servername>/uddi or https://<servername>/uddi.

    • Authentication for read (inquiry) access: If this option is selected, this UDDI Services site mandates the use of Windows Integrated Authentication for UDDI Inquiry API requests into this site.
Membership in Administrators, or equivalent, is the minimum required to complete this procedure.

To select an authentication type

  1. Click Start, point to All Programs, point to Microsoft UDDI Services, and then click UDDI Services Management Console.
  2. In the console tree, click the UDDI Services site that you want to configure.
  3. On the Action menu, click Properties.
  4. Click the Security tab.
  5. Under Authenticated access, select the authentication type that you want to use, and then click OK.

Encryption


The use of Secure Sockets Layer (SSL) for publishing updates to the UDDI Services site is automatically selected during UDDI Services Basic configuration. SSL encryption provides increased security for communication between client computers and the UDDI Services Web Application. If you do not want to use SSL encryption, you can use Custom configuration to clear the Require SSL for publication to this UDDI Services site option on the Configure UDDI Services Database Component page. When using SSL encryption with UDDI Services, you must configure a server certificate for the Internet Information Services (IIS) service that hosts the UDDI Services Web Application and then create an HTTPS binding for the Web site. For more information about configuring server certificates on a Web server, see Configuring Server Certificates in IIS 7.0 at http://go.microsoft.com/fwlink/?LinkID=64327 . After the UDDI Services are configured, you can still enable or disable the SSL option by using the UDDI Services snap-in.
Membership in Administrators, or equivalent, is the minimum required to complete this procedure.

To enable or disable SSL

  1. Click Start, point to All Programs, point to Microsoft UDDI Services, and then click UDDI Services Management Console.
  2. In the console tree, click the UDDI Services site that you want to configure.
  3. On the Action menu, click Properties.
  4. Click the Security tab.
  5. Under Secure Communications, select or clear the Require SSL for publication requests to this site check box.
  6. Click OK.

Cryptography


You can change the default key settings that are used for UDDI publisher authentication. Cryptography settings include the following:
  • SOAP authentication token expiration: SOAP authentication tokens communicate publisher credentials for UDDI publisher authenticated publications.
  • Cryptography key time-out: The cryptography key is used to generate SOAP authentication tokens.
Membership in Administrators, or equivalent, is the minimum required to complete this procedure.

To change cryptography settings

  1. Click Start, point to All Programs, point to Microsoft UDDI Services, and then click UDDI Services Management Console.
  2. In the console tree, click the UDDI Services site that you want to configure.
  3. On the Action menu, click Properties.
  4. Under Cryptography, click Change, and then modify one of the following:
    1. SOAP Authentication Token Expiration:

      Use the up or down arrow to change the time, in minutes, after which tokens that are issued for publication will expire.
    2. Cryptography Key Timeout:

      To reset the cryptography key that is used to encrypt SOAP authentication tokens now, click Reset Now.

      To automatically reset the cryptography key after a certain number of days, select the Automatically reset cryptography key check box, and then specify the number of days by using the up or down arrow.
  5. Click OK twice.

WSDL-First Web Service

Implementing WS-Security with CXF in a WSDL-First Web Service

Security is one of the most common requirements for SOAP-based web services. Several standards exist, among them WS-Security and WS-SecurityPolicy. They can be hard to implement, and they are often ignored in favor of a more ad hoc security standard, most often using password authentication in the message itself and SSL for transport layer security.
Trying to implement these standards recently, I had a very hard time finding a consistent and complete guide for doing so, or even a good explanation of the standards themselves. I did find good information on Glen Mazza's Blog, and my implementation and this tutorial owe much to that information. But that tutorial is based on another one which is in turn based on another one. I found it difficult to filter through the layers to find what was necessary. Thus, I wrote this to provide a more complete and easy to use guide.
This tutorial will try to take you step-by-step through adding a security policy to an existing working web service WSDL as well as adding the additional CXF and Spring configuration necessary to make it work. It will not tell you how to build a CXF web service to start with, or how to configure Spring to make it work.

Tools Needed

  • Maven, 2.2.1 or better
  • JDK 1.6 or better

Code

You can find the code necessary for the tutorial here:

Technologies and Techniques Used

This tutorial uses Apache CXF to provide the backing for a JAX-WS web service which is built WSDL-First.
It uses CXF instead of the Glassfish jaxws-ri implementation or the embedded JDK implementation because I found getting jaxws-ri to do the same thing very cumbersome: it needed to reside in an endorsed standards directory (which puts an installation burden on any system administrators using the product); it requires annotations in the WSDL to work correctly; it requires different annotations for the client and server, so two WSDL versions need maintenance; and it failed with a fatal bug when SOAP faults were returned. CXF exhibited none of these problems, and was easy to integrate with Spring. That said, we generate the JAX-WS and JAXB code with Sun/Oracle's standard tools to make sure they're compliant.
The service is built WSDL-first because I believe that this is the most implementation-independent way of producing a SOAP-based web service, and because I think it gives you better interfaces by forcing you to think of them as services, rather than as java methods. It also allows us to clearly specify the security policy, which makes it easier for service consumers to comply.
This example also uses a multi-module Maven project which separates the WSDL, the generated JAX-WS code, and the service implementation/WAR into separate modules, which allows for easy re-use of the WSDL and/or the generated code.
The tutorial example also uses Spring, and the starting code consists of a complete working web service, packaged as a WAR, configured via Spring. Although various techniques are used to construct the configuration, I won't be explaining the base Maven or Spring configuration in detail.
That said, there are some "tricks" in the code that might cause problems moving this example into an existing web service project:
  • The WSSecurityTutorialJaxWs project uses binding customizations to make the generated code more Java-friendly. These are like any other standard JAX-WS binding customizations, but you should note they exist.
  • The WSSecurityTutorialJaxWs unpacks the WSDL into a temporary directory for generation; it also unpacks the WSDL into the target/classes directory so that it ends up in the final WAR. This is because various tools, including CXF, can load the WSDL from the classpath rather than from the endpoint server, and so it is added to the jar as a convenience.
  • The WSSecurityTutorialWAR module is configured by various files through Spring, using an extension of Spring's property placeholder functionality which will, if necessary, read properties from system property or JNDI env values. There are three tiers of property configuration files: a default one, a deployment one, and a test one. The intent is for the default one (in src/main/resources) to be rolled into the WAR, for the deployment one to be modified and deployed to the deployment server's file system, and its location specified via a system property or JNDI value.
  • SLF4J is used for logging, and configuration files in the META-INF directories of the WAR and test classpaths force CXF to use SLF4J as well.
  • The WAR module also uses TestNG instead of JUnit, which allows us to "group" tests. A normal build will run the "unit" and "local-integration" groups. Adding the "integration-test" profile to the build (e.g., 'mvn clean install -Pintegration-test') executes the "remote-integration" group and uses a plugin to start Tomcat so that the service can be tested running in a container.

Getting Started

You can download the starting code here. If you unzip that, you should be able to CD, on the command line, into the WSSecurityTutorialParent module and execute "mvn clean install -Pintegration-test" successfully. If not, you have something wrong with your environment, and you will have to diagnose it before you can continue.

Altering the WSDL

To begin, you have to decide what the service's security policy will actually be, and modify the WSDL to specify it.
Aside from the specifications themselves, there seems to be precious little information about the security specification standard (WS-SecurityPolicy) available. Some information can be found http://wso2.org/library/3132 herehere, and here.
Basically to declare a security policy for your web service, you have to define the policy using the http://schemas.xmlsoap.org/ws/2004/09/policy (wsp) and http://schemas.xmlsoap.org/ws/2005/07/securitypolicy (sp) schemas in your WSDL, and then attach the policy declarations to the service, operation, and/or input/output bindings that you want controlled by that policy.
A policy is declared with the "WS-Policy" schema/vocabulary (http://schemas.xmlsoap.org/ws/2004/09/policy wsp), and looks like this, basically:
WS-Policy Declaration
<wsp:Policy wsu:Id="UniqueIdentifier">
    <wsp:ExactlyOne>
        ...
    </wsp:ExactlyOne>
</wsp:Policy>
Inside the policy declaration, which in itself doesn't define what the policy is, you need to add security policy declarations. These are defined by the (http://schemas.xmlsoap.org/ws/2005/07/securitypolicy sp) schema, and there are a large number of variations, as defined in the specification linked above.
Basically, for our tutorial, we want to require that the body and custom headers of our messages are signed with a X.509 certificate (for source authentication), and that the body of our messages is encrypted with an X.509 certificate (for message privacy).
A policy to encrypt an input or output message is pretty simple, and looks basically like this:
WS-SecurityPolicy Input/Output Declaration
<wsp:Policy wsu:Id="InputOutputUniqueIdentifier">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:EncryptedParts>
    <sp:Body />
   </sp:EncryptedParts>
   <sp:SignedParts>
    <sp:Body />
    <sp:Header Namespace="http://example.com/tutotial/"/>
   </sp:SignedParts>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>
This says any operation whose input or output is linked to InputOutputUniqueIdentifier must have an encrypted body and must have a signed body and headers (the signed headers are all in the given namespace).
In theory we could require that the headers also be encrypted, but there is a CXF bug which prevents this from working (CXF-3452; also see related CXF-3453).
We then need to declare, for the entire service binding, how the input/output binding will take place (what kinds of tokens, how the tokens are exchanged, etc.). The options here are complex, and aside from the rather opaque specification, there's not much explanatory documentation available.
WS-SecurityPolicy Binding Policy Declaration
<wsp:Policy wsu:Id="UniqueBindingPolicyIdentifier">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:AsymmetricBinding>
    <wsp:Policy>
     <sp:InitiatorToken>
      <wsp:Policy>
       <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
        <wsp:Policy>
         <sp:WssX509V3Token11 />
        </wsp:Policy>
       </sp:X509Token>
      </wsp:Policy>
     </sp:InitiatorToken>
     <sp:RecipientToken>
      <wsp:Policy>
       <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
        <wsp:Policy>
         <sp:WssX509V3Token11 />
         <sp:RequireIssuerSerialReference />
        </wsp:Policy>
       </sp:X509Token>
      </wsp:Policy>
     </sp:RecipientToken>
     <sp:Layout>
      <wsp:Policy>
       <sp:Strict />
      </wsp:Policy>
     </sp:Layout>
     <sp:IncludeTimestamp />
     <sp:OnlySignEntireHeadersAndBody />
     <sp:AlgorithmSuite>
      <wsp:Policy>
       <sp:Basic128 />
      </wsp:Policy>
     </sp:AlgorithmSuite>
     <sp:EncryptSignature />
    </wsp:Policy>
   </sp:AsymmetricBinding>
   <sp:Wss11>
    <wsp:Policy>
     <sp:MustSupportRefIssuerSerial />
    </wsp:Policy>
   </sp:Wss11>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>
This says an AsymmetricBinding will be used (asymmetric or public/private keys rather than symmetric encryption); the initiator must always include an X.509 token; the return message will also be signed/encrypted with an X.509 certificate, but the token itself will not be included and instead an issuer serial # reference will be included. Additionally, strict header layout is used; a timestamp is included and messages will be rejected if the timestamp is too far out-of-date (to avoid replay attacks); only complete headers and bodies must be signed rather than child elements of either; the "Basic128" algorithm suite is used; the signature itself must be encrypted; and the caller must support issuer serial references.
If we wanted to include a further layer of security for message transport, or wanted to use transport encryption instead of message-level encryption, we could add something like:
HTTPS Transport Policy Declaration
<sp:TransportToken>
 <wsp:Policy>
  <sp:HttpsToken />
 </wsp:Policy>
</sp:TransportToken>

So to implement these assertions, you should do the following:
Add to the attributes of your wsdl:definitions element:
  • xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  • xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
  • xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
I also added, for editor convenience:
Add the complete set of declarations to your WSDL (I added them as the last elements in the WSDL):
Complete Tutorial Binding Assertion
<wsp:Policy wsu:Id="TutorialBindingPolicy">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:AsymmetricBinding>
    <wsp:Policy>
     <sp:InitiatorToken>
      <wsp:Policy>
       <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
        <wsp:Policy>
         <sp:WssX509V3Token11 />
        </wsp:Policy>
       </sp:X509Token>
      </wsp:Policy>
     </sp:InitiatorToken>
     <sp:RecipientToken>
      <wsp:Policy>
       <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
        <wsp:Policy>
         <sp:WssX509V3Token11 />
         <sp:RequireIssuerSerialReference />
        </wsp:Policy>
       </sp:X509Token>
      </wsp:Policy>
     </sp:RecipientToken>
     <sp:Layout>
      <wsp:Policy>
       <sp:Strict />
      </wsp:Policy>
     </sp:Layout>
     <sp:IncludeTimestamp />
     <sp:OnlySignEntireHeadersAndBody />
     <sp:AlgorithmSuite>
      <wsp:Policy>
       <sp:Basic128 />
      </wsp:Policy>
     </sp:AlgorithmSuite>
     <sp:EncryptSignature />
    </wsp:Policy>
   </sp:AsymmetricBinding>
   <sp:Wss11>
    <wsp:Policy>
     <sp:MustSupportRefIssuerSerial />
    </wsp:Policy>
   </sp:Wss11>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="TutorialInputBindingPolicy">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:EncryptedParts>
    <sp:Body />
   </sp:EncryptedParts>
   <sp:SignedParts>
    <sp:Body />
    <sp:Header Namespace="http://example.com/tutotial/"/>
   </sp:SignedParts>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="TutorialOutputBindingPolicy">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:EncryptedParts>
    <sp:Body />
   </sp:EncryptedParts>
   <sp:SignedParts>
    <sp:Body />
    <sp:Header Namespace="http://example.com/tutotial/"/>
   </sp:SignedParts>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>
You then must "reference" the policy declarations where you want them used. To each wsdl:binding element where the binding policy should apply, add:
Binding Policy Reference
<wsp:PolicyReference URI="#TutorialBindingPolicy" />
For each input element where the policy should apply, add:
Input Policy Reference
<wsp:PolicyReference URI="#TutorialInputBindingPolicy"/>
For each output element where the policy should apply, add:
Output Policy Reference
<wsp:PolicyReference URI="#TutorialOutputBindingPolicy"/>
So, for instance, the tutorial's code:
Complete Tutorial Binding
<wsdl:binding name="TutorialWebServiceSOAP" type="tns:TutorialWebService">
 <wsp:PolicyReference URI="#TutorialBindingPolicy" />
 <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
 <wsdl:operation name="sendTutorialMessage">
  <soap:operation soapAction="http://example.com/tutotial/sendTutorialMessage" />
  <wsdl:input>
   <wsp:PolicyReference URI="#TutorialInputBindingPolicy"/>
   <soap:body use="literal" parts="parameters" />
   <soap:header use="literal" part="source" message="tns:TutorialRequest"/>
  </wsdl:input>
  <wsdl:output>
   <wsp:PolicyReference URI="#TutorialOutputBindingPolicy"/>
   <soap:body use="literal" parts="response"/>
   <soap:header use="literal" part="acknowledgment" message="tns:TutorialResponse"/>
  </wsdl:output>
  <soap:address location="http://localhost/" />
 </wsdl:port>
</wsdl:service>

Implementing the Binding

Now you need to get CXF to read, enforce, and support the binding on the server and client. In our example, the server is the end-result WAR of the WAR module, and the client example is the integration test cases in that module.

Dependencies

To do this, you will need to add additional CXF dependencies: one to support WS-Policy, one to support WS-Security, and one as an encryption provider.
In the tutorial example, the Parent module controls the versions, exclusions, etc. of all dependencies, so to the dependencyManagement element of the Parent POM, add:
New Dependency Management Entries
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-ws-security</artifactId>
 <version>${cxf.version}</version>
 <exclusions>
  <exclusion>
   <groupId>commons-logging</groupId>
   <artifactId>commons-logging</artifactId>
  </exclusion>
 </exclusions>
</dependency>
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-ws-policy</artifactId>
 <version>${cxf.version}</version>
 <exclusions>
  <exclusion>
   <groupId>commons-logging</groupId>
   <artifactId>commons-logging</artifactId>
  </exclusion>
 </exclusions>
</dependency>
<dependency>
 <groupId>org.bouncycastle</groupId>
 <artifactId>bcprov-jdk16</artifactId>
 <version>${bouncycastle.version}</version>
 <exclusions>
  <exclusion>
   <groupId>commons-logging</groupId>
   <artifactId>commons-logging</artifactId>
  </exclusion>
 </exclusions>
</dependency>
And to the WAR module's POM:
New WAR Dependency Entries
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-ws-security</artifactId>
</dependency>
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-ws-policy</artifactId>
</dependency>
<dependency>
 <groupId>org.bouncycastle</groupId>
 <artifactId>bcprov-jdk16</artifactId>
</dependency>

New Spring Configuration Files

These new dependencies allow CXF to process the policy declarations and the new headers. To activate them, you need to load the CXF Spring configuration files for those new CXF modules. So, to the WAR's web.xml you should add, right under the existing classpath:META-INF/cxf/cxf-servlet.xml entry:
New Spring Files
classpath:META-INF/cxf/cxf-extension-policy.xml
classpath:META-INF/cxf/cxf-extension-ws-security.xml
And to your client, right after classpath*:/META-INF/cxf/cxf-extension-http.xml, you should add the same two XML files. For the tutorial, this is done in the ContextConfigurations attribute of TutorialWebServiceTest.java.
I found, when experimenting with this, that the CXF configuration files are sensitive to the order in which they are loaded by Spring – so the order specified above for the two new files, and where they are placed relative to existing CXF configurations, seems to be important.

Generate Certificates

Unless you have existing X.509 certificates for your client and server, you are going to have to generate new ones. Of course, for a production scenario, you should have issuer-signed certificates from a recognized authority such as Verisign, but for testing and development, and for this tutorial, self-signed certificates can be used. You can use the Java keytool for this; you will need to create two keystores (client and server), generate a client key and a server key, export the public keys, and import the public keys into the opposite number's keystore. A script to do this is here:
generate-keys.sh
#!/bin/bash

# Set the values we'll use for the generation
read -p"Server Key Alias?" serverkeyalias
read -p"Server Key Password?" serverkeypassword
read -p"Server Keystore Password?" serverstorepassword
read -p"Server Keystore File Name?" serverkeystorename

read -p"Client Key Alias?" clientkeyalias
read -p"Client Key Password?" clientkeypassword
read -p"Client Keystore Password?" clientstorepassword
read -p"Client Keystore File Name?" clientkeystorename

# Generate the server and client keys
keytool -genkey -alias $serverkeyalias -keyalg RSA -sigalg SHA1withRSA -keypass $serverkeypassword -storepass $serverstorepassword -keystore $serverkeystorename -dname "cn=localhost"
keytool -genkey -alias $clientkeyalias -keyalg RSA -sigalg SHA1withRSA -keypass $clientkeypassword -storepass $clientstorepassword -keystore $clientkeystorename -dname "cn=clientuser"

# Export the client key and import it to the server keystore
keytool -export -rfc -keystore $clientkeystorename -storepass $clientstorepassword -alias $clientkeyalias -file $clientkeyalias.cer
keytool -import -trustcacerts -keystore $serverkeystorename -storepass $serverstorepassword -alias $clientkeyalias -file $clientkeyalias.cer -noprompt
rm $clientkeyalias.cer

# Export the server key and import it to the client keystore
keytool -export -rfc -keystore $serverkeystorename -storepass $serverstorepassword -alias $serverkeyalias -file $serverkeyalias.cer
keytool -import -trustcacerts -keystore $clientkeystorename -storepass $clientstorepassword -alias $serverkeyalias -file $serverkeyalias.cer -noprompt
rm $serverkeyalias.cer
Of course you should note or remember the necessary passwords; you will need them later.
These keystores need to be placed where the server or client can read them. For the tutorial, the client keystore goes into src/test/resources, and the server one goes into src/main/springconfig/local. You will later need to tell the client and server, via Spring properties, where these are.

Create a CallbackHandler

To get passwords for specific keys, CXF uses an implementation of javax.security.auth.callback.CallbackHandler. If you don't already have one, you will need to create one. Create a new java class that implements javax.security.auth.callback.CallbackHandler that handles callbacks of type org.apache.ws.security.WSPasswordCallback. For example:
KeystorePasswordCallback.java
package com.example.tutorial.ws.security;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

/**
 * Really callback for key passwords.  Configure it with a map
 * of key-alias-to-password mappings.  Obviously this could
 * be extended to encrypt or obfuscate these passwords if desired.
 */
public class KeystorePasswordCallback implements CallbackHandler
{

    private Map<String, String> passwords = new HashMap<String, String>();

    /**
     * {@inheritDoc}
     * 
     * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
     */
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
    {
        for (Callback callback : callbacks)
        {
            if (callback instanceof WSPasswordCallback)
            {
                WSPasswordCallback pc = (WSPasswordCallback)callback;
    
                String pass = passwords.get(pc.getIdentifier());
                if (pass != null)
                {
                    pc.setPassword(pass);
                    return;
                }
            }
        }
    }

    /**
     * @return the passwords
     */
    public Map<String, String> getPasswords()
    {
        return passwords;
    }

    /**
     * @param passwords the passwords to set
     */
    public void setPasswords(Map<String, String> passwords)
    {
        this.passwords = passwords;
    }
    
}

Configure the Service

Next, you will need to configure the web service to handle WS-Security. Assuming you already have a CXF service defined in a Spring configuration file, you need to add:
  • The CallbackHandler you just created, with necessary passwords
  • A series of properties for the keystore to be used by the service
  • The key alias to be used for signing
To do this to the tutorial code, find cxf-service-config.xml, and add:
cxf-service-config.xml Additions
<bean id="keystorePasswordCallback" class="com.example.tutorial.ws.security.KeystorePasswordCallback">
 <property name="passwords">
  <map>
   <entry key="${wss.keyAlias}" value="${wss.keyPassword}"/>
  </map>
 </property>
</bean>

<util:properties id="keystoreProperties">
 <prop key="org.apache.ws.security.crypto.provider">org.apache.ws.security.components.crypto.Merlin</prop>
 <prop key="org.apache.ws.security.crypto.merlin.keystore.type">${wss.keystoreType}</prop>
 <prop key="org.apache.ws.security.crypto.merlin.keystore.password">${wss.keystorePassword}</prop>
 <prop key="org.apache.ws.security.crypto.merlin.keystore.alias">${wss.keyAlias}</prop>
 <prop key="org.apache.ws.security.crypto.merlin.file">${wss.keystorePath}</prop>
</util:properties>
These define a password callback, with a key alias entry and password, and the properties to manage the keystore. Note that all these entries are defined Spring property tokens; you will define these soon.
And to the existing jaxws:endpoint/jaxws:properties in that file, add:
cxf-service-config.xml Additions
<entry key="ws-security.callback-handler" value-ref="keystorePasswordCallback"/>
<entry key="ws-security.encryption.properties" value-ref="keystoreProperties"/>
<entry key="ws-security.signature.properties" value-ref="keystoreProperties"/>
<entry key="ws-security.encryption.username" value="useReqSigCert"/>
The entry useReqSigCert tells CXF to "encrypt the response with the same certificate that signed the request".
In this example we also use the same keystore properties for encryption and signature; if you have separate key and trust stores, you can create separate properties with different values.
Because most of the entries above are Spring property tokens, we need to enter the correct values into the property file that's being used by Spring to store these values. For the tutorial, add to TutorialDeploymentPropertyPlaceholders.properties:
TutorialDeploymentPropertyPlaceholders.properties
wss.keyAlias=the key alias you generated the service key with
wss.keyPassword=the key password you generated the service key with
wss.keystoreType=jks
wss.keystorePassword=the key store password you generated the service key with
wss.keystorePath=${configDirectory}/the name you gave the service keystore

Configure the Client

The client configuration is essentially the same, with very minor changes. For the tutorial:
war-spring-test.xml Additions
<bean id="keystorePasswordCallback" class="com.example.tutorial.ws.security.KeystorePasswordCallback">
 <property name="passwords">
  <map>
   <entry key="${wss.keyAlias}" value="${wss.keyPassword}"/>
  </map>
 </property>
</bean>

<util:properties id="keystoreProperties">
 <prop key="org.apache.ws.security.crypto.provider">org.apache.ws.security.components.crypto.Merlin</prop>
 <prop key="org.apache.ws.security.crypto.merlin.keystore.type">${wss.keystoreType}</prop>
 <prop key="org.apache.ws.security.crypto.merlin.keystore.password">${wss.keystorePassword}</prop>
 <prop key="org.apache.ws.security.crypto.merlin.keystore.alias">${wss.keyAlias}</prop>
 <prop key="org.apache.ws.security.crypto.merlin.file">${wss.keystorePath}</prop>
</util:properties>

...

<jaxws:client ...

 <jaxws:properties>
  <entry key="ws-security.callback-handler" value-ref="keystorePasswordCallback"/>  
  <entry key="ws-security.encryption.properties" value-ref="keystoreProperties"/>
  <entry key="ws-security.signature.properties" value-ref="keystoreProperties"/>
  <entry key="ws-security.encryption.username" value="${serverKeyAlias}"/>
 </jaxws:properties>
... 
Note that this one uses a specific key alias for the "username".
Then to the properties file:
TutorialTestPropertyPlaceholders.properties
wss.keyAlias=the alias you used to generate the client key
wss.keyPassword=the key password you used to generate the client key
wss.keystoreType=jks
wss.keystorePassword=the store password you used to generate the client key
wss.keystorePath=${configDirectory}/the name you gave to the client keystore
wss.serverKeyAlias=the server key alias you used to generate the server key

Run and Test

This (should) be it. You should be able now to run the service and test its encryption functionality. The tutorial code has logging interceptors turned on so you can see the encrypted and signed messages.

Notes about the Encrypted Messages

Hopefully, if everything works, the exchanged messages should look much like this:
An Encrypted Message
<soap:Envelope
 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
 <soap:Header>
  <ns2:message-source
   xmlns="http://example.com/tutotial/types/"
   xmlns:ns2="http://example.com/tutotial/"
   xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
   message-identifier="SYSTEM FAILURE"
   system-identifier="test"
   wsu:Id="Id-1337947189"/>
  <wsse:Security
   xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
   soap:mustUnderstand="1">
   <wsse:BinarySecurityToken
    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"
    EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
    ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
    wsu:Id="CertId-ACAFC43C228502A539130230131374311">MIIBoTCCAQqgAwIBAgIETSyeWTANBgkqhkiG9w0BAQUFADAVMRMwEQYDVQQDEwpjbGllbnR1c2VyMB4XDTExMDExMTE4MTU1M1oXDTExMDQxMTE4MTU1M1owFTETMBEGA1UEAxMKY2xpZW50dXNlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAgtoyaaP/nPzb7aW9VlRJTGDJENKMy87kewpN2z3TxMdzxsaFxQxtnnW+/iw+9kPAoEWQhFDIO7SG1VCEQrTfrefQ5b2fZZkeEKpMAc/Ls1BQxR7REUlBH7AhDNEu00tAhd0Rg7DUdIHhwI1phkEgasK13t7XxGMuzjb3MxdV5ZkCAwEAATANBgkqhkiG9w0BAQUFAAOBgQA+9VHcnZK2DAbkbNAdur/u6hPSGQz3s1l0ZK+WpKkRrSMh7P/eNZM8lDZnhJbjdyroU1u2X8DIgasQ+CCoHqSltwOpo75VrRCNbjBYATL+SEpU8zh37zO8jQVe4Bte6AAFQ1zFPpEAqgSVgxhNtXLPDrLVoos2svONEqd9wa4XuA==</wsse:BinarySecurityToken>
   <wsu:Timestamp
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    wsu:Id="Timestamp-9">
    <wsu:Created>2011-04-08T22:21:53.743Z</wsu:Created>
    <wsu:Expires>2011-04-08T22:26:53.743Z</wsu:Expires>
   </wsu:Timestamp>
   <xenc:EncryptedKey
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
    Id="EncKeyId-ACAFC43C228502A539130230131375015">
    <xenc:EncryptionMethod
     Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
    <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">
      <ds:X509Data>
       <ds:X509IssuerSerial>
        <ds:X509IssuerName>CN=localhost</ds:X509IssuerName>
        <ds:X509SerialNumber>1294769753</ds:X509SerialNumber>
       </ds:X509IssuerSerial>
      </ds:X509Data>
     </wsse:SecurityTokenReference>
    </ds:KeyInfo>
    <xenc:CipherData>
     <xenc:CipherValue>Kr5zeACNhaKl+INqWlI7moEbdSp1o8q7w0RUTTESxAnc9cKrjw1JPyM7VclXSIKOyqUQ81HbeypdiVUKNXMtpxUIcpGxQAtVeDec8nYZgNfBA6LRUh2xMe8QEf43UVKxS9MCvepS+J3tjhjSB4KJLR0mz15Ii0Gx/FJdjBt+RDM=</xenc:CipherValue>
    </xenc:CipherData>
    <xenc:ReferenceList>
     <xenc:DataReference
      URI="#EncDataId-11"/>
     <xenc:DataReference
      URI="#EncDataId-12"/>
    </xenc:ReferenceList>
   </xenc:EncryptedKey>
   <xenc:EncryptedData
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
    Id="EncDataId-12"
    Type="http://www.w3.org/2001/04/xmlenc#Element">
    <xenc:EncryptionMethod
     Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
    <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">
      <wsse:Reference
       xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
       URI="#EncKeyId-ACAFC43C228502A539130230131375015"/>
     </wsse:SecurityTokenReference>
    </ds:KeyInfo>
    <xenc:CipherData>
     <xenc:CipherValue>glktSJ3F6cyD/b60F9mpkR0cBwttOxv7pRWxYfzqZS+8UcSnk52LhXpU1UwGiYD+53ULAdS0S4Av
09Fm8/bYTJd8gzuPoSXI1HZCEkEV7WoappMX+QDQRSf9Vusd4W5uGSiecN7twDx8l4uAS2Ipj592
vQWSD+Dpm9YkNZOhSj+vkg6Az2lVtf8Zl8SgEawuIztYzVlrfsTdC39KprD3lDPlzgZOM+t4tmTw
3fbggRvMrtKviIdDLJZau8G78PtmvtuD4pXfl/8d+foBuTk/pcofNJ4Pv/gfbnmI9UnMXu+du0nK
c9ZFRz9Y5dnEfMqCy7yYS3Yqm+7OhD+UzGa6IyoVD4E/TSFqK7SGvSVOS6qkNOQaIyxmUHYi52HP
Ab5cEnirab+rxZX9TWpfKI/TIrlAGWbbwJbk1SsAeRbLic7qgWCY23UQX5iwz3kfEOfi8NahRADZ
2s4DnOe/hYqz6ml3sL/KxA7nhfCAdDv9oheeMvU2b46MOo1Z0hIa8zvCU8NHnexFIp3wQJUqDWgA
mGHnVBiJuT8OUpdIeCA/hKd6ICAzG2isOsO9IWFb87aTD70xPTbI0lcaaB+5R9ZwuwVWxzr0T1K9
233bzcbUY9sIVXtzDwShgXxkQQbEDjJD8tTNfz20ZHq955Qe4hgAQXiphZ5gadpcv7PTQm9qzOvU
ZE6IVBol1ENFK0+VAqGOMS9lvMy68cTkrkc/usRDLZcKVMGpLj/1c5rQ0PrEBbwzxK7R3PHBhBRn
BcxLOgTexLaVgzcCGwrPUkbZW+RvDQuSl7SxzElbRyHsCKMQTKI6DtmbX72VwOsAhTCEO7WgkxVa
f1eGR+KSTrlD6nR1xEQ4KzT5ZvZ2RvCGQLO5TqOdFLPPd2tHMui4MQrdSoxpNJdm8FVKJrjG0CNb
REl/wx8sPWLvleBCh22DvCovldvYZfPR+y0sNRtTtniQ9TBK4IduoTD3Wg+USLek2KgyrHubeTkO
lnzakLOIFAv752NTfdbKt7y8uOl7cuozzWxAScQagXDfMEUjr8HvGiTESEu5OOXpHUhNOGMlIyfG
ZshsmpVPywWB9fVTkwkOME97B8lscSf2AC7gQ/Ts34tyX8IszF7sZFKFU20s/TYqBh2erwqEI9LN
CQ3ARK+Tak5CkVIjCy15ESoORsmBMApI5r/GO+dIwWKtEL4MLP7GypEJn39gGeQHFzOygx0U463t
4QkrUpOfju6UyHGAb4hzHw6EpsgntMz6hreReNoXbNCnFtaK0llN3An22wK8dAKTHI6mpK+u6AK/
x1ibN1s5LlGYTvLC8VY8XOCTT9WwV74N5MjdmEcNDk1PwrjtcMxE5Os8J0emp7S3/zD5JppLdyw8
SK+jzi1OqH575urtRw2ZSikV7jihEW/CJqSGIJYvWCJ8v8S/sJJOztmXQ/OIhLpl3Mbk6RKIVrHV
svWW+iOaGuKoXXyuBxdXeCZC9niopmmSlOs3r9ksRW8HHK6YzGTKDHOjVluihTL6lbmNlzvewIrb
aGbKBkhHIlgZfHtRVDD+HPM+uPugctZrdMoY56L4dBWG3Zv1LqzhSCVab78nfmcH9cKETcr8rY8i
hNPtKQz+lATV9kDoo5U6aHt/cTV2mhHqI1bQ2ouElJYPncZSoSTvZ/whMu+QMiz7wdflc3xRTzUk
O5zpXZkSfinCTfBu7EizVibf64rdhJIuYrW51lYgBb1gK66HvWe46MNQ8aBUtMAVwiUIO7ABOEwG
UkabDzyxmzV1EirrsYRUDq9E8aJY9FO+kRx4tHt4kd6as7KIEUWtSjs/oXDCyX0I1oXKRrFnxOWF
4Gj9zOXGNqD5opX6nqKkzB9dvlymGzvdHqlXz375EndCbAeRiI8JbBV6UKkhH2+NoJwTt5p9nPMn
Ac2txkNksDe8rvmn6fmkKXvguyb/Y+iJpdxplNdxBHFtFK2BozMvDyCFqylYaFvZVcp3c7E8v2eJ
B/HsICreV5UFdYpKxOadJO8OngE7xgoV8UdqLj5/o22a9QsiBa8fKXBYiw+po2Aw/W18Znutz6w2
f3elnihXxyZBgSJHfqSI964OB/ELp0r5kiQzr1WEvSgSYcAShcTCjVvmYwi+OZ1D5daPYMtj4BKN
BQPk5KKr4dQeSi+56DrZlCAVwldGoWIef0fbfLJvi2lZLLtFOhHpOGSIa6IuNw9czwzQvtsnBQEA
5a/WTodJ9w93i3tLTdBeEVG4mUkDyo0PR6zpfAbK46K7hoFUtMO0rpwYaW3bKrUvA35lQbNXP20z
u4ZmXNU48bZUijhUs3An+uQhQIKYdR+Mqt5AmCAfvVPDEM75tlC3OEvflsEu5u7F93uzk5Qej0Hi
2gnOp7YoUgqvkCHbmvrifhSrm8dTi77EDbH3k6YnjqrLKaanYC9o12F1KAYopUBBoyCrqqQJAPm7
mYuxniAqeuKgXZO2et3xin/Klg0PKtxI6tEC0r4OFGU+woVN/B0wM7n/XFMTu25KZzjaXX1LdBA/
3Q4riSuRuzOHD6kpZUC+k/i5T06EqhLUWyW3hQ6t/9hOVczUuBNR42lsGdGtRGMOey277Gymffg0
VwGfFih6UxSJxAVFWBiMntCxDQHWQ2AM1SGd+RvoMJtn1UzcxcKUwRbFJDWrWieUOJV0/i6E0rPe
Bug22/ylmB4jcNLS7u3ble0nsLHm4jvbWreDmWujV9vGEWArn9BBEDTaJLWFEwg6qOw6vVP8RIzc
VdTKcYaNG4PnAbay</xenc:CipherValue>
    </xenc:CipherData>
   </xenc:EncryptedData>
  </wsse:Security>
 </soap:Header>
 <soap:Body
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  wsu:Id="Id-1857134841">
  <xenc:EncryptedData
   xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
   Id="EncDataId-11"
   Type="http://www.w3.org/2001/04/xmlenc#Content">
   <xenc:EncryptionMethod
    Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
   <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">
     <wsse:Reference
      xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
      URI="#EncKeyId-ACAFC43C228502A539130230131375015"/>
    </wsse:SecurityTokenReference>
   </ds:KeyInfo>
   <xenc:CipherData>
    <xenc:CipherValue>1QzMDBtcLlhUOwAeI++PCtUZS+fRwiVly4kOBl+7pNcsFhCudYaySmaKnb1v1Qyh0kmdPxMBjMmD
ZlKTSQESwyDYxlBzu+UxQJi/ovJ85m+k/MJHNvvsuXMwS7VPPGERvnUDr+tfngWrnhKMdx3hE25t
TIsSkCzd89/OPfc9xtrtKxMse1JrJhHaDB62xo4JRD7/dSsS2Wh4vQHhlNipm/w/Yf89vSp35kne
DnqdqmJf49jfefiRgo4HfzAv5MAZpgZ25ngzJK7bnuf5oCEUdauWEgvIviJnU1UT6wApvyYeldby
aeacc3YrfOFxtON2dyXnoPAXRRAyNUabDeuagNGVjZoyKfhmmTiPpjXVNrtXePppkCEXq46yKH9i
hmW728l95VBGaUbS3J/405+ywrr4H5pl6ypMMAY5L/dnk449BpQ3XU/W6JH7UgkmhMwSZMwdt0du
HvNcS/UpW/gaOREynPTV8EcEKscPty3LM8c00uW59sVIYaYEnED1K68zFmejcHcQj2RwtuSd/6dL
Ao5u7JtM1OmcQ6LT5YddMHQPnThZTGxVQWimGPoU+089UXUavcIX5nMY/PUY1ISuzVlvRFw+aEwC
Us7Iq05a9F8ZsbQVq7I20qPZGSouDIbPn5rpHEmQf56wB2k1bS/RqrTqaOXUADlhwWSWfpizT07F
k0QMlOWpyxqJ1q8mnxjllFqVjuu2QulLgyI+ee3cKzh8Wi0tVwh4wqX+XIXLV0Q+IJ1gs6j7lTAU
nXzaqNgYbVG2cIk70V+OyKeXh2Og9Z8gBpB09hULj3SRdIeYpuWrsvWdrDbunKl00OBPsbaZSbcg
pK4/PfNN5II8hVEvF6Fn6V0DkGP9i4c0lT0H52E=</xenc:CipherValue>
   </xenc:CipherData>
  </xenc:EncryptedData>
 </soap:Body>
</soap:Envelope>
The most notable change between this and a "normal" SOAP message is the wsse:Security header and the blocks of xenc:CipherData. I found several things worth noting, because nothing I had read explained how this worked:
  • The wsse:Security element in the header contains the information needed to decrypt and verify the message.
  • The wsse:BinarySecurityToken element contains the actual token data
  • The wsu:Timestamp element contains our requested timestamp, in this case expiring in 5 minutes. Messages sent after the expiration date should fail.
  • The xenc:EncryptedKey element contains information about the key that was actually used to encrypt the message. It contains the token reference for the encrypting key, which in the case of the above message is the public key of the server. It also contains a xenc:CipherValue element which, as I understand it, is a 128-Bit symmetric key, encrypted with the public key of the server. This 128-Bit key is used to encrypt the message; only the randomly generated symmetric key included here is used to encrypt the message. This provides the speed of symmetric encryption coupled with the security of PPK encryption by exchanging random, single-use keys encrypted with the public key of the recipient.
  • It also contains a reference list of elements which it should be used to decrypt.
  • The first xenc:EncryptedData element contains the signature for the message, encrypted with the given symmetric key.
  • The second xenc:EncryptedData contains the body of the message, encrypted with the given symmetric key.

Easy Way to Handle Android Notifications

Android Notifications Android Toast class provides a handy way to show users alerts but problem is that these alerts are not persist...