Skip to main content
Previous sectionNext section

Combining Encryption and Signing

You can encrypt and sign within the same message. In most cases, you can simply combine the approaches given in the preceding topics. This topic discusses multiple scenarios.

Signing and Then Encrypting with Asymmetric Keys

To sign and then encrypt (when using asymmetric keys), do the following:

  1. Follow the steps in “Adding a Digital Signature.”

  2. Follow the steps in “Encrypting Security Header Elements.”

    Or follow the steps in “Encrypting the SOAP Body.”

Encrypting and Then Signing with Asymmetric Keys

To encrypt only the SOAP body and then add a digital signature (when using asymmetric keys), do the following:

  1. Follow the steps in “Encrypting the SOAP Body.”

  2. Follow the steps in “Adding a Digital Signature.”

To encrypt any security header elements and then add a digital signature (when using asymmetric keys), it is necessary to use a top-level <ReferenceList> element, which has not been necessary in earlier parts of this book. In this case, do the following:

  1. Follow steps 1 — 4 in “Encrypting Security Header Elements,” earlier in this book.

  2. 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.EncryptedData. In this procedure, specify all three arguments:

    1. The encrypted key instance that you created in the previous steps.

    2. The security header element to encrypt.

    3. $$$SOAPWSReferenceEncryptedKey, which specifies how the <EncryptedData> uses the encrypted key instance.

    For example:

     set refopt=$$$SOAPWSReferenceEncryptedKey
     set encdata=##class(%XML.Security.EncryptedData).Create(enckey,userToken,refopt)
    Copy code to clipboard
  3. Create a <ReferenceList> element. To do so, call the %New() method of the %XML.Security.ReferenceList class. For example:

     set reflist=##class(%XML.Security.ReferenceList).%New() 
    Copy code to clipboard
  4. Within this <ReferenceList>, create a <Reference> that points to the <EncryptedData> elements. To do so, do the following for each <EncryptedData>:

    1. Call the Create() class method of %XML.Security.DataReference and specify the encrypted data instance as the argument. This method returns an instance of %XML.Security.DataReference.

    2. Call the AddReference() method of your reference list instance and specify the data reference instance as the argument.

    For example:

     set dataref=##class(%XML.Security.DataReference).Create(encdata)
     do reflist.AddReference(dataref)
    Copy code to clipboard
  5. Add the <ReferenceList> 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 reference list instance. For example:

     do ..SecurityOut.AddSecurityElement(reflist)
    Copy code to clipboard
    Note:

    The <ReferenceList> element must be added before you add the other items.

  6. Add the <EncryptedKey> element to the WS-Security header element. Use the AddSecurityElement(). For example:

     do ..SecurityOut.AddSecurityElement(enckey)
    Copy code to clipboard
  7. 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.EncryptedData 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)
    Copy code to clipboard

    Or, if the encrypted security header element is <Signature>, use AddSecurityElement() instead.

  8. Follow the steps “Adding a Digital Signature,” earlier in this book.

  9. Send the SOAP message. See the general comments in “Adding Security Header Elements,” earlier in this book.

Signing and Then Encrypting with Symmetric Keys

To sign and then encrypt (when using symmetric keys):

  1. Follow the steps in “Using a <DerivedKeyToken> for Encryption.”

  2. Follow the steps in “Using a <DerivedKeyToken> for Signing.”

Using <DerivedKeyToken> Elements

The following example signs and then encrypts using symmetric keys. It creates an <EncryptedKey> element using the public key of the message recipient and then uses that to generate two <DerivedKeyToken> elements, one for signing and one for encryption:

 // create UsernameToken
  set userToken=##class(%SOAP.Security.UsernameToken).Create("_SYSTEM","SYS")

  //get credentials of message recipient
  set x509alias = "servernopassword"
  set cred = ##class(%SYS.X509Credentials).GetByAlias(x509alias) 

  //get EncryptedKey element
  set enc=##class(%XML.Security.EncryptedKey).CreateX509(cred,$$$SOAPWSEncryptNone)
  do client.SecurityOut.AddSecurityElement(enc)

  // get derived keys
  set dkenc=##class(%SOAP.WSSC.DerivedKeyToken).Create(enc,$$$SOAPWSReferenceEncryptedKey)
  do client.SecurityOut.AddSecurityElement(dkenc)
  set dksig=##class(%SOAP.WSSC.DerivedKeyToken).Create(enc,$$$SOAPWSReferenceEncryptedKey)
  do client.SecurityOut.AddSecurityElement(dksig)

  // create and add signature
  set sig=##class(%XML.Security.Signature).Create(dksig,,$$$SOAPWSReferenceDerivedKey)
  do client.SecurityOut.AddSecurityElement(sig) 
 
  // ReferenceList to encrypt Body and Username. Add after signing
  set reflist=##class(%XML.Security.ReferenceList).%New()
  set refopt=$$$SOAPWSReferenceDerivedKey
  set encryptedData=##class(%XML.Security.EncryptedData).Create(dkenc,userToken,refopt)
  set dataref=##class(%XML.Security.DataReference).Create(encryptedData)
  do reflist.AddReference(dataref)
  set encryptedData=##class(%XML.Security.EncryptedData).Create(dkenc,"",refopt)
  set dataref=##class(%XML.Security.DataReference).Create(encryptedData)
  do reflist.AddReference(dataref)
  do client.SecurityOut.AddSecurityElement(reflist)
  
  // Add UsernameToken; force after ReferenceList so that it can decrypt properly
  do client.SecurityOut.AddSecurityElement(userToken,reflist)
Copy code to clipboard

This client sends messages like the following:

<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#" 
                       Id="Id-A0CBB4B7-18A8-40C1-A2CD-C0C383BF9531">
            <EncryptionMethod Algorithm="[parts omitted]#rsa-oaep-mgf1p">
               <DigestMethod xmlns="http://www.w3.org/2000/09/xmldsig#" 
                             Algorithm="[parts omitted]#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">
              5afOHv1w7WSXwDyz6F3WdM1r6cM=</KeyIdentifier>
               </SecurityTokenReference>
            </KeyInfo>
            <CipherData>
               <CipherValue>fR4hoJy4[parts omitted]Gmq1xg==</CipherValue>
            </CipherData>
         </EncryptedKey>
         <DerivedKeyToken xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" 
                          xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" 
                          wsu:Id="Enc-43F73EB2-77EC-4D72-9DAD-17B1781BC49C">
            <SecurityTokenReference xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
               <Reference URI="#Id-A0CBB4B7-18A8-40C1-A2CD-C0C383BF9531"></Reference>
            </SecurityTokenReference>
            <Nonce>Q1wDt0PSSLmARcy+Pg49Sg==</Nonce>
         </DerivedKeyToken>
         <DerivedKeyToken xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" 
                          xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" 
                          wsu:Id="Enc-ADE64310-E695-4630-9DA6-A818EF5CEE9D">
            <SecurityTokenReference xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
               <Reference URI="#Id-A0CBB4B7-18A8-40C1-A2CD-C0C383BF9531"></Reference>
            </SecurityTokenReference>
            <Offset>0</Offset>
            <Length>24</Length>
            <Nonce>PvaakhgdxoBVLR6I1j6KGA==</Nonce>
         </DerivedKeyToken>
         <ReferenceList xmlns="http://www.w3.org/2001/04/xmlenc#">
            <DataReference URI="#Enc-F8013636-5339-4C25-87CD-C241330865F5"></DataReference>
            <DataReference URI="#Enc-CDF877AC-8347-4903-97D9-E8238C473DC4"></DataReference>
         </ReferenceList>
         <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" 
                        Id="Enc-F8013636-5339-4C25-87CD-C241330865F5" 
                        Type="http://www.w3.org/2001/04/xmlenc#Element">
            <EncryptionMethod Algorithm="[parts omitted]#aes256-cbc"></EncryptionMethod>
            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
               <SecurityTokenReference xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
                  <Reference URI="#Enc-43F73EB2-77EC-4D72-9DAD-17B1781BC49C"></Reference>
               </SecurityTokenReference>
            </KeyInfo>
            <CipherData>
               <CipherValue>ebxkmD[parts omitted]ijtJg==</CipherValue>
            </CipherData>
         </EncryptedData>
         <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
               <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
               </CanonicalizationMethod>
               <SignatureMethod Algorithm="[parts omitted]#hmac-sha1"></SignatureMethod>
               <Reference URI="#Body-C0D7FF05-EE59-41F6-939D-7B2F2B883E5F">
                  <Transforms>
                     <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
                  </Transforms>
                  <DigestMethod Algorithm="[parts omitted]#sha1"></DigestMethod>
                  <DigestValue>vic7p2selz4Wvm1nAX67p0xF1VI=</DigestValue>
               </Reference>
            </SignedInfo>
            <SignatureValue>TxIBa4a8wX5oFN+eyjjsUuLdn7U=</SignatureValue>
            <KeyInfo>
               <SecurityTokenReference xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
                  <Reference URI="#Enc-ADE64310-E695-4630-9DA6-A818EF5CEE9D"></Reference>
               </SecurityTokenReference>
            </KeyInfo>
         </Signature>
      </Security>  
   </SOAP-ENV:Header>  
   <SOAP-ENV:Body wsu:Id="Body-C0D7FF05-EE59-41F6-939D-7B2F2B883E5F">
      <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" 
                     Id="Enc-CDF877AC-8347-4903-97D9-E8238C473DC4" 
                     Type="http://www.w3.org/2001/04/xmlenc#Content">
         <EncryptionMethod Algorithm="[parts omitted]#aes256-cbc"></EncryptionMethod>
         <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SecurityTokenReference xmlns="[parts omitted]oasis-200401-wss-wssecurity-secext-1.0.xsd">
               <Reference URI="#Enc-43F73EB2-77EC-4D72-9DAD-17B1781BC49C"></Reference>
            </SecurityTokenReference>
         </KeyInfo>
         <CipherData>
            <CipherValue>vYtzDsv[parts omitted]GohGsL6</CipherValue>
         </CipherData>
      </EncryptedData>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Copy code to clipboard

Encrypting and Then Signing with Symmetric Keys

To encrypt and then sign (when using symmetric keys):

  1. Follow the steps in “Using a <DerivedKeyToken> for Signing.”

  2. Follow the steps in “Using a <DerivedKeyToken> for Encryption.”

Order of Security Header Elements

In general, you should add security elements to the security header in the order in which you perform the processing. The message recipient should be able to process the message from beginning to end without having any forward references.

The following table lists the resulting order of security header elements when you use asymmetric keys (these scenarios use asymmetric key bindings):

Signing and then encrypting Encrypting and then signing
  1. Other header elements
  2. <EncryptedKey>
  3. <Signature>
  1. Other header elements
  2. <EncryptedKey>
  3. <Signature>
  4. <ReferenceList>

The following table lists the resulting order of security header elements when you use symmetric keys (these scenarios use symmetric key bindings):

Signing and then encrypting Encrypting and then signing
  1. Other header elements
  2. <EncryptedKey>
  3. <DerivedKeyToken>
  4. <DerivedKeyToken>
  5. <ReferenceList>
  6. <Signature>
  1. Other header elements
  2. <EncryptedKey>
  3. <DerivedKeyToken>
  4. <DerivedKeyToken>
  5. <Signature>
  6. <ReferenceList>