Sample code for 30+ languages & platforms
Dart 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 Dart Downloads

Dart
import 'package:chilkat/chilkat.dart';

void main() {
  // 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:
  final signature = 'dSUmPwxc9...aKAf8mpEXg==';
  final certChainUrl = 'https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem';
  final 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 
  final http = CkHttp();
  final sbPem = CkStringBuilder();
  try {
    http.quickGetSb(certChainUrl, sbPem);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  final pem = CkPem();
  try {
    pem.loadPem(sbPem.getAsString(), 'passwordNotUsed');
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  // The 1st certificate should be the signing certificate.
  final CkCert cert;
  try {
    cert = pem.getCert(0);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  // Get the public key from the cert.
  final pubKey = CkPublicKey();
  cert.getPublicKey(pubKey);

  // Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
  final rsa = CkRsa();
  try {
    rsa.usePublicKey(pubKey);
  } on ChilkatException {
    print(cert.lastErrorText);
    return;
  }

  // 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...)
  rsa.encodingMode = 'base64';
  try {
    rsa.verifyStringENC(jsonBody, 'sha1', signature);
    print('The signature is verified against the JSON body of the request. Yay!');
  } on ChilkatException {
    print('Sorry, not verified.  Crud!');
  }
}