Securing Caché Web Services
Encrypting the SOAP Body
[Back] [Next]
   
Server:docs1
Instance:LATEST
User:UnknownUser
 
-
Go to:
Search:    

This chapter describes how to encrypt the body of SOAP messages sent by Caché web services and web clients. It discusses the following topics:

The chapters Encrypting Security Header Elements and Using Derived Key Tokens for Encryption and Signing describe how to encrypt security header elements as well as other ways to encrypt the SOAP body.
Overview of Encryption
Caché support for encryption of SOAP messages is based on WS-Security 1.1. In turn, WS-Security follows the XML Encryption specification. According to the latter specification, to encrypt an XML document:
  1. You generate a symmetric key for temporary use.
  2. You use this to encrypt the document (or selected parts of the document).
    You replace those parts of the document with <EncryptedData> elements that contain the encrypted version of the contents.
  3. You encrypt the symmetric key with the public key of the entity to whom you are sending the document.
    You can obtain the public key from an X.509 certificate contained in a request message from that entity. Or you can obtain it ahead of time.
  4. You include the encrypted symmetric key within an <EncryptedKey> element in the same document. The <EncryptedKey> element provides, directly or indirectly, information that enables the recipient to determine the key to use to decrypt this element.
    This information can be contained within the <EncryptedKey> element, or the <EncryptedKey> element can include a direct reference to a binary security token that contains an X.509 certificate or a signed SAML assertion. In the latter case, the security token must be added to the message before the <Signature> element is added.
The document can include multiple <EncryptedKey> elements, applicable to different encrypted parts of the document.
Later chapters of this book describe other ways to encrypt parts of SOAP messages. The details of the messages themselves vary, but the general process is the same and follows the XML Encryption specification: You generate and use symmetric keys, encrypt the symmetric key, and include the encrypted symmetric key in the messages.
Encrypting the SOAP Body
To encrypt the body of SOAP messages, you can use the basic procedure here or the variations described in the subsections. First, the following figure summarizes the process:
In detail, the process is as follows:
  1. Optionally include the %soap.inc include file, which defines macros you might need to use.
  2. Obtain a credential set that contains the public key of the entity that will receive the SOAP messages, typically from the inbound message that you have received. See Retrieving Credential Sets Programmatically,” earlier in this book.
    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.X509Credentials, as discussed in Retrieving Credential Sets Programmatically.”
  3. Create a binary security token that contains the certificate associated with that credential set. To do so, call the CreateX509Token() class method of %SOAP.Security.BinarySecurityToken. For example:
     set bst=##class(%SOAP.Security.BinarySecurityToken).CreateX509Token(credset)
    This method returns an instance of %SOAP.Security.BinarySecurityToken that represents the <BinarySecurityToken> header element.
  4. Add this token 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 method argument, use the token you just created. For example:
     do ..SecurityOut.AddSecurityElement(bst)
  5. Create the encrypted key based on the binary security token. To do so, call the CreateX509() class method of %XML.Security.EncryptedKey. For example:
     set enckey=##class(%XML.Security.EncryptedKey).CreateX509(bst)
    This method generates a symmetric key, uses it to encrypt the SOAP body, and returns an instance of %XML.Security.EncryptedKey which represents the <EncryptedKey> header element. This header element contains the symmetric key, encrypted by the public key contained in the given binary security token.
  6. Optionally modify the encrypted key instance to use different algorithms. See Specifying the Block Encryption Algorithm and Specifying the Key Transport Algorithm,” later in this chapter.
  7. 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.EncryptedKey.
    For example:
     do ..SecurityOut.AddSecurityElement(enckey)
    This step also adds an <EncryptedData> element as the child of the <Body> element.
  8. Send the SOAP message. The SOAP body is encrypted and the WS-Security header is included.
    The WS-Security header includes the <BinarySecurityToken> and <EncryptedKey> elements.
    See the general comments in Adding Security Header Elements,” earlier in this book.
Variation: Using Information That Identifies the Certificate
A <BinarySecurityToken> contains a certificate in serialized, base-64–encoded format. You can omit this token and instead use information that identifies the certificate; the recipient uses this information to retrieve the certificate from the appropriate location. To do so, use the preceding steps, with the following changes:
Reference Options for X.509 Certificates
The section A Brief Look at the WS-Security Header,” earlier in this book, shows one way in which certificates are used in SOAP messages. In the example there, the digital signature consists of two header elements:
There are other possible forms of reference. For example, the <Signature> could instead include a thumbprint of the certificate, and the <BinarySecurityToken> is not needed in the message in this case.
When you create an encrypted key, digital signature, or SAML assertion, you can specify the referenceOption argument, which controls how the newly created element uses the certificate (or more, specifically, the key material) contained in the credentials.
For reference, this argument can have any of the following values. These values are macros defined in the %soap.inc include file:
$$$SOAPWSReferenceDirect
The element includes a direct reference to the binary security token. Specifically, a <KeyInfo> element is created with a <SecurityTokenReference> subelement with a <Reference> subelement whose URI attribute is a local reference to the <BinarySecurityToken>. In order to use this option, you must be sure to also add the security token to the WS-Security header; details are given in the relevant sections.
$$$SOAPWSReferenceThumbprint
The element includes the SHA-1 thumbprint of the X.509 certificate.
$$$SOAPWSReferenceKeyIdentifier
The element includes the SubjectKeyIdentifier of the X.509 certificate.
$$$SOAPWSReferenceIssuerSerial
The element includes a <KeyInfo> element with a <SecurityTokenReference> child with an <X509Data> child that contains an <X509IssuerSerial> element.
$$$KeyInfoX509Certificate
The element includes a <KeyInfo> element with an <X509Data> child that contains an <X509Certificate> element. This usage is not recommended by the WS-Security specification for the <Signature> and <EncryptedKey> elements, but may be used for the <Assertion> element.
$$$KeyInfoX509IssuerSerial
The element includes a <KeyInfo> element with an <X509Data> child that contains an <X509IssuerSerial> element. This usage is not recommended by the WS-Security specification for the <Signature> and <EncryptedKey> elements, but may be used for the <Assertion> element.
$$$KeyInfoX509SKI
The element includes a <KeyInfo> element with an X509Data> child that contains an <X509SKI> element. This usage is not recommended by the WS-Security specification for the <Signature> and <EncryptedKey> elements, but may be used for the <Assertion> element.
$$$KeyInfoX509SubjectName
The element includes a <KeyInfo> element with an <X509Data> child that contains an <X509SubjectName> element. This usage is not recommended by the WS-Security specification for the <Signature> and <EncryptedKey> elements, but may be used for the <Assertion> element.
$$$KeyInfoRSAKey
The element includes a <KeyInfo> element with a <KeyValue> child that contains an <RSAKeyValue> element. This usage is not recommended by the WS-Security specification for the <Signature> and <EncryptedKey> elements, but may be used for the <Assertion> element.
Variation: Using a Signed SAML Assertion
To encrypt using the public key contained in the certificate in a signed SAML assertion, do the following:
  1. Skip steps 1–4 in the preceding steps.
  2. Create a signed SAML assertion with a <SubjectConfirmation> element that uses the Holder-of-key method . See Creating and Adding SAML Tokens,” later in this book.
  3. Create the <EncryptedKey> element. When you do so, use the signed SAML assertion as the first argument to the CreateX509() class method. For example:
     set enckey=##class(%XML.Security.EncryptedKey).CreateX509(signedassertion)
  4. Continue with step 5 in the preceding steps.
Message Encryption Examples
In this example, the web client (not shown) sends a signed request message and the web service sends an encrypted response.
The web service obtains the public key from the client certificate in the signature of the request message and uses that to add an <EncryptedKey> element in its response, which is encrypted. The <EncryptedKey> element is encrypted with the client’s public key and it contains the symmetric key used to encrypt the response message body.
The web service is as follows:
Class XMLEncr.DivideWS Extends %SOAP.WebService
{

Parameter SECURITYIN = "REQUIRE";

Parameter SERVICENAME = "XMLEncryptionDemo";

Parameter NAMESPACE = "http://www.myapp.org";

Method Divide(arg1 As %Numeric = 2, arg2 As %Numeric = 8) As %Numeric [ WebMethod ]
{
  Do ..EncryptBody() 
  Try {
      Set ans=arg1 / arg2
      } Catch {
      Do ..ApplicationError("division error")
      }
  Quit ans
}

Method EncryptBody()
{
  //Retrieve X.509 certificate from the signature of the inbound request
  Set clientsig = ..SecurityIn.Signature
  Set clientcred = clientsig.X509Credentials
  set bst=##class(%SOAP.Security.BinarySecurityToken).CreateX509Token(clientcred)
  do ..SecurityOut.AddSecurityElement(bst)
  
  //generate a symmetric key, encrypt that with the public key of
  //the certificate contained in the token, and create an 
  //<EncryptedKey> element with a direct reference to the token (default)
  Set enc=##class(%XML.Security.EncryptedKey).CreateX509(bst)
  
  //add the <EncryptedKey> element to the security header
  Do ..SecurityOut.AddSecurityElement(enc)
}

///  Create our own method to produce application specific SOAP faults.
Method ApplicationError(detail As %String)
{
    //details omitted
}

}
This service sends response 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">
            <BinarySecurityToken wsu:Id="SecurityToken-4EC1997A-AD6B-48E3-9E91-8D50C8EA3B53" 
                                 EncodingType="[parts omitted]#Base64Binary" 
                                 ValueType="[parts omitted]#X509v3">
                         MIICnDCCAYQ[parts omitted]ngHKNhh
            </BinarySecurityToken>
            <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
               <EncryptionMethod Algorithm="[parts omitted]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">
                     <Reference URI="#SecurityToken-4EC1997A-AD6B-48E3-9E91-8D50C8EA3B53" 
                                ValueType="[parts omitted]#X509v3"></Reference>
                  </SecurityTokenReference>
               </KeyInfo>
               <CipherData>
                  <CipherValue>WtE[parts omitted]bSyvg==</CipherValue>
               </CipherData>
               <ReferenceList>
                  <DataReference URI="#Enc-143BBBAA-B75D-49EB-86AC-B414D818109F"></DataReference>
               </ReferenceList>
            </EncryptedKey>
         </Security>  
      </SOAP-ENV:Header>  
      <SOAP-ENV:Body>
         <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#" 
                        Id="Enc-143BBBAA-B75D-49EB-86AC-B414D818109F" 
                        Type="http://www.w3.org/2001/04/xmlenc#Content">
            <EncryptionMethod Algorithm="[parts omitted]#aes128-cbc"></EncryptionMethod>
            <CipherData>
               <CipherValue>MLwR6hvKE0gon[parts omitted]8njiQ==</CipherValue>
            </CipherData>
         </EncryptedData>
      </SOAP-ENV:Body>
   </SOAP-ENV:Envelope>
Specifying the Block Encryption Algorithm
By default, the message itself is encrypted with $$$SOAPWSaes128cbc. You can specify a different algorithm. To do so, set the Algorithm property of your instance of %XML.Security.EncryptedKey.
Possible values are $$$SOAPWSaes128cbc (the default), $$$SOAPWSaes192cbc and $$$SOAPWSaes256cbc
For example:
 set enckey.Algorithm=$$$SOAPWSaes256cbc
This information is also applicable when you create an <EncryptedKey> in other scenarios, as described later in this book.
Specifying the Key Transport Algorithm
The key transport algorithm is the public key encryption algorithm used for the symmetric keys (see http://www.w3.org/TR/xmlenc-core/). By default, this is $$$SOAPWSrsaoaep. You can instead use $$$SOAPWSrsa15. To do so, call the SetEncryptionMethod() method of your instance of %XML.Security.EncryptedKey, created in the previous step. The argument to this method can be either $$$SOAPWSrsaoaep (the default) or $$$SOAPWSrsa15
For example:
 do enckey.SetEncryptionMethod($$$SOAPWSrsa15)
This information is also applicable when you create an <EncryptedKey> in other scenarios, as described later in this book.