Search code examples
typescripthashdeno

How to create (and verify) a hash with HmacSHA256 in deno?


I know how to do that in Python.

#!/usr/bin/python
import sys
import os
import hashlib
import hmac
import base64

secretKey = bytes("passw@rd", 'UTF-8')
message = bytes(f'hello world\nhello deno', 'UTF-8')
encryptedKey = base64.b64encode(hmac.new(secretKey, message, digestmod=hashlib.sha256).digest())
print(encryptedKey)

code output

But I don't know how to do it in deno. I would like the same result of the python code above in deno.


Solution

  • You can create a HMAC-SHA256 hash with the help of the built-in crypto.subtle tools (available since mid of 2021) like shown below:

    import { encode, decode } from "https://deno.land/std/encoding/base64.ts"
    
    // just an example of the data for which we create an HMAC
    const message = "hello world\nhello deno"
    
    const encoder = new TextEncoder()
    
    const secretKey = "passw@rd";
    const keyBuf = encoder.encode(secretKey);
    
    const key = await crypto.subtle.importKey(
      "raw",
      keyBuf,
      {name: "HMAC", hash: "SHA-256"},
      true,
      ["sign", "verify"],
    )
    
    const data = encoder.encode(message);
    const result = await crypto.subtle.sign("HMAC", key , data.buffer);
    console.log(encode(new Uint8Array(result)));
    

    kqfsOD/HMHBRL9F1Si4Y/qo9PCw2csuwXIGZK/P1IWc=

    If the goal is to just verify an existing signature, you can pass the decoded signature to the verify function:

    // validation of a received hmac-code
    const hmacBase64 = "kqfsOD/HMHBRL9F1Si4Y/qo9PCw2csuwXIGZK/P1IWc=";
    
    const hmacDecoded = decode(hmacBase64); // Base64 decoding
    
    const verified = await crypto.subtle.verify("HMAC", key, hmacDecoded, data.buffer);
    console.log("The signature is " + (verified? "": "in") + "valid");
    

    The signature is valid


    Prior to the introduction of crypto.subtle in Deno there were two choices based on external packages:

    You can use God Crypto for it, but that requires an extra Base64 module. Important notice: the owner of God Crypto stopped maintaining the package, therefore it's not recommended to use anymore.

    import { hmac } from "https://deno.land/x/[email protected]/mod.ts"
    import * as base64 from "https://deno.land/x/[email protected]/mod.ts"
    
    let secretKey = "passw@rd"
    let message = "hello world\nhello deno"
    
    const result: string = base64.fromUint8Array(hmac("sha256", secretKey, message))
    
    console.log(result)
    

    kqfsOD/HMHBRL9F1Si4Y/qo9PCw2csuwXIGZK/P1IWc=

    Or you can use the even more convinient hmac module, which has output encoding for "base64", "utf8" and "hex" integrated:

    import { hmac } from "https://deno.land/x/[email protected]/mod.ts";
    
    let secretKey = "passw@rd"
    let message = "hello world\nhello deno"
    
    const result = hmac("sha256", secretKey , message , "utf8", "base64");
    console.log(result)
    

    kqfsOD/HMHBRL9F1Si4Y/qo9PCw2csuwXIGZK/P1IWc=