EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Calulate digest value & signature value

Also by EldoS: CallbackFilter
A component to monitor and control disk activity, track file and directory operations (create, read, write, rename etc.), alter file data, encrypt files, create virtual files.
Posted: 11/13/2013 07:16:20
by Jacob jvandiermen (Standard support level)
Joined: 08/09/2013
Posts: 55

Hello Eldos,

I use your Eldos XMLBlackBox components to generate a xml signature.
The purpose for this is to digitally sign a payment order and send it to the bank.
Hereby I use TElXMLSigner object for signing and a TElXMLKeyInfoX509Data for loading the private key certificate.
The setting for the TElXMLSigner object are:
• CanonicalizationMethod := xcmCanon;
• SignatureMethodType := xmtSig;
• SignatureMethod := xsmRSA_SHA1;

For the <ds:Reference> element we only use the <ds:Object> node for the URI.
So we have only one <ds:Reference> element with <ds:Reference URI=”#Resource1”> and
<ds:Object id=”Resource1”> in the <ds:SignedInfo>
When I generate the xml signature and send it to the bank the xml signature is rejected.
The bank confirms that the xml structure and tags are valid.
To verify what is wrong with my xml signature the bank signs the same payment order I used and generated a xml signature.
I can see that the digest value en signature value are different form the values I calculated in my signature file.
To calculate the digest value you have to canonicalized the <ds:Object id=”Resource1”> node and use this as input for the SHA1. Then we encode the output as Base64.
Now I use a function with the standard SHA1 algorithm to calculate the SHA1 value.
Than I encoded this to Base64. That isn’t the right way to do it. Because my input isn't canonicalized before I I use it in the SHA1 function.
How can I do that ? I think I have to use a TElXMLReference object to calculate the digest value for me.
Furthermore when I manipulate the digest value ( I used the digest value the bank calculated) in the xml and calculate the signature value with TElXMLReference object property URINode set to the <ds:SignedInfo> I don’t get the same result for the signature value as the bank. So evindently I'm not setting the proeperties of the TElXMLReferenceto the right values.

Here is the code I Use:


TXMLSignatureNodes =
                dsig_Signature                =  0,

                dsig_SignedInfo               =  1,

                dsig_CanonicalizationMethod   =  2,

                dsig_SignatureMethod          =  3,

                dsig_Reference                =  4,

                dsig_DigestMethod             =  5,

                dsig_DigestValue              =  6,

                dsig_SignatureValue           =  7,

                dsig_KeyInfo                  =  8,

                dsig_X509Data                 =  9,

                dsig_X509SubjectName          = 10,

                dsig_X509Certificate          = 11,

                dsig_KeyValue                 = 12,

                dsig_RSAKeyValue              = 13,

                dsig_Modulus                  = 14,

                dsig_Exponent                 = 15,

                dsig_Object                   = 16,


    TXMLSignatureTypes =

function encryptStringWithSHA1HashBase64Encoding(strValue: AnsiString): AnsiString;
  index: Integer;
  DCP_sha1: TDCP_sha1;
  digest: array[0..19] of byte;  // SHA-1 produces a 160bit (20byte) output
  digest4Base64: ByteArray;
        DCP_sha1:= TDCP_sha1.Create(nil);
        for index:= low(digest) to high(digest) do
            digest4Base64[index]:= digest[index];
        result:= SBEncoding.Base64EncodeArray(digest4Base64,True);
        on E : Exception do
          result:= '';

function getSignatureValue(fileNameCertificate,keyName,password: string; xmlDOMDocument: TElXMLDOMDocument ;                                           node2Sign: TXMLSignatureNodes; xmlSignatureType: TXMLSignatureTypes): AnsiString;
  index: integer;
  xmlNodeName: string;
  xmlDOMNode, xmlDOMNode4Signing: TElXMLDOMNode;
  xmlDOMNodeList: TElXMLDOMNodeList;
  certificateFileStream: TFileStream;
  xmlReferenceList: TElXMLReferenceList;
  xmlReference: TElXMLReference;
  xmlSigner: TElXMLSigner;
  RSAKeyData: TElXMLKeyInfoRSAData;
  X509KeyInfoData: TElXMLKeyInfoX509Data;
  PGPKeyData: TElXMLKeyInfoPGPData;

  bFound: boolean;
  parentNode: TParentNodeRecord;
   result:= '';
  //For signing we have to point to a node that blackbox calls the reference  
  //object  which we will use for the singing.
  xmlReference:= TElXMLReference.Create;
  xmlReference.DigestMethod := xdmSHA1;

  //assign the node element we are going to use for signing to the refernce
  //object URINode propertie
  xmlNodeName:= replaceUnderscoreByColon(getXMLSignatureNodesEnumNameAsString(node2Sign));
  // just to check if node has all the siblings
  xmlDOMNodeList:= xmlDOMDocument.ChildNodes;
  //We just want the first node from the xml this is the <ds:SigendInfo> node
  xmlDOMNode:= xmlDOMNodeList.Item[pred(xmlDOMNodeList.Length)];
  if xmlDOMNode.HasChildNodes then
    for index:= 0 to Pred(xmlDOMNode.ChildNodes.Length) do
        if AnsiCompareStr(xmlNodeName,xmlDOMNode.ChildNodes.Item[index].NodeName) = 0 then
            //we have to initialize a TElXMLDomNode if we are using the  
            //enveloped or enveloping method for signing
            xmlDOMNode4Signing:= xmlDOMNode.ChildNodes.Item[index].CloneNode(true);
            xmlReference.URINode:= xmlDOMNode.ChildNodes.Item[index];

  xmlReference.URI:= '';
  xmlReference.URI := '#' + xmlNodeName;
  xmlReferenceList:= TElXMLReferenceList.Create;

  //For the actual signing we use the TElXMLSigner object. Because the signing
  //is with a certificate
  //we use a TElXMLKeyInfoX509Data object which will contain the certificate
  xmlSigner:= TElXMLSigner.Create(nil);
  case (xmlSignatureType) of
    TXMLSignatureTypes.xst_Enveloped:   xmlSigner.SignatureType:= xstEnveloped;
    TXMLSignatureTypes.xst_Enveloping:  xmlSigner.SignatureType:= xstEnveloping
  xmlSigner.CanonicalizationMethod := xcmCanon;
  xmlSigner.SignatureMethodType := xmtSig;
  xmlSigner.SignatureMethod := xsmRSA_SHA1;
  xmlSigner.MACMethod:= xmmHMAC_SHA1;
  xmlSigner.References := xmlReferenceList;
  xmlSigner.KeyName := keyName;
  xmlSigner.IncludeKey := True;

  RSAKeyData := TElXMLKeyInfoRSAData.Create(True);
  RSAKeyData.RSAKeyMaterial.Passphrase := password;
  X509KeyInfoData := TElXMLKeyInfoX509Data.Create(True);
  PGPKeyData := TElXMLKeyInfoPGPData.Create(True);

  //We use the TElXMLKeyInfoRSAData object to read all the info from the
    certificateFileStream:= TFileStream.Create(fileNameCertificate, fmOPENREAD or fmShareDenyWrite );
  //If the TElXMLKeyInfoRSAData hasn't got a secret key we can use the TElXMLKeyInfoX509Data object
  //to retieve  de certifiacte information
  if not RSAKeyData.RSAKeyMaterial.SecretKey then
    certificateFileStream.Position := 0;
    loadCertificate(certificateFileStream, RSAKeyData.RSAKeyMaterial.Passphrase,X509KeyInfoData);


  if Assigned(X509KeyInfoData.Certificate) then
      xmlSigner.KeyData := X509KeyInfoData;


  xmlSigner.Signature.SignaturePrefix:= 'dsig';

    if Assigned(xmlSigner)  then
        if Assigned(xmlSigner.Signature) then
          if Assigned(xmlSigner.Signature.SignatureValue) then
            result:= SBEncoding.Base64EncodeArray(xmlSigner.Signature.SignatureValue.Value,True);




Posted: 11/13/2013 07:45:11
by Dmytro Bogatskyy (EldoS Corp.)

The question has been moved to HelpDesk for investigation



Topic viewed 1882 times

Number of guests: 1, registered members: 0, in total hidden: 0


Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!