Sample code for 30+ languages & platforms
SQL Server Requires Chilkat v11.0.0+

Verify Signature of Alexa Custom Skill Request

See more HTTP Misc Examples

This example verifies the signature of an Alexa Custom Skill Request.

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
    DECLARE @iTmp0 int
    DECLARE @sTmp0 nvarchar(4000)
    DECLARE @success int
    SELECT @success = 0

    --  This example assumes you have a web service that will receive requests from Alexa.
    --  A sample request sent by Alexa will look like the following:

    --  Connection: Keep-Alive
    --  Content-Length: 2583
    --  Content-Type: application/json; charset=utf-8
    --  Accept: application/json
    --  Accept-Charset: utf-8
    --  Host: your.web.server.com
    --  User-Agent: Apache-HttpClient/4.5.x (Java/1.8.0_172)
    --  Signature: dSUmPwxc9...aKAf8mpEXg==
    --  SignatureCertChainUrl: https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem
    --  
    --  {"version":"1.0","session":{"new":true,"sessionId":"amzn1.echo-api.session.433 ... }}

    --  First, assume we've written code to get the 3 pieces of data we need:
    DECLARE @signature nvarchar(4000)
    SELECT @signature = 'dSUmPwxc9...aKAf8mpEXg=='
    DECLARE @certChainUrl nvarchar(4000)
    SELECT @certChainUrl = 'https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem'
    DECLARE @jsonBody nvarchar(4000)
    SELECT @jsonBody = '{"version":"1.0","session":{"new":true,"sessionId":"amzn1.echo-api.session.433 ... }}'

    --  To validate the signature, we do the following:

    --  First, download the PEM-encoded X.509 certificate chain that Alexa used to sign the message 
    DECLARE @http int
    EXEC @hr = sp_OACreate 'Chilkat.Http', @http OUT
    IF @hr <> 0
    BEGIN
        PRINT 'Failed to create ActiveX component'
        RETURN
    END

    DECLARE @sbPem int
    EXEC @hr = sp_OACreate 'Chilkat.StringBuilder', @sbPem OUT

    EXEC sp_OAMethod @http, 'QuickGetSb', @success OUT, @certChainUrl, @sbPem
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @http, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        RETURN
      END

    DECLARE @pem int
    EXEC @hr = sp_OACreate 'Chilkat.Pem', @pem OUT

    EXEC sp_OAMethod @sbPem, 'GetAsString', @sTmp0 OUT
    EXEC sp_OAMethod @pem, 'LoadPem', @success OUT, @sTmp0, 'passwordNotUsed'
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @pem, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        EXEC @hr = sp_OADestroy @pem
        RETURN
      END

    --  The 1st certificate should be the signing certificate.
    DECLARE @cert int
    EXEC sp_OAMethod @pem, 'GetCert', @cert OUT, 0
    EXEC sp_OAGetProperty @pem, 'LastMethodSuccess', @iTmp0 OUT
    IF @iTmp0 = 0
      BEGIN
        EXEC sp_OAGetProperty @pem, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        EXEC @hr = sp_OADestroy @pem
        RETURN
      END

    --  Get the public key from the cert.
    DECLARE @pubKey int
    EXEC @hr = sp_OACreate 'Chilkat.PublicKey', @pubKey OUT

    EXEC sp_OAMethod @cert, 'GetPublicKey', @success OUT, @pubKey

    EXEC @hr = sp_OADestroy @cert

    --  Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
    DECLARE @rsa int
    EXEC @hr = sp_OACreate 'Chilkat.Rsa', @rsa OUT

    EXEC sp_OAMethod @rsa, 'UsePublicKey', @success OUT, @pubKey
    IF @success = 0
      BEGIN
        EXEC sp_OAGetProperty @cert, 'LastErrorText', @sTmp0 OUT
        PRINT @sTmp0
        EXEC @hr = sp_OADestroy @http
        EXEC @hr = sp_OADestroy @sbPem
        EXEC @hr = sp_OADestroy @pem
        EXEC @hr = sp_OADestroy @pubKey
        EXEC @hr = sp_OADestroy @rsa
        RETURN
      END

    --  RSA "decrypt" the signature.
    --  (Amazon's documentation is confusing, because we're simply verifiying the signature against the SHA-1 hash
    --  of the request body.  This happens in a single call to VerifyStringENC...)
    EXEC sp_OASetProperty @rsa, 'EncodingMode', 'base64'
    DECLARE @bVerified int
    EXEC sp_OAMethod @rsa, 'VerifyStringENC', @bVerified OUT, @jsonBody, 'sha1', @signature
    IF @bVerified = 1
      BEGIN

        PRINT 'The signature is verified against the JSON body of the request. Yay!'
      END
    ELSE
      BEGIN

        PRINT 'Sorry, not verified.  Crud!'
      END

    EXEC @hr = sp_OADestroy @http
    EXEC @hr = sp_OADestroy @sbPem
    EXEC @hr = sp_OADestroy @pem
    EXEC @hr = sp_OADestroy @pubKey
    EXEC @hr = sp_OADestroy @rsa


END
GO