From 979a7195dcd9373ba9301b836f57cb1ba7ab9310 Mon Sep 17 00:00:00 2001 From: dtinth on MBP M1 Date: Fri, 12 Apr 2024 03:40:10 +0700 Subject: [PATCH] allow hmac signing --- index.html | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index a8c0f2b..a73724d 100644 --- a/index.html +++ b/index.html @@ -143,7 +143,9 @@

NFC onboarder

{sn} will be replaced with the tag's serial number{sn} will be replaced with the tag's serial number, + {hmac:key} will be replaced with the HMAC of the tag's + serial number using the specified key

@@ -161,7 +163,9 @@

NFC onboarder

{sn} will be replaced with the tag's serial number{sn} will be replaced with the tag's serial number, + {hmac:key} will be replaced with the HMAC of the tag's + serial number using the specified key @@ -222,6 +226,22 @@

NFC tag has been onboarded.

} else { setScreen("welcome"); } + async function hmac(str, key) { + const strBytes = new TextEncoder().encode(str); + const keyBytes = new TextEncoder().encode(key); + const cryptoKey = await crypto.subtle.importKey( + "raw", + keyBytes, + { name: "HMAC", hash: "SHA-256" }, + false, + ["sign"] + ); + const signature = await crypto.subtle.sign("HMAC", cryptoKey, strBytes); + // Format as hex + return Array.from(new Uint8Array(signature)) + .map((b) => b.toString(16).padStart(2, "0")) + .join(""); + } $("#scan").addEventListener("click", async () => { try { const reader = new NDEFReader(); @@ -253,7 +273,23 @@

NFC tag has been onboarded.

2 ); const sn = serialNumber.replace(/:/g, ""); - const expectedUrl = url.replaceAll("{sn}", sn); + + const hmacRegex = /\{hmac:([^}]+)\}/g; + const hmacMap = new Map(); + const promises = []; + url.replaceAll(hmacRegex, (_, key) => { + promises.push( + hmac(sn, key).then((sig) => { + hmacMap.set(key, sig); + }) + ); + }); + if (promises.length) { + await Promise.all(promises); + } + const expectedUrl = url + .replaceAll("{sn}", sn) + .replaceAll(hmacRegex, (_, key) => hmacMap.get(key)); for (const snSpan of document.querySelectorAll(".sn")) { snSpan.textContent = serialNumber; }