Sample code for 30+ languages & platforms
Objective-C

Verify Signature of Alexa Custom Skill Request

See more HTTP Misc Examples

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

Chilkat Objective-C Downloads

Objective-C
#import <NSString.h>
#import <CkoHttp.h>
#import <CkoStringBuilder.h>
#import <CkoPem.h>
#import <CkoCert.h>
#import <CkoPublicKey.h>
#import <CkoRsa.h>

BOOL success = NO;

// 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:
NSString *signature = @"dSUmPwxc9...aKAf8mpEXg==";
NSString *certChainUrl = @"https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem";
NSString *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 
CkoHttp *http = [[CkoHttp alloc] init];
CkoStringBuilder *sbPem = [[CkoStringBuilder alloc] init];
success = [http QuickGetSb: certChainUrl sbContent: sbPem];
if (success == NO) {
    NSLog(@"%@",http.LastErrorText);
    return;
}

CkoPem *pem = [[CkoPem alloc] init];
success = [pem LoadPem: [sbPem GetAsString] password: @"passwordNotUsed"];
if (success == NO) {
    NSLog(@"%@",pem.LastErrorText);
    return;
}

// The 1st certificate should be the signing certificate.
CkoCert *cert = [pem GetCert: [NSNumber numberWithInt: 0]];
if (pem.LastMethodSuccess == NO) {
    NSLog(@"%@",pem.LastErrorText);
    return;
}

// Get the public key from the cert.
CkoPublicKey *pubKey = [[CkoPublicKey alloc] init];
[cert GetPublicKey: pubKey];

// Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
CkoRsa *rsa = [[CkoRsa alloc] init];
success = [rsa UsePublicKey: pubKey];
if (success == NO) {
    NSLog(@"%@",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";
BOOL bVerified = [rsa VerifyStringENC: jsonBody hashAlg: @"sha1" sig: signature];
if (bVerified == YES) {
    NSLog(@"%@",@"The signature is verified against the JSON body of the request. Yay!");
}
else {
    NSLog(@"%@",@"Sorry, not verified.  Crud!");
}