Last active
January 30, 2023 16:09
-
-
Save cendyne/e56a53ec0b2c65c42822162d537020c3 to your computer and use it in GitHub Desktop.
HKDF derive key web crypto subtle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// We generated this above as an example IND key derivation key | |
let openSSLSecretKey = '0de81e851cd7995626ad4c3e160ae1c449af4e15c8ceabd44fb75be581adfbaa'; | |
// Parse the hex string into a Uint8Array | |
let ikm = Uint8Array.from(openSSLSecretKey | |
.match(/.{1,2}/g) | |
.map((byte) => parseInt(byte, 16))); | |
// Import the raw key data | |
let kdk = await crypto.subtle.importKey( | |
'raw', | |
ikm, | |
'HKDF', | |
false, // KDF keys cannot be exported | |
['deriveKey', 'deriveBits']); | |
// We are going to create a signing key from the secret | |
// If we create other keys too, they should not have the | |
// same label! | |
let label = 'signing key'; | |
// This function works with bytes. | |
// Therefore we must encode our label which is text to bytes. | |
let encoder = new TextEncoder(); | |
let info = encoder.encode(label); | |
// A salt is a required property, even though it is empty. | |
let salt = new Uint8Array(); // Nothing inside! | |
// Derive a signing key from the key derivation key | |
let signingKey = await crypto.subtle.deriveKey( | |
// Again, the salt is empty | |
// The info will uniquely describe this key | |
{name: 'HKDF', salt, info, hash: 'SHA-256'}, | |
// The input key material we decoded from hex above | |
// and then wrapped in a CryptoKey | |
kdk, | |
// We're creating an HMAC-SHA-256 key | |
{name: 'HMAC', hash: 'SHA-256'}, | |
// We do not need to export it, | |
// since we can create it deterministically. | |
false, | |
// it needs to sign and verify | |
['sign', 'verify']); | |
// Prove that it works | |
// Let's sign "Hello world" | |
let message = 'Hello world'; | |
let encodedMessage = encoder.encode(message); | |
let tag = await crypto.subtle.sign( | |
{name: 'HMAC'}, | |
signingKey, | |
encodedMessage); | |
console.log(`Message ${message} - tag: ${btoa(tag)}`); | |
// Message Hello world - tag: W29iamVjdCBBcnJheUJ1ZmZlcl0= | |
// And prove that it can match its own mac too. | |
let verified = await crypto.subtle.verify( | |
{name: 'HMAC'}, | |
signingKey, | |
tag, | |
encodedMessage); | |
console.log(`Verify?: ${verified}`); | |
// Verify?: true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment