Zig Requires Chilkat v11.0.0+
Zig
Verify Signature of Alexa Custom Skill Request
See more HTTP Misc Examples
This example verifies the signature of an Alexa Custom Skill Request.Chilkat Zig Downloads
const std = @import("std");
const chilkat = @import("chilkat");
pub fn main(init: std.process.Init) !void {
const alloc = init.arena.allocator();
// 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:
const signature = "dSUmPwxc9...aKAf8mpEXg==";
const cert_chain_url = "https://s3.amazonaws.com/echo.api/echo-api-cert-6-ats.pem";
const json_body = "{\"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
const http = try chilkat.Http.init();
defer http.deinit();
const sb_pem = try chilkat.StringBuilder.init();
defer sb_pem.deinit();
http.quickGetSb(cert_chain_url, sb_pem) catch {
std.debug.print("{s}\n", .{try http.getLastErrorText(alloc)});
return;
};
const pem = try chilkat.Pem.init();
defer pem.deinit();
pem.loadPem(try sb_pem.getAsString(alloc), "passwordNotUsed") catch {
std.debug.print("{s}\n", .{try pem.getLastErrorText(alloc)});
return;
};
// The 1st certificate should be the signing certificate.
ERROR: Method not in the Zig package: Pem.GetCert
ERROR: Method not in the Zig package: Pem.GetCert
const cert = pem.ERROR();
if (!pem.getLastMethodSuccess()) {
std.debug.print("{s}\n", .{try pem.getLastErrorText(alloc)});
return;
}
// Get the public key from the cert.
const pub_key = try chilkat.PublicKey.init();
defer pub_key.deinit();
cert.getPublicKey(pub_key) catch {};
// Use the public key extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
const rsa = try chilkat.Rsa.init();
defer rsa.deinit();
rsa.usePublicKey(pub_key) catch {
std.debug.print("{s}\n", .{try cert.getLastErrorText(alloc)});
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.setEncodingMode("base64");
if (rsa.verifyStringENC(json_body, "sha1", signature)) {
std.debug.print("The signature is verified against the JSON body of the request. Yay!\n", .{});
} else |_| {
std.debug.print("Sorry, not verified. Crud!\n", .{});
}
}