Sample code for 30+ languages & platforms
SQL Server

RFC3161 Timestamp Client - Fetch from Timestamp Authority (TSA) and Verify

See more HTTP Examples

Sends an RFC 3161 timestamp request to a TSA (Timestamp Authority) server and validates the timestamp token response.

Chilkat SQL Server Downloads

SQL Server
-- Important: See this note about string length limitations for strings returned by sp_OAMethod calls.
--
CREATE PROCEDURE ChilkatSample
AS
BEGIN
    DECLARE @hr int
    -- Important: Do not use nvarchar(max).  See the warning about using nvarchar(max).
    DECLARE @sTmp0 nvarchar(4000)
    DECLARE @success int
    SELECT @success = 0

    -- This requires the Chilkat API to have been previously unlocked.
    -- See Global Unlock Sample for sample code.

    -- First sha-256 hash the data that is to be timestamped.
    -- In this example, the data is the string "Hello World"

    DECLARE @crypt int
    EXEC @hr = sp_OACreate 'Chilkat.Crypt2', @crypt OUT
    IF @hr <> 0
    BEGIN
        PRINT 'Failed to create ActiveX component'
        RETURN
    END

    EXEC sp_OASetProperty @crypt, 'HashAlgorithm', 'sha256'
    EXEC sp_OASetProperty @crypt, 'EncodingMode', 'base64'
    DECLARE @base64Hash nvarchar(4000)
    EXEC sp_OAMethod @crypt, 'HashStringENC', @base64Hash OUT, 'Hello World'

    DECLARE @http int
    EXEC @hr = sp_OACreate 'Chilkat.Http', @http OUT

    DECLARE @requestToken int
    EXEC @hr = sp_OACreate 'Chilkat.BinData', @requestToken OUT

    DECLARE @optionalPolicyOid nvarchar(4000)
    SELECT @optionalPolicyOid = ''
    DECLARE @addNonce int
    SELECT @addNonce = 0
    DECLARE @requestTsaCert int
    SELECT @requestTsaCert = 1

    -- Create a time-stamp request token
    EXEC sp_OAMethod @http, 'CreateTimestampRequest', @success OUT, 'sha256', @base64Hash, @optionalPolicyOid, @addNonce, @requestTsaCert, @requestToken
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @http, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @crypt
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @requestToken
        RETURN
      END

    -- Send the time-stamp request token to the TSA.
    -- This is the equivalent of the following CURL command:
    -- curl -H "Content-Type: application/timestamp-query" --data-binary '@file.tsq' https://freetsa.org/tsr > file.tsr
    DECLARE @tsaUrl nvarchar(4000)
    SELECT @tsaUrl = 'https://freetsa.org/tsr'
    -- Another timestamp server you could try is: http://timestamp.digicert.com
    SELECT @tsaUrl = 'http://timestamp.digicert.com'
    DECLARE @resp int
    EXEC @hr = sp_OACreate 'Chilkat.HttpResponse', @resp OUT

    EXEC sp_OAMethod @http, 'HttpBd', @success OUT, 'POST', @tsaUrl, @requestToken, 'application/timestamp-query', @resp
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @http, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @crypt
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @requestToken
        EXEC @hr = sp_OADestroy @resp
        RETURN
      END

    -- Get the timestamp reply from the HTTP response object.
    DECLARE @timestampReply int
    EXEC @hr = sp_OACreate 'Chilkat.BinData', @timestampReply OUT

    EXEC sp_OAMethod @resp, 'GetBodyBd', @success OUT, @timestampReply

    -- Show the base64 encoded timestamp reply.
    EXEC sp_OAMethod @timestampReply, 'GetEncoded', @sTmp0 OUT, 'base64'
    PRINT @sTmp0

    -- Let's verify the timestamp reply against the TSA's cert, which we've previously downloaded.
    -- See https://freetsa.org/index_en.php
    DECLARE @tsaCert int
    EXEC @hr = sp_OACreate 'Chilkat.Cert', @tsaCert OUT

    EXEC sp_OAMethod @tsaCert, 'LoadFromFile', @success OUT, 'qa_data/certs/freetsa.org.cer'
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @tsaCert, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @crypt
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @requestToken
        EXEC @hr = sp_OADestroy @resp
        EXEC @hr = sp_OADestroy @timestampReply
        EXEC @hr = sp_OADestroy @tsaCert
        RETURN
      END

    -- The VerifyTimestampReply method will return one of the following values:
    -- -1:  The timestampReply does not contain a valid timestamp reply.
    -- -2: The  timestampReply is a valid timestamp reply, but failed verification using the public key of the tsaCert.
    -- 0:  Granted and verified.
    -- 1: Granted and verified, with mods (see RFC 3161)
    -- 2: Rejected.
    -- 3: Waiting.
    -- 4: Revocation Warning
    -- 5: Revocation Notification
    DECLARE @pkiStatus int
    EXEC sp_OAMethod @http, 'VerifyTimestampReply', @pkiStatus OUT, @timestampReply, @tsaCert
    IF @pkiStatus < 0
      BEGIN
        EXEC sp_OAGetProperty @http, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @crypt
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @requestToken
        EXEC @hr = sp_OADestroy @resp
        EXEC @hr = sp_OADestroy @timestampReply
        EXEC @hr = sp_OADestroy @tsaCert
        RETURN
      END


    PRINT 'pkiStatus = ' + @pkiStatus

    DECLARE @json int
    EXEC @hr = sp_OACreate 'Chilkat.JsonObject', @json OUT

    EXEC sp_OAMethod @http, 'GetLastJsonData', NULL, @json

    EXEC sp_OASetProperty @json, 'EmitCompact', 0
    EXEC sp_OAMethod @json, 'Emit', @sTmp0 OUT
    PRINT @sTmp0

    -- The JSON looks like the following.

    -- Use this online tool to generate parsing code from sample JSON: 
    -- Generate Parsing Code from JSON

    -- {
    --   "timestampReply": {
    --     "pkiStatus": {
    --       "value": 0,
    --       "meaning": "granted"
    --     }
    --   },
    --   "pkcs7": {
    --     "verify": {
    --       "digestAlgorithms": [
    --         "sha256"
    --       ],
    --       "signerInfo": [
    --         {
    --           "cert": {
    --             "serialNumber": "04CD3F8568AE76C61BB0FE7160CCA76D",
    --             "issuerCN": "DigiCert SHA2 Assured ID Timestamping CA",
    --             "digestAlgOid": "2.16.840.1.101.3.4.2.1",
    --             "digestAlgName": "SHA256"
    --           },
    --           "contentType": "1.2.840.113549.1.9.16.1.4",
    --           "signingTime": "200405023019Z",
    --           "messageDigest": "f14zOsdnN9vyyV3HjjBiLzNDi1PF28hAFMODxNkNRZs=",
    --           "signingAlgOid": "1.2.840.113549.1.1.1",
    --           "signingAlgName": "RSA-PKCSV-1_5",
    --           "authAttr": {
    --             "1.2.840.113549.1.9.3": {
    --               "name": "contentType",
    --               "oid": "1.2.840.113549.1.9.16.1.4"
    --             },
    --             "1.2.840.113549.1.9.5": {
    --               "name": "signingTime",
    --               "utctime": "200405023019Z"
    --             },
    --             "1.2.840.113549.1.9.16.2.12": {
    --               "name": "signingCertificate",
    --               "der": "MBowGDAWBBQDJb1QXtqWMC3CL0+gHkwovig0xQ=="
    --             },
    --             "1.2.840.113549.1.9.4": {
    --               "name": "messageDigest",
    --               "digest": "f14zOsdnN9vyyV3HjjBiLzNDi1PF28hAFMODxNkNRZs="
    --             }
    --           }
    --         }
    --       ]
    --     }
    --   }
    -- }

    DECLARE @signingTime int
    EXEC @hr = sp_OACreate 'Chilkat.DtObj', @signingTime OUT

    DECLARE @authAttrSigningTimeUtctime int
    EXEC @hr = sp_OACreate 'Chilkat.DtObj', @authAttrSigningTimeUtctime OUT

    DECLARE @strVal nvarchar(4000)

    DECLARE @certSerialNumber nvarchar(4000)

    DECLARE @certIssuerCN nvarchar(4000)

    DECLARE @certDigestAlgOid nvarchar(4000)

    DECLARE @certDigestAlgName nvarchar(4000)

    DECLARE @contentType nvarchar(4000)

    DECLARE @messageDigest nvarchar(4000)

    DECLARE @signingAlgOid nvarchar(4000)

    DECLARE @signingAlgName nvarchar(4000)

    DECLARE @authAttrContentTypeName nvarchar(4000)

    DECLARE @authAttrContentTypeOid nvarchar(4000)

    DECLARE @authAttrSigningTimeName nvarchar(4000)

    DECLARE @authAttrSigningCertificateName nvarchar(4000)

    DECLARE @authAttrSigningCertificateDer nvarchar(4000)

    DECLARE @authAttrMessageDigestName nvarchar(4000)

    DECLARE @authAttrMessageDigestDigest nvarchar(4000)

    DECLARE @timestampReplyPkiStatusValue int
    EXEC sp_OAMethod @json, 'IntOf', @timestampReplyPkiStatusValue OUT, 'timestampReply.pkiStatus.value'
    DECLARE @timestampReplyPkiStatusMeaning nvarchar(4000)
    EXEC sp_OAMethod @json, 'StringOf', @timestampReplyPkiStatusMeaning OUT, 'timestampReply.pkiStatus.meaning'
    DECLARE @i int
    SELECT @i = 0
    DECLARE @count_i int
    EXEC sp_OAMethod @json, 'SizeOfArray', @count_i OUT, 'pkcs7.verify.digestAlgorithms'
    WHILE @i < @count_i
      BEGIN
        EXEC sp_OASetProperty @json, 'I', @i
        EXEC sp_OAMethod @json, 'StringOf', @strVal OUT, 'pkcs7.verify.digestAlgorithms[i]'
        SELECT @i = @i + 1
      END
    SELECT @i = 0
    EXEC sp_OAMethod @json, 'SizeOfArray', @count_i OUT, 'pkcs7.verify.signerInfo'
    WHILE @i < @count_i
      BEGIN
        EXEC sp_OASetProperty @json, 'I', @i
        EXEC sp_OAMethod @json, 'StringOf', @certSerialNumber OUT, 'pkcs7.verify.signerInfo[i].cert.serialNumber'
        EXEC sp_OAMethod @json, 'StringOf', @certIssuerCN OUT, 'pkcs7.verify.signerInfo[i].cert.issuerCN'
        EXEC sp_OAMethod @json, 'StringOf', @certDigestAlgOid OUT, 'pkcs7.verify.signerInfo[i].cert.digestAlgOid'
        EXEC sp_OAMethod @json, 'StringOf', @certDigestAlgName OUT, 'pkcs7.verify.signerInfo[i].cert.digestAlgName'
        EXEC sp_OAMethod @json, 'StringOf', @contentType OUT, 'pkcs7.verify.signerInfo[i].contentType'
        EXEC sp_OAMethod @json, 'DtOf', @success OUT, 'pkcs7.verify.signerInfo[i].signingTime', 0, @signingTime
        EXEC sp_OAMethod @json, 'StringOf', @messageDigest OUT, 'pkcs7.verify.signerInfo[i].messageDigest'
        EXEC sp_OAMethod @json, 'StringOf', @signingAlgOid OUT, 'pkcs7.verify.signerInfo[i].signingAlgOid'
        EXEC sp_OAMethod @json, 'StringOf', @signingAlgName OUT, 'pkcs7.verify.signerInfo[i].signingAlgName'
        EXEC sp_OAMethod @json, 'StringOf', @authAttrContentTypeName OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.3".name'
        EXEC sp_OAMethod @json, 'StringOf', @authAttrContentTypeOid OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.3".oid'
        EXEC sp_OAMethod @json, 'StringOf', @authAttrSigningTimeName OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.5".name'
        EXEC sp_OAMethod @json, 'DtOf', @success OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.5".utctime', 0, @authAttrSigningTimeUtctime
        EXEC sp_OAMethod @json, 'StringOf', @authAttrSigningCertificateName OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.16.2.12".name'
        EXEC sp_OAMethod @json, 'StringOf', @authAttrSigningCertificateDer OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.16.2.12".der'
        EXEC sp_OAMethod @json, 'StringOf', @authAttrMessageDigestName OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.4".name'
        EXEC sp_OAMethod @json, 'StringOf', @authAttrMessageDigestDigest OUT, 'pkcs7.verify.signerInfo[i].authAttr."1.2.840.113549.1.9.4".digest'
        SELECT @i = @i + 1
      END

    EXEC @hr = sp_OADestroy @crypt
    EXEC @hr = sp_OADestroy @http
    EXEC @hr = sp_OADestroy @requestToken
    EXEC @hr = sp_OADestroy @resp
    EXEC @hr = sp_OADestroy @timestampReply
    EXEC @hr = sp_OADestroy @tsaCert
    EXEC @hr = sp_OADestroy @json
    EXEC @hr = sp_OADestroy @signingTime
    EXEC @hr = sp_OADestroy @authAttrSigningTimeUtctime


END
GO