D
Deno

help

Verify AWS SNS signature with PEM certificate

Ccaleb2/9/2024
Hello, I'm trying to verify aws sns messages in deno given a signing cert (in pem format, RSA sha1) and signature. However, when I do crypto.subtle.importKey, I keep getting this error:
DOMException: ASN.1 error: unexpected ASN.1 DER tag: expected OBJECT IDENTIFIER, got CONTEXT-SPECIFIC [0] (constructed) at DER byte 8
at new DOMException (ext:deno_web/01_dom_exception.js:115:20)
at new <anonymous> (ext:sb_core_main_js/js/errors.js:23:9)
at Object.DOMExceptionDataError (ext:core/01_core.js:232:46)
at buildCustomError (ext:core/01_core.js:245:36)
at importKeyRSA (ext:deno_crypto/00_crypto.js:3425:10)
at SubtleCrypto.importKey (ext:deno_crypto/00_crypto.js:985:16)
DOMException: ASN.1 error: unexpected ASN.1 DER tag: expected OBJECT IDENTIFIER, got CONTEXT-SPECIFIC [0] (constructed) at DER byte 8
at new DOMException (ext:deno_web/01_dom_exception.js:115:20)
at new <anonymous> (ext:sb_core_main_js/js/errors.js:23:9)
at Object.DOMExceptionDataError (ext:core/01_core.js:232:46)
at buildCustomError (ext:core/01_core.js:245:36)
at importKeyRSA (ext:deno_crypto/00_crypto.js:3425:10)
at SubtleCrypto.importKey (ext:deno_crypto/00_crypto.js:985:16)
My attempt:
await crypto.subtle.importKey(
"spki",
binaryDer, // where binaryDer is as derived here: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#subjectpublickeyinfo_import (but with BEGIN CERTIFICATE and END CERTIFICATE)
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-1",
},
true,
["verify"],
);
await crypto.subtle.importKey(
"spki",
binaryDer, // where binaryDer is as derived here: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#subjectpublickeyinfo_import (but with BEGIN CERTIFICATE and END CERTIFICATE)
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-1",
},
true,
["verify"],
);
thanks
DAHDeno AI Helper2/9/2024
I wasn't able to find the answer to your question in the official Deno documentation. However, based on the error message you've provided, it seems like there might be an issue with the format of the DER-encoded key you're trying to import. The error suggests that the ASN.1 DER structure is not as expected for an OBJECT IDENTIFIER. From the code snippet you've shared, it looks like you're trying to import a PEM certificate as a SPKI (SubjectPublicKeyInfo) format, which is generally correct for public keys. However, please ensure that you are correctly converting the PEM certificate to the binary DER format before attempting to import it. The PEM certificate should have the "BEGIN CERTIFICATE" and "END CERTIFICATE" headers removed, and the remaining base64-encoded string should be converted to a Uint8Array (binary format). Here's a general approach to convert a PEM certificate to DER format:
const pem = /* your PEM string */;
const pemHeader = "-----BEGIN CERTIFICATE-----";
const pemFooter = "-----END CERTIFICATE-----";
const pemContents = pem.replace(pemHeader, "").replace(pemFooter, "").trim();
const binaryDerString = atob(pemContents);
const binaryDer = new Uint8Array(binaryDerString.length);
for (let i = 0; i < binaryDerString.length; i++) {
binaryDer[i] = binaryDerString.charCodeAt(i);
}
const pem = /* your PEM string */;
const pemHeader = "-----BEGIN CERTIFICATE-----";
const pemFooter = "-----END CERTIFICATE-----";
const pemContents = pem.replace(pemHeader, "").replace(pemFooter, "").trim();
const binaryDerString = atob(pemContents);
const binaryDer = new Uint8Array(binaryDerString.length);
for (let i = 0; i < binaryDerString.length; i++) {
binaryDer[i] = binaryDerString.charCodeAt(i);
}
Please note that this advice is not based on the Deno documentation, and I would advise you to double-check the accuracy of this advice. If the issue persists after ensuring the PEM to DER conversion is correct, you may want to verify that the certificate is indeed in the correct format and that there are no issues with the certificate itself.
Ccaleb2/10/2024
This ^ but I had to extract the public key from the cert using https://deno.land/x/jose@v5.2.1/index.ts, export that to public key string, then do this ^ but removing BEGIN PUBLIC KEY and END PUBLIC KEY, and then doing crypto.subtle.importKey() on that

Looking for more? Join the community!