Sample code for 30+ languages & platforms
PowerBuilder

Verify Signature of Alexa Custom Skill Request

See more HTTP Misc Examples

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

Chilkat PowerBuilder Downloads

PowerBuilder
integer li_rc
integer li_Success
string ls_Signature
string ls_CertChainUrl
string ls_JsonBody
oleobject loo_Http
oleobject loo_SbPem
oleobject loo_Pem
oleobject loo_Cert
oleobject loo_PubKey
oleobject loo_Rsa
integer li_BVerified

li_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:
ls_Signature = "dSUmPwxc9...aKAf8mpEXg=="
ls_CertChainUrl = "https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem"
ls_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 
loo_Http = create oleobject
li_rc = loo_Http.ConnectToNewObject("Chilkat.Http")
if li_rc < 0 then
    destroy loo_Http
    MessageBox("Error","Connecting to COM object failed")
    return
end if
loo_SbPem = create oleobject
li_rc = loo_SbPem.ConnectToNewObject("Chilkat.StringBuilder")

li_Success = loo_Http.QuickGetSb(ls_CertChainUrl,loo_SbPem)
if li_Success = 0 then
    Write-Debug loo_Http.LastErrorText
    destroy loo_Http
    destroy loo_SbPem
    return
end if

loo_Pem = create oleobject
li_rc = loo_Pem.ConnectToNewObject("Chilkat.Pem")

li_Success = loo_Pem.LoadPem(loo_SbPem.GetAsString(),"passwordNotUsed")
if li_Success = 0 then
    Write-Debug loo_Pem.LastErrorText
    destroy loo_Http
    destroy loo_SbPem
    destroy loo_Pem
    return
end if

// The 1st certificate should be the signing certificate.
loo_Cert = loo_Pem.GetCert(0)
if loo_Pem.LastMethodSuccess = 0 then
    Write-Debug loo_Pem.LastErrorText
    destroy loo_Http
    destroy loo_SbPem
    destroy loo_Pem
    return
end if

// Get the public key from the cert.
loo_PubKey = create oleobject
li_rc = loo_PubKey.ConnectToNewObject("Chilkat.PublicKey")

loo_Cert.GetPublicKey(loo_PubKey)

destroy loo_Cert

// Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
loo_Rsa = create oleobject
li_rc = loo_Rsa.ConnectToNewObject("Chilkat.Rsa")

li_Success = loo_Rsa.UsePublicKey(loo_PubKey)
if li_Success = 0 then
    Write-Debug loo_Cert.LastErrorText
    destroy loo_Http
    destroy loo_SbPem
    destroy loo_Pem
    destroy loo_PubKey
    destroy loo_Rsa
    return
end if

// 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...)
loo_Rsa.EncodingMode = "base64"
li_BVerified = loo_Rsa.VerifyStringENC(ls_JsonBody,"sha1",ls_Signature)
if li_BVerified = 1 then
    Write-Debug "The signature is verified against the JSON body of the request. Yay!"
else
    Write-Debug "Sorry, not verified.  Crud!"
end if



destroy loo_Http
destroy loo_SbPem
destroy loo_Pem
destroy loo_PubKey
destroy loo_Rsa