Securing Caché Web Services
Combining Encryption and Signing
[Home] [Back] [Next]
InterSystems: The power behind what matters   
Class Reference   
Search:    

You can encrypt and sign within the same message. In most cases, you can simply combine the approaches given in the preceding chapters. This chapter discusses the following 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. 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)
  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() 
  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)
  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)
    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)
  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 Caché 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)
    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):
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)
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>
Encrypting and Then Signing with Symmetric Keys
To encrypt and then sign (when using symmetric keys):
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
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