/// This package is based on the Go implementation found here:
/// https://cs.opensource.google/go/go/+/refs/tags/go1.23.0:src/crypto/hmac/hmac.go
/// which has the copyright notice:
/// Copyright 2009 The Go Authors. All rights reserved.
/// Use of this source code is governed by a BSD-style
/// license that can be found in the LICENSE file.
///|
/// `gen_hmac` generates a base64-encoded String representing
/// the SHA256 signature of the provided `body` using the provided
/// `client_secret` key.
pub fn gen_hmac(body : Bytes, client_secret : Bytes) -> String {
let h = HMAC::new(client_secret)
for b in body {
h.inner.write(b)
}
let buf = h.sum()
@base64.url_encode2str(buf)
}
///|
priv struct HMAC {
opad : FixedArray[Byte]
ipad : FixedArray[Byte]
outer : Digest
inner : Digest
}
///|
fn HMAC::new(key : Bytes) -> HMAC {
let hm = {
opad: FixedArray::make(block_size, b'\x00'),
ipad: FixedArray::make(block_size, b'\x00'),
outer: Digest::new(),
inner: Digest::new(),
}
// If key is too big, hash it.
let mut key = FixedArray::from_iter(key.iter())
if key.length() > block_size {
for b in key {
hm.outer.write(b)
}
key = hm.outer.sum()
}
// copy
for index, b in key {
hm.ipad[index] = b
hm.opad[index] = b
}
for index, b in hm.ipad {
hm.ipad[index] = b ^ b'\x36'
hm.inner.write(hm.ipad[index])
}
for index, b in hm.opad {
hm.opad[index] = b ^ b'\x5c'
}
hm
}
///|
fn HMAC::sum(self : HMAC) -> FixedArray[Byte] {
let inner_sum = self.inner.sum()
self.outer.reset()
for b in self.opad {
self.outer.write(b)
}
for b in inner_sum {
self.outer.write(b)
}
self.outer.sum()
}