How does SOAP Message Encryption work?

Archived Content
This article is provided for historical perspective only, and may not reflect current conditions. Please refer to relevant product page for more up-to-date product information and resources.
  • By Thilina Buddhika
  • 23 Oct, 2009

WS Security Specification describes enhancements to SOAP messaging to provide message integrity, confidentiality,

non-repudiation etc. It does not introduce new information security concepts, rather it is based on the existing security

concepts like XML encryption, XML signature, etc. It sets the foundation to secure web services by adapting these existing

technologies accordingly.

href="https://www.oasis-open.org/committees/download.php/16790/wss-v1.1-spec-os-SOAPMessageSecurity.pdf" target="_blank" rel="noopener">WS

Security Specification

recommends to use symmetric keys for encryption. This is mainly due to the low performance factor

of asymmetric key based encryption. Even if the asymmetric binding is used, it is advised to use symmetric keys for

encryption. In such scenarios, the PKI is used to establish the symmetric keys. Initiator can come up with the symmetric and

encrypt it using the public key of the recipient. Then the recipient can decrypt this key and find out the symmetric key

which is used for encryption.

It is possible to encrypt the whole XML element or  just the content of it. WS Security

Specification enforces not to encrypt <S11:Header>, <S12:Header>, <S11:Envelope>, <S12:Envelope>,or

<S11:Body>, <S12:Body> elements. But encrypting the sub elements of those elements are allowed.

If a particular element or content of it is supposed to be encrypted, then that element should be replaced by the

<xenc:EncryptedData> element which is the result of encrypting the original element.

Ex :

<xenc:EncryptedData Id="EncDataId-3" 

Type="https://www.w3.org/2001/04/xmlenc#Content">...</xenc:EncryptedData>

Symmetric keys used for the encryption operations should be embedded inside

<xenc:EncryptedKey> elements. Each <xenc:EncryptedKey> element should contain a <ds:KeyInfo> element that

contains information about the key used to encrypt the symmetric key. Then there can be a <xenc:ReferenceList> which

is the manifest of the elements which are encrypted. If a <xenc:ReferenceList> element is appearing inside a

<xenc:EncryptedKey> element, it implies that the symmetric key resulted by decrypting the cipher value of the

<xenc:EncryptedKey> element should be used decrypt the elements specified in that refernce list.

<xenc:ReferenceList> is comprised of a list of <xenc:DataReference> elements which contains refernces to the

elements which are encrypted using this key. If we put this in a simplified manner, <xenc:ReferenceList> inside a

<xenc:EncryptedKey> element refers to all the <xenc:EncryptedData> elements which are encrypted using the

symmetric key contained in that  <xenc:EncryptedKey> element. Each <xenc:EncryptedData> element should be

referred using <xenc:DataReference> element.

Ex :

          <xenc:EncryptedKey Id="EncKeyId-E296581B23458CA12512507910022225">
                <xenc:EncryptionMethod Algorithm="https://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                <ds:KeyInfo xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
                    <wsse:SecurityTokenReference>
                        <wsse:KeyIdentifier
                                

EncodingType="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
                                

ValueType="https://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">
                            HYL371NzoOs2+IA24VDkBGcUFQM=
                        </wsse:KeyIdentifier>
                    </wsse:SecurityTokenReference>
                </ds:KeyInfo>
                <xenc:CipherData>
                    <xenc:CipherValue>
                        

H9l+f1lqTvi4W3vaHwXMhhdfOT8t2t75fzgCkUvjX7ae9FLMEm7/hoQCEurJE4SOmPRXUvLV3MSI21Fcr3HW2OFc1SEpAZQwxma03/iG0jlSyAOOO/j9jitTnmvh

tMGI9HShrM0cP77U0GDBTIoXqMSOrzMKbSQ8iz7wl5dG+TY=
                    </xenc:CipherValue>
                </xenc:CipherData>
                <xenc:ReferenceList>
                    <xenc:DataReference URI="#EncDataId-3"/>
                </xenc:ReferenceList>
          </xenc:EncryptedKey>

Lets come back to the <xenc:EncryptedData> element. Earlier we said that all the

elements which should be encrypted must be replaced by a <xenc:EncryptedData> elements. This element might contain a

<ds:KeyInfo> element which points to another <ds:KeyInfo> element or an attached security token. But it is not

mandatory to have such <ds:KeyInfo> element, if that <xenc:EncryptedData> element is listed in

a <xenc:ReferenceList> of a particuar <xenc:EncryptedKey>. It should contain a </xenc:CipherData>

element, which contains the cipher data.

Ex :

      <xenc:EncryptedData Id="EncDataId-3" Type="https://www.w3.org/2001/04/xmlenc#Content">
            <xenc:EncryptionMethod Algorithm="https://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
            <ds:KeyInfo xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
                <wsse:SecurityTokenReference
                        

xmlns:wsse="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                    <wsse:Reference URI="#EncKeyId-E296581B23458CA12512507910022225"/>
                </wsse:SecurityTokenReference>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>HTnMneoskQeLew99eIqCLh+8kUAvKozGjsLMfBN8Ji2QDx64Rl53vKqXYybDQeGidWHn9L7OFSEW
                    6kWuSsDqB+AWQezNgoACcxrNfn7vGwQidD3Kl6aviSaFALzJJkphk29Cip7vSOFmxJn3qIaA82AD
                    rrnPYT57uyPh03XELwrv1Wret3q1uNZ0pnjk6xjYjsQzkAgADUeE/MfWSMdjvpZ6eQ4wwTOmemeh
                    HtVLEdIsKoCyXRBMC9Etiu3KoymArNWRAMgQHvSzBmGxuWCALOHYru8OJpmetZacz5KVqWHifRhP
                    wXFsWOQF3zfBQhJmf4fRiAXkeJ4ZXn3BjT4dz/BVoDaHJFEwK5KY9GRtg0U7Eu3l5k6RNM3ds56N
                    PGP/DhvKJfcFCh4qKVfbWFDVLdeqcRzrHXWuiHTu6BoiwJgzFoQ8vjP6Bw==
                </xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>

Having said about the optional <ds:KeyInfo> element inside a

<xenc:EncryptedData> element, now it is possible to take the <xenc:ReferenceList> element out of the

<xenc:EncryptedKey> element if required. In such scenarios, <xenc:EncryptedData> elements should contain the

<ds:KeyInfo> elements pointing to the keys that are used for the encryption. With this option, it is possible to use

multiple keys for encrypting the elements in the same SOAP message.

So lets bring all the bits and pieces together. Following listing depicts a SOAP message with an encrypted soap body.

<soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:xenc="https://www.w3.org/2001/04/xmlenc#">
    <soapenv:Header xmlns:wsa="https://www.w3.org/2005/08/addressing">
        <wsse:Security 

xmlns:wsse="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                       soapenv:mustUnderstand="1">
            <xenc:EncryptedKey Id="EncKeyId-E296581B23458CA12512507910022225">
                <xenc:EncryptionMethod Algorithm="https://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
                <ds:KeyInfo xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
                    <wsse:SecurityTokenReference>
                        <wsse:KeyIdentifier
                                

EncodingType="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
                                

ValueType="https://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">
                            HYL371NzoOs2+IA24VDkBGcUFQM=
                        </wsse:KeyIdentifier>
                    </wsse:SecurityTokenReference>
                </ds:KeyInfo>
                <xenc:CipherData>
                    <xenc:CipherValue>
                        

H9l+f1lqTvi4W3vaHwXMhhdfOT8t2t75fzgCkUvjX7ae9FLMEm7/hoQCEurJE4SOmPRXUvLV3MSI21Fcr3HW2OFc1SEpAZQwxma03/iG0jlSyAOOO/j9jitTnmvh

tMGI9HShrM0cP77U0GDBTIoXqMSOrzMKbSQ8iz7wl5dG+TY=
                    </xenc:CipherValue>
                </xenc:CipherData>
                <xenc:ReferenceList>
                    <xenc:DataReference URI="#EncDataId-3"/>
                </xenc:ReferenceList>
            </xenc:EncryptedKey>
        </wsse:Security>
        <wsa:To>https://localhost:8081/axis2/services/sample03</wsa:To>
        <wsa:MessageID>urn:uuid:EE5C34B1DCEF6DBA991250791000372</wsa:MessageID>
        <wsa:Action>urn:echo</wsa:Action>
    </soapenv:Header>
    <soapenv:Body 

xmlns:wsu="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                  wsu:Id="Id-14900151">
        <xenc:EncryptedData Id="EncDataId-3" Type="https://www.w3.org/2001/04/xmlenc#Content">
            <xenc:EncryptionMethod Algorithm="https://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
            <ds:KeyInfo xmlns:ds="https://www.w3.org/2000/09/xmldsig#">
                <wsse:SecurityTokenReference
                        

xmlns:wsse="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                    <wsse:Reference URI="#EncKeyId-E296581B23458CA12512507910022225"/>
                </wsse:SecurityTokenReference>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>HTnMneoskQeLew99eIqCLh+8kUAvKozGjsLMfBN8Ji2QDx64Rl53vKqXYybDQeGidWHn9L7OFSEW
                    6kWuSsDqB+AWQezNgoACcxrNfn7vGwQidD3Kl6aviSaFALzJJkphk29Cip7vSOFmxJn3qIaA82AD
                    rrnPYT57uyPh03XELwrv1Wret3q1uNZ0pnjk6xjYjsQzkAgADUeE/MfWSMdjvpZ6eQ4wwTOmemeh
                    HtVLEdIsKoCyXRBMC9Etiu3KoymArNWRAMgQHvSzBmGxuWCALOHYru8OJpmetZacz5KVqWHifRhP
                    wXFsWOQF3zfBQhJmf4fRiAXkeJ4ZXn3BjT4dz/BVoDaHJFEwK5KY9GRtg0U7Eu3l5k6RNM3ds56N
                    PGP/DhvKJfcFCh4qKVfbWFDVLdeqcRzrHXWuiHTu6BoiwJgzFoQ8vjP6Bw==
                </xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </soapenv:Body>
</soapenv:Envelope>

An asymmetric key is used for encrption. <xenc:EncryptedKey> element contains a

<ds:KeyInfo> element which can be used by the recipient to locate the correct private key from his keystore to decrypt

the symmetric key. <wsse:SecurityTokenReference> element inside that <ds:KeyInfo> element specifies a

ThumbprintSHA1 value that can be used as a key identifier. Then it contains a <xenc:CipherData> which contains the

cipher text of the symmetric key. Decrypting this cipher text using the private key of the recipient with result with the

symmetric key.

Then it has the <xenc:ReferenceList> with a single <xenc:DataReference> element.

That <xenc:DataReference> element refers to an element using the URI fragment #EncDataId-3. If you carefully observe,

you will note that, this URI fragment is the ID of the <xenc:EncryptedData> which is the child element of the soap

body. That <xenc:EncryptedData> element contains a <ds:KeyInfo> element which points to the

<xenc:EncryptedKey> element mentioned above using a SecurityToken Reference. <xenc:CipherValue> contains the

encrypted content of the soap body, which should be decrypted using the symmetric key.

Encryption of SOAP headers is not discussed here, to keep this note short as much as possible.

Refer to

target="_blank" rel="noopener">WS Security Specification

for a comprehensive description about the SOAP message encryption.

Author

Thilina Buddhika, Software Engineer, WSO2, [email protected]