Community articleValidateHMACWithHashedSecret function
Added by IBM contributorIBM on July 26, 2013
Rate this article 1 starsRate this article 2 starsRate this article 3 starsRate this article 4 starsRate this article 5 stars


This function determines whether an HMAC signature is valid. HMAC signatures include both Authenticated Clickwrap and Signature Pad signatures.
For Authenticated Clickwrap signatures, you must know the hash of the signer's shared secret to use this function. For Signature Pad signatures, you may use this function without the shared secret if the signature was created without one. In any case, the shared secret should be available from a corporate database or other system.
This function will also notarize (that is, digitally sign) a valid HMAC signature if you provide a digital certificate. However, notarization will not occur if the signature does not include a shared secret. Once notarized, you must use the VerifySignature function to validate the signature.


   Function ValidateHMACWithHashedSecret(
			hashedSecret As Variant, 
      theServerCert As ICertificate, 
      theStatus As Long
      ) As Integer


Table 1. Function parameters
hashedSecretVariantThe hash of the shared secret that identifies the user. This should be available from a corporate database or other system.
If there is more than one shared secret, you must concatenate the strings with no separating characters and then hash the combined secret. For example, if the secrets were "blue" and "red", you would pass the hash of "bluered" to the function.
If there is no shared secret, pass an empty string.
You must encode the byte array as follows:
Authenticated Clickwrap (HMAC) UTF-8
Signature Pad UTF-16LE
The method for doing this depends on the software library you are using to interface with the COM API.
Note that the function expects the hashed secret to be a single-byte binary array. Using a double-byte binary array produces an incorrect result.
theCertificateICertificateThe server certificate.
If you pass null, the function will verify the HMAC signature but will not sign it.
If you pass in a certificate and if the HMAC signature is valid, the function will use the private key of the certificate to digitally sign the HMAC signature. This signature is appended to the signature item, and can be verified using UFLVerifySignature.
theStatusLongThis is a status flag that reports whether the operation was successful. Possible values are:
SUSTATUS_OK — the operation was successful.
SUSTATUS_CANCELLED — the operation was cancelled by the user.
SUSTATUS_INPUT_REQUIRED — the operation required user input, but could not receive it (for example, it was run on a server with no user).


A constant if the verification is successful, or throws an exception if an error occurs. The following table lists the possible return values:
Table 2. return codes
CodeNumeric ValueStatus
UFL_DS_OK0The signature is verified.
UFL_DS_ALGORITHM UNAVAILABLE13590The appropriate verification engine for the signature is not available.
UFL_DS_F2MATCHSIGNER13529The certificate does not match the signer's name.
UFL_DS_FAILED AUTHENTICATION1272The signature is invalid or the secret used is incorrect.
UFL_DS_HASHCOMPFAILED13527The document has been tampered with.
UFL_DS_NOSIGNATURE13526There is no signature.
UFL_DS_NOT AUTHENTICATED1240The signer cannot be authenticated.
UFL_DS_UNEXPECTED13589An unexpected error occurred.
UFL_DS_UNVERIFIABLE859The signature cannot be verified.


The following function validates an HMAC signature using a hashed secret. First, the function uses DereferenceEx and GetLiteralByRefEx to locate the signature item in a form. It then uses GetEngineCertificateList and GetDataByPath to locate a server signing certificate. Next, it uses GetSignature and GetDataByPath to get the signer's common name and Hash to create a hashed secret. Finally, it uses ValidateHMACWithHashedSecret to determine if the HMAC signature is valid, and returns "Valid" or "Invalid", as appropriate.
Note that this example also relies on a second function called StringToBinary. This function converts a string to a single-byte binary array, which is required for the hash function. This prevents COM from converting the string to a double-byte array before hashing it, which would produce an incorrect result.
   Function ValidateHMACSigHashed(Form)
      Dim SigObject, XFDL, HashObject, SecurityManager  ' objects
      Dim TheCerts  ' CertificateList
      Dim Cert, SigningCert  ' ICertificate
      Dim SignerName, SharedSecret, HashedSecret, CommonName, _
         SigItemRef  ' Strings
      Dim Validation  ' Integer
      Dim TempNode, SigNode  ' IFormNodeP
      Set TempNode = Form
      ' Get the SignatureButton node
      Set TempNode = Form.DereferenceEx(vbNullString, _
         "PAGE1.HMACSignatureButton", 0, UFL_ITEM_REFERENCE, Nothing)
      ' Get the name of the signature item
      SigItemRef = TempNode.GetLiteralByRefEx(vbNullString, "signature", _
         0, vbNullString, Nothing)
      ' Get the signature item node
      Set SigNode = TempNode.DereferenceEx(vbNullString, SigItemRef, 0, _
         UFL_ITEM_REFERENCE, Nothing)
      ' Get available server certificates for Generic RSA signing
      Set XFDL = CreateObject("PureEdge.xfdl_XFDL")
      Set TheCerts = XFDL.GetEngineCertificateList("Generic RSA", 1) 
         ' vbNull
      ' Locate the certificate that has a common name of "User1-CP.02.01".
      ' This is the certificate we will use when verifying the signature.
      For Each Cert in TheCerts
         CommonName = Cert.GetDataByPath("SigningCert: Subject: CN", _
            False, 1) ' vbNull
         If CommonName = "User1-CP.02.01" Then
            Set SigningCert = Cert
         End If
      ' Get the signature object from the signature node
      Set SigObject = SigNode.GetSignature
      ' Get the signer's name from the signature object
      SignerName = SigObject.GetDataByPath("SigningCert: Subject: CN", _
         False, 1) ' vbNull
      ' Include code that matches the signer's identity to a shared secret
      ' that is hashed, and sets SharedSecret to match. In most cases, this 
      ' would be a database lookup. For the purposes of this example, we will
      ' use the Hash function to assign a hashed value to HashedSecret.
      ' Get the Security Manager object
      Set SecurityManager = _
      ' Get the Hash object
      Set HashObject = SecurityManager.LookupHashAlgorithm("sha1")
      ' Set the Hashed secret. First convert the secret to a single-byte
      ' binary array, then hash the secret.
      SharedSecret = StringToBinary("secret")      
      HashedSecret = HashObject.Hash(SharedSecret)
      ' Validate the signature
      Validation = SigNode.ValidateHMACWithHashedSecret(HashedSecret, _
         SigningCert, 1) ' vbNull
      ' Check the validation code and return either "Valid" or "Invalid"
      If Validation = UFL_DS_OK Then
         ValidateHMACSigHashed = "Valid"
         ValidateHMACSigHashed = "Invalid"
      End If
   End Function
   ' The following function is required to convert a string to a single-byte binary 
   '   array before hashing that string. This prevents COM from converting
   '  the string to a multi-byte format, which would produce and incorrect
   '  hash.
   Function StringToBinary(String)
      Dim Counter, Binary
      For Counter = 1 to len(String)
         Binary = Binary & ChrB(Asc(Mid(String, Counter, 1)))
      StringToBinary = Binary
   End Function

Parent topic:
FormNodeP functions