Skip to main content

Encrypting Security Header Elements

This topic describes how to encrypt elements within the WS-Security header in messages sent by InterSystems IRIS web services and web clients. (The tools described here can also be used to encrypt the SOAP body, alone or in combination with security header elements.)

Typically you perform both encryption and signing. This topic describes encryption alone, for simplicity. For information on combining encryption and signing, see Combining Encryption and Signing.

The topic Using Derived Key Tokens for Encryption and Signing describes yet another way to encrypt parts of SOAP messages.

Encrypting Security Header Elements

Unlike the encryption technique shown in the previous topic, the process of encrypting a WS-Security header element requires you to specify how the <EncryptedData> element is connected to the corresponding <EncryptedKey> element.

To encrypt a security header element, do the following:

  1. Optionally include the %soap.inc include file, which defines macros you might need to use.

  2. Create the header element or elements to be encrypted. For example:

     set userToken=##class(%SOAP.Security.UsernameToken).Create("_SYSTEM","SYS")
  3. Obtain a credential set that contains the public key of the entity that will receive the SOAP messages. See Retrieving Credential Sets Programmatically.

    For example:

     set credset=..SecurityIn.Signature.X509Credentials

    Be sure to check the type of the returned object to see if it is an instance of %SYS.X509CredentialsOpens in a new tab, as discussed in Retrieving Credential Sets Programmatically.

  4. Create the encrypted key based on the credential set. To do so, call the CreateX509() class method of %XML.Security.EncryptedKeyOpens in a new tab and optionally specify the second argument. For example:

     set enckey=##class(%XML.Security.EncryptedKey).CreateX509(credset,$$$SOAPWSEncryptNone)

    This method generates a symmetric key and returns an instance of %XML.Security.EncryptedKeyOpens in a new tab which represents the <EncryptedKey> header element. This header element contains the symmetric key, encrypted by the public key contained in the given credential set.

    The second argument specifies whether this key encrypts the SOAP body (in addition to any other uses of the key). The value $$$SOAPWSEncryptNone means that this key will not be used to encrypt the SOAP body. If you omit this argument, the SOAP body is encrypted as well.

  5. Optionally modify the encrypted key instance to use different algorithms. See Specifying the Block Encryption Algorithm and Specifying the Key Transport Algorithm.

  6. For each security header element to encrypt, create an <EncryptedData> element based on that element. To do so, call the Create() class method of %XML.Security.EncryptedDataOpens in a new tab. In this procedure, specify only the second argument, which is the security header element to encrypt. For example:

     set encdata=##class(%XML.Security.EncryptedData).Create(,userToken)
  7. For the <EncryptedKey>, add references to the <EncryptedData> elements. Do the following for each <EncryptedData> element:

    1. Call the Create() class method of %XML.Security.DataReferenceOpens in a new tab and provide the encrypted data instance as the argument.

    2. Call the AddReference() method of the encrypted key instance and provide the data reference as the argument.

    For example:

     set dataref=##class(%XML.Security.DataReference).Create(encdata)
     do enckey.AddReference(dataref)

    This step updates the encrypted key instance to include a pointer to the encrypted data instance.

    If this <EncryptedKey> also encrypts the SOAP body, it automatically includes a reference to the <EncryptedData> element in <Body>.

  8. Add the <EncryptedKey> element to the WS-Security header element. To do so, call the AddSecurityElement() method of the SecurityOut property of your web client or web service. For the element to add, specify your instance of %XML.Security.EncryptedKeyOpens in a new tab.

    For example:

     do ..SecurityOut.AddSecurityElement(enckey)
  9. Add the encrypted security header element to the WS-Security header element. To do so, call the AddSecurityElement() method of the SecurityOut property of your web client or web service. In this case, you specify two arguments:

    1. The security header element to include (not the instance of the %XML.Security.EncryptedDataOpens in a new tab based on that element).

    2. The encrypted key instance. The second argument specifies where to place the item specified by the first argument. If the arguments are A,B, then InterSystems IRIS ensures that A is after B. You specify this so that the recipient processes the encrypted key first and later processes the encrypted security header element that depends on it.

    For example:

     do ..SecurityOut.AddSecurityElement(userToken,enckey)
  10. Send the SOAP message. See the general comments in Adding Security Header Elements.

Basic Examples

The following example invokes a web client and sends a <UsernameToken> that is encrypted. In this example, the body is not encrypted.

  Set client=##class(XMLEncrSecHeader.Client.XMLEncrSecHeaderSoap).%New()

  // Create UsernameToken
  set user="_SYSTEM"
  set pwd="SYS"
  set userToken=##class(%SOAP.Security.UsernameToken).Create(user,pwd)
 
  //get credentials for encryption
  set cred = ##class(%SYS.X509Credentials).GetByAlias("servernopassword") 

  //get EncryptedKey element and add it
  set encropt=$$$SOAPWSEncryptNone   ; means do not encrypt body
  set enckey=##class(%XML.Security.EncryptedKey).CreateX509(cred,encropt)

  //create EncryptedData and add a reference to it from EncryptedKey
  set encdata=##class(%XML.Security.EncryptedData).Create(,userToken)
  set dataref=##class(%XML.Security.DataReference).Create(encdata)
  do enckey.AddReference(dataref)

  //add EncryptedKey to security header
  do client.SecurityOut.AddSecurityElement(enckey) 
  //add UsernameToken and place it after EncryptedKey
  do client.SecurityOut.AddSecurityElement(userToken,enckey) 

  Quit client.Divide(1,2)

This client sends messages like the following:

<?xml version="1.0" encoding="UTF-8" ?>
   <SOAP-ENV:Envelope [parts omitted]>  
      <SOAP-ENV:Header>
         <Security xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
               <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
                  <DigestMethod 
                    xmlns="http://www.w3.org/2000/09/xmldsig#"
                    Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
                  </DigestMethod>
               </EncryptionMethod>
               <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                  <SecurityTokenReference 
                       xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
                     <KeyIdentifier EncodingType="[parts omitted]#Base64Binary"    
                            ValueType="[parts omitted]#ThumbprintSHA1">[omitted]</KeyIdentifier>
                  </SecurityTokenReference>
               </KeyInfo>
               <CipherData>
                  <CipherValue>pftET8jFDEjNC2x[parts omitted]xEjNC2==</CipherValue>
               </CipherData>
               <ReferenceList>
                  <DataReference URI="#Enc-61000920-44DE-471E-B39C-6D08CB17FDC2">
                  </DataReference>
               </ReferenceList>
            </EncryptedKey>
            <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" 
                   Id="Enc-61000920-44DE-471E-B39C-6D08CB17FDC2" 
                   Type="http://www.w3.org/2001/04/xmlenc#Element">
               <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc">
               </EncryptionMethod>
               <CipherData>
                  <CipherValue>wW3ZM5tgPD[parts omitted]tgPD==</CipherValue>
               </CipherData>
            </EncryptedData>
         </Security>  
      </SOAP-ENV:Header>  
      <SOAP-ENV:Body>
         [omitted]
      </SOAP-ENV:Body>
   </SOAP-ENV:Envelope>

As a simple variation, consider the procedure in the preceding section. Suppose that we did the following in step 4 and made no other changes:

 set enckey=##class(%XML.Security.EncryptedKey).CreateX509(credset)

In this case, the messages from the client include an encrypted body and an encrypted <UsernameToken>:

<?xml version="1.0" encoding="UTF-8" ?>
   <SOAP-ENV:Envelope [parts omitted]>  
      <SOAP-ENV:Header>
         <Security xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
               <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
                  <DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" 
                        Algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
                  </DigestMethod>
               </EncryptionMethod>
               <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                  <SecurityTokenReference 
                     xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
                     <KeyIdentifier EncodingType="[parts omitted]#Base64Binary" 
                         ValueType="[parts omitted]#ThumbprintSHA1">
                               5a[parts omitted]dM1r6cM=
                     </KeyIdentifier>
                  </SecurityTokenReference>
               </KeyInfo>
               <CipherData>
                  <CipherValue>TB8uavpr[parts omitted]nZBiMCcg==</CipherValue>
               </CipherData>
               <ReferenceList>
                  <DataReference URI="#Enc-43FE435F-D1D5-4088-A343-0E76D154615A"></DataReference>
                  <DataReference URI="#Enc-55FE109A-3C14-42EB-822B-539E380EDE48"></DataReference>
               </ReferenceList>
            </EncryptedKey>
            <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" 
                 Id="Enc-43FE435F-D1D5-4088-A343-0E76D154615A" 
                 Type="http://www.w3.org/2001/04/xmlenc#Element">
               <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc">
               </EncryptionMethod>
               <CipherData>
                  <CipherValue>G+X7dqI[parts omitted]nojroQ==</CipherValue>
               </CipherData>
            </EncryptedData>
         </Security>  
      </SOAP-ENV:Header>  
      <SOAP-ENV:Body>
         <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" 
                  Id="Enc-55FE109A-3C14-42EB-822B-539E380EDE48" 
                  Type="http://www.w3.org/2001/04/xmlenc#Content">
            <EncryptionMethod Algorithm="[parts omitted]aes128-cbc"></EncryptionMethod>
            <CipherData>
               <CipherValue>YJbzyi[parts omitted]NhJoln==</CipherValue>
            </CipherData>
         </EncryptedData>
      </SOAP-ENV:Body>
   </SOAP-ENV:Envelope>

In comparison to the previous example, in this case, the <EncryptedKey> element includes references to two <EncryptedData> elements. One is the <EncryptedData> element in the security header, which contains the <UsernameToken>; this reference was created and added manually. The other is the <EncryptedData> element in the SOAP body; this reference was added automatically.

FeedbackOpens in a new tab