Skip to main content

Adding a Digital Signature

Adding a Digital Signature

To digitally sign a SOAP message, you can use the basic procedure here or the variations described in the following parts of the topic.

First, the following figure summarizes the process:

Using a certificate, the steps are to to create the security objects and then add them to the header.

In detail, the process is as follows:

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

  2. If you want to sign any security header elements, create those security header elements. For example:

     set utoken=##class(%SOAP.Security.UsernameToken).Create("_SYSTEM","SYS")
  3. Create an instance of %SYS.X509CredentialsOpens in a new tab, as described in Retrieving Credential Sets Programmatically. This InterSystems IRIS credential set must contain your own certificate, and you must provide the private key password, if it has not already been loaded. For example:

     Set x509alias = "servercred" 
     Set pwd = "mypassword" 
     Set credset = ##class(%SYS.X509Credentials).GetByAlias(x509alias,mypassword)
    
  4. 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.BinarySecurityTokenOpens in a new tab. For example:

     set bst=##class(%SOAP.Security.BinarySecurityToken).CreateX509Token(credset)

    This method returns an instance of %SOAP.Security.BinarySecurityTokenOpens in a new tab that represents the <BinarySecurityToken> header element.

  5. 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)
  6. Create the <Signature> element based on the binary security token. To do so, call the CreateX509() class method of %XML.Security.SignatureOpens in a new tab. For example:

     set dsig=##class(%XML.Security.Signature).CreateX509(bst)

    This method returns an instance of %XML.Security.SignatureOpens in a new tab that represents the <Signature> header element. The <Signature> element applies to a default set of parts of the message; you can specify a different set of parts.

    Formally, this method has the following signature:

    classmethod CreateX509(credentials As %SYS.X509Credentials = "", 
                           signatureOptions As %Integer, 
                           referenceOption As %Integer, 
                           Output status As %Status) as %XML.Security.Signature
    

    Where:

  7. Add the digital signature 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 argument, specify the signature object created in the previous step. For example:

     do ..SecurityOut.AddSecurityElement(dsig)
  8. Send the SOAP message. See the general comments in Adding Security Header Elements.

Example

This example shows a web service that signs its response messages.

To make this example work in your own environment, first do the following:

  • Create a certificate for the server.

  • Load this certificate into InterSystems IRIS on the server side, creating credentials with the name servercred. When you do so, also load the private key file and provide its password (so that the web service does not have to provide that password when it signs its response message.)

    The web service refers to an InterSystems IRIS credential set with this exact name.

Class DSig.DivideWS Extends %SOAP.WebService
{

///  Name of the Web service.
Parameter SERVICENAME = "DigitalSignatureDemo";

///  SOAP namespace for the Web service
Parameter NAMESPACE = "http://www.myapp.org";

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

/// use in documentation
/// signs and includes a binary security token
Method SignResponses()
{
 //Add timestamp because that's commonly done
 Set ts=##class(%SOAP.Security.Timestamp).Create()
 Do ..SecurityOut.AddSecurityElement(ts)

 //access previously stored server certificate & private key file
 //no need to use private key file password, because that has been saved
 Set x509alias = "servercred" 
 Set cred = ##class(%SYS.X509Credentials).GetByAlias(x509alias)
 set bst=##class(%SOAP.Security.BinarySecurityToken).CreateX509Token(cred)
 do ..SecurityOut.AddSecurityElement(bst)

 //Create WS-Security Signature object
 Set signature=##class(%XML.Security.Signature).CreateX509(bst)
 
 //Add WS-Security Signature object to the outbound message
 Do ..SecurityOut.AddSecurityElement(signature)
 Quit
}


///  Create our own method to produce application specific SOAP faults.
Method ApplicationError(detail As %String)
{
    Set fault=##class(%SOAP.Fault).%New()
    Set fault.faultcode=$$$FAULTServer
    Set fault.detail=detail
    Set fault.faultstring="Application error"
    // ReturnFault must be called to send the fault to the client.
    // ReturnFault will not return here.
    Do ..ReturnFault(fault)
}


}
FeedbackOpens in a new tab