Tuesday, December 6, 2011

Symmetric/Asymmetric Encryption/Signature with Apache Rampart

What is meant by Symmetric ? Both the parties, client and server use the same key to encrypt and sign.

Now the question is how to establish this key..? Anyone of the two parties can generate the key, but.. how do we pass the generated key to the other end...

This is how it works in Web Services security...

1. Initiator generates a key
2. Signs/Encrypts the message with the generated key
3. Encrypts the key with the public key of the recipient
4. Builds an encrypted key element with the output from [3] and associates an ID with that element and stores it in-memory using ID as the key. [This is how Rampart stores it]
<xenc:EncryptedKey Id="EncKeyId-C1AFA8321D1093CA1913231781007902">
    <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>
      <wsse:KeyIdentifier
       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/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">r3iHLvhEdbQLQGh0iuDzzJMBz40=</wsse:KeyIdentifier>
     </wsse:SecurityTokenReference>
    </ds:KeyInfo>
    <xenc:CipherData>
<xenc:CipherValue>O8LF2rEFKOJfKZpWlpmHI2OopDX00Ep4koqpJuEqhPbm3do1MTSovi0ZGl6wwtXYYCr3VzHobwDoc6yAECEoCEH9ZUvnzBKXa7OqmuGl3LOhIe91sTpHdceXbq7f6MpfePMPuHsdKhkbWea3aTOzbvzRm5VctZC7K4wk0LryBMQ=
     </xenc:CipherValue>
    </xenc:CipherData>
   </xenc:EncryptedKey>
5. EncryptedKey element will be included in the Security header of the SOAP message going from the sender to the recipient.

Here what you see under CipherValue element is the encrypted generated key.

The value of KeyIdentifier, which is r3iHLvhEdbQLQGh0iuDzzJMBz40=, is the base64 encoded SHA1 value of the fingerprint of the recipient's public key. Looking at this fingerprint value, recipient can pick the corresponding private key to decrypt the message and get the generated key out.

Also, let's have a look at the Algorithm attribute of EncryptionMethod element. This is the algorithm used to encrypt the generated key - and which to use is based on the Algorithm Suite defined in your security policy. In this case I have used Basic256 as the Algorithm Suite - so it uses rsa-oaep-mgf1p as the asymmetric key wrapping algorithm.

Now let's see what happens at the recipient end...

1. Recipient gets the message
2. Finds the private key corresponding to the fingerprint value in EncryptedKey element
3. Decrypts the encrypted generated key
4. Decrypts the message and verifies the signature using the key from [3]
5. Generates the response
6. Signs/Encrypts the response from the same key from [3]
7. Now it generates the SHA1 of the EncryptedKey element it receives from the client and adds the base64 encoded value to the response
8. Sends the response to the client

Once the client gets the message, it will perform following validations..

1. Client gets the message
2. Goes through all the stored EncryptedKey elements in-memory to check whether the SHA1 hash of any of them matches with the hash value in the response. If any match found, that's the Encrypted key.
3. EncryptedKey element in the memory also maintains the generated key in clear text, so client can find it
4. From the key found in [3]. client validates the message

With Symmetric binding, only the recipient needed to have a public/private key pair.

But in Asymmetric binding both the parties should have their own key pairs.

Even it's Asymmetric, the encryption happens with a generated symmetric key - the reason is Asymmetric encryption is resource consuming and also cannot operate on a large amount of data... so, WS-Security specification recommends to use symmetric key encryption with a generated key, even with the Asymmetric binding.

The major difference between the Asymmetric and the Symmetric is the way Signature been handled.

With Symmetric binding, both the request and the response are signed using the same generated key.. But in Asymmetric binding, the request is signed using the sender's private key and the response is signed using recipient's private key. In other words, Asymmetric provides a guarantee on non-repudiation while Symmetric binding does not.

Let's see how Asymmetric binding works in Web Services security..

1. Initiator/client generates a key
2. Encrypts the message with the generated key
3. Signs message with it's own private key
4. Encrypts the generated key with the public key of the recipient
5. Builds an encrypted key element with the output from [4] and associates an ID with that element. Do NOT store it in-memory as in the case of Symmetric.
<xenc:EncryptedKey Id="EncKeyId-C1AFA8321D1093CA1913231781007902">
    <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>
      <wsse:KeyIdentifier
       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/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">r3iHLvhEdbQLQGh0iuDzzJMBz40=</wsse:KeyIdentifier>
     </wsse:SecurityTokenReference>
    </ds:KeyInfo>
    <xenc:CipherData>
<xenc:CipherValue>O8LF2rEFKOJfKZpWlpmHI2OopDX00Ep4koqpJuEqhPbm3do1MTSovi0ZGl6wwtXYYCr3VzHobwDoc6yAECEoCEH9ZUvnzBKXa7OqmuGl3LOhIe91sTpHdceXbq7f6MpfePMPuHsdKhkbWea3aTOzbvzRm5VctZC7K4wk0LryBMQ=
     </xenc:CipherValue>
    </xenc:CipherData>
   </xenc:EncryptedKey>
6. EncryptedKey element will be included in the Security header of the SOAP message going from the sender to the recipient.

The SOAP messages for Symmetric and Asymmetric requests look alike - cannot find any differences.

Now let's see what happens at the recipient end...

1. Recipient gets the message
2. Finds the private key corresponding to the fingerprint value in EncryptedKey element
3. Decrypts the encrypted generated key
4. Decrypts the message using the key from [3]
5. Verifies the signature of the message using the public key of the sender
6. Generates the response
7. Generates a new key
8. Encrypts the message with the generated new key
9. Signs message with it's own private key
10. Encrypts the generated key with the public key of the initiator [the client]
11. EncryptedKey element will be built with the encrypted generated key and included in the Security header of the SOAP message going from the service to the client.
12. Sends the response to the client

Once the client gets the message, it will perform following validations...

1. Client gets the message
2. Finds the private key corresponding to the fingerprint value in EncryptedKey element
3. Decrypts the encrypted generated key with the key from [2]
4. Decrypts the message using the key from [3]
5. Verifies the signature of the message using the public key of the service

One of my colleagues recently asked me how to find whether someone is using Asymmetric or Symmetric binding just by looking at the SOAP messages...

This is not possible by looking at the SOAP request - but looking at the SOAP response we can figure it out. When using Asymmetric binding SOAP response will have the EncryptedKey element inside the Security header - but not in the case of Symmetric binding.

Let's summarize the differences in the behavior between Asymmetric and Symmetric bindings.

Symmetric Binding Asymmetric Binding
Client Generates a key Generates a key
Service Uses the same key generated from the client Generates a key
Client Stores the generated key Does NOT store the generated key
Service Does not generate keys Does NOT store the generated key
Client Encrypts with the generated key Encrypts with the generated key
Service Encrypts with the client generated key Encrypts with the service generated key
Client Signs with the generated key Signs with the it's own private key
Service Signs with the client generated key Signs with the it's own private key
Client Adds the EncryptedKey element to the request Adds the EncryptedKey element to the request
Service Does NOT add the EncryptedKey element to the response Adds the EncryptedKey element to the response
Client Signature algorithm hmac-sha1 Signature algorithm rsa-sha1
Service Signature algorithm hmac-sha1 Signature algorithm rsa-sha1

1 comments:

chris said...

Hello,

It was a nice article to read through, but my requirement is the other way around. Instead I want client to encrypt using the server's public key and sign using X.509 certificate. And server generating a secret key, encrypting the response using that generated key and signing the generated key using client's certificate sent in the request.