Category talk:Wren-crypto
Source code
<lang ecmascript>/* Module "crypto.wren" */
/*
Bits contains bit manipulation routines which are useful for cryptograpgic purposes. To make these as fast as possible no checks are performed on the inputs.
- /
class Bits {
// Rotates the bits in a 32-bit unsigned integer 'x' to the left by 'c' places between 1 and 31. static leftRotate (x, c) { (x << c) | (x >> (32 - c)) }
// Rotates the bits in a 32-bit unsigned integer 'x' to the right by 'c' places between 1 and 31. static rightRotate(x, c) { (x >> c) | (x << (32 - c)) }
}
/*
Bytes contains byte manipulation routines which are useful for cryptograpgic purposes. To make these as fast as possible no checks are performed on the inputs.
- /
class Bytes {
// Converts a 32-bit unsigned integer 'x' to a list of 4 bytes in big-endian format. static fromIntBE(x) { var bytes = List.filled(4, 0) bytes[3] = x & 255 bytes[2] = (x >> 8) & 255 bytes[1] = (x >> 16) & 255 bytes[0] = (x >> 24) & 255 return bytes }
// Converts a 32-bit unsigned integer 'x' to a list of 4 bytes in little-endian format. static fromIntLE(x) { var bytes = List.filled(4, 0) bytes[0] = x & 255 bytes[1] = (x >> 8) & 255 bytes[2] = (x >> 16) & 255 bytes[3] = (x >> 24) & 255 return bytes }
// Converts a list of 4 bytes in big-endian format to a 32-bit unsigned integer. static toIntBE(bytes) { bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3] }
// Converts a list of 4 bytes in little-endian format to a 32-bit unsigned integer. static toIntLE(bytes) { bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24 }
// Converts a list of an even number of bytes or the 4 bytes of a 32-bit unsigned integer // in big-endian format into a lower case hexadecimal string. static toHexString(bytes) { if (bytes is Num) bytes = fromIntBE(bytes) var digits = "0123456789abcdef" var res = [] for (byte in bytes) { var d = (byte != 0) ? [] : [0] while (byte > 0) { d.add(digits[byte % 16]) byte = (byte/16).floor } res.add((d.count == 2) ? d[1] : 0) res.add(d[0]) } return res.join() }
// Converts a lower case hexadecimal string into a byte list. static fromHexString(hs) { var digits = "0123456789abcdef" var bytes = List.filled(hs.count/2, 0) var i = 0 while (i < hs.count-1) { bytes[i/2] = digits.indexOf(hs[i]) * 16 + digits.indexOf(hs[i+1]) i = i + 2 } return bytes }
}
/* Md5 implements the MD5 hashing algorithm. */ class Md5 {
static init_() { __k = [ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ]
__r = [ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 ] }
// Computes the MD5 message digest of a byte sequence or string. static digest(initBytes) { if (!__k) init_() var h0 = 0x67452301 var h1 = 0xefcdab89 var h2 = 0x98badcfe var h3 = 0x10325476 if (initBytes is String) initBytes = initBytes.bytes var initLen = initBytes.count var newLen = initLen + 1 while (newLen % 64 != 56) newLen = newLen + 1 var msg = List.filled(newLen + 8, 0) for (i in 0...initLen) msg[i] = initBytes[i] msg[initLen] = 0x80 // remaining bytes already 0 var lenBits = Bytes.fromIntLE(initLen * 8) for (i in newLen...newLen+4) msg[i] = lenBits[i-newLen] var extraBits = Bytes.fromIntLE(initLen >> 29) for (i in newLen+4...newLen+8) msg[i] = extraBits[i-newLen-4] var offset = 0 var w = List.filled(16, 0) var mask = 0xffffffff while (offset < newLen) { for (i in 0...16) w[i] = Bytes.toIntLE(msg[offset+i*4...offset + i*4 + 4]) var a = h0 var b = h1 var c = h2 var d = h3 var f var g for (i in 0...64) { if (i < 16) { f = (b & c) | ((~b) & d) g = i } else if (i < 32) { f = (d & b) | ((~d) & c) g = (5*i + 1) % 16 } else if (i < 48) { f = b ^ c ^ d g = (3*i + 5) % 16 } else { f = c ^ (b | (~d)) g = (7*i) % 16 } var temp = d d = c c = b b = b + Bits.leftRotate((a + f + __k[i] + w[g]), __r[i]) a = temp } h0 = (h0 + a) & mask h1 = (h1 + b) & mask h2 = (h2 + c) & mask h3 = (h3 + d) & mask offset = offset + 64 }
h0 = Bytes.toHexString(Bytes.fromIntLE(h0)) h1 = Bytes.toHexString(Bytes.fromIntLE(h1)) h2 = Bytes.toHexString(Bytes.fromIntLE(h2)) h3 = Bytes.toHexString(Bytes.fromIntLE(h3)) return h0 + h1 + h2 + h3 }
}
/* Sha256 implements the SHA-256 hashing algorithm. */ class Sha256 {
static init_() { __k = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ] }
// Computes the SHA-256 message digest of a byte sequence or string. static digest(initBytes) { if (!__k) init_() var h0 = 0x6a09e667 var h1 = 0xbb67ae85 var h2 = 0x3c6ef372 var h3 = 0xa54ff53a var h4 = 0x510e527f var h5 = 0x9b05688c var h6 = 0x1f83d9ab var h7 = 0x5be0cd19 if (initBytes is String) initBytes = initBytes.bytes var initLen = initBytes.count var newLen = initLen + 1 while (newLen % 64 != 56) newLen = newLen + 1 var msg = List.filled(newLen + 8, 0) for (i in 0...initLen) msg[i] = initBytes[i] msg[initLen] = 0x80 // remaining bytes already 0 var initBits = initLen * 8 var p = 2.pow(32) var u = (initBits/p).floor var l = initBits % p var bytesU = Bytes.fromIntBE(u) var bytesL = Bytes.fromIntBE(l) for (i in 0..3) msg[newLen+i] = bytesU[i] for (i in 0..3) msg[newLen+i+4] = bytesL[i] var offset = 0 var w = List.filled(64, 0) var mask = 0xffffffff while (offset < newLen) { for (i in 0..15) w[i] = Bytes.toIntBE(msg[offset+i*4...offset + i*4 + 4]) for (i in 16..63) { var s0 = Bits.rightRotate(w[i-15], 7) ^ Bits.rightRotate(w[i-15], 18) ^ (w[i-15] >> 3) var s1 = Bits.rightRotate(w[i- 2], 17) ^ Bits.rightRotate(w[i- 2], 19) ^ (w[i- 2] >> 10) w[i] = w[i-16] + s0 + w[i-7] + s1 } var a = h0 var b = h1 var c = h2 var d = h3 var e = h4 var f = h5 var g = h6 var h = h7 for (i in 0..63) { var s1 = Bits.rightRotate(e, 6) ^ Bits.rightRotate(e, 11) ^ Bits.rightRotate(e, 25) var ch = (e & f) ^ ((~e) & g) var temp1 = h + s1 + ch + __k[i] + w[i] var s0 = Bits.rightRotate(a, 2) ^ Bits.rightRotate(a, 13) ^ Bits.rightRotate(a, 22) var maj = (a & b) ^ (a & c) ^ (b & c) var temp2 = s0 + maj h = g g = f f = e e = d + temp1 d = c c = b b = a a = temp1 + temp2 } h0 = (h0 + a) & mask h1 = (h1 + b) & mask h2 = (h2 + c) & mask h3 = (h3 + d) & mask h4 = (h4 + e) & mask h5 = (h5 + f) & mask h6 = (h6 + g) & mask h7 = (h7 + h) & mask offset = offset + 64 } h0 = Bytes.toHexString(h0) h1 = Bytes.toHexString(h1) h2 = Bytes.toHexString(h2) h3 = Bytes.toHexString(h3) h4 = Bytes.toHexString(h4) h5 = Bytes.toHexString(h5) h6 = Bytes.toHexString(h6) h7 = Bytes.toHexString(h7) return h0 + h1 + h2 + h3 + h4 + h5 + h6 + h7 }
}
/* Sha224 implements the SHA-224 hashing algorithm. */ class Sha224 {
static init_() { __k = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ] }
// Computes the SHA-224 message digest of a byte sequence or string. static digest(initBytes) { if (!__k) init_() var h0 = 0xc1059ed8 var h1 = 0x367cd507 var h2 = 0x3070dd17 var h3 = 0xf70e5939 var h4 = 0xffc00b31 var h5 = 0x68581511 var h6 = 0x64f98fa7 var h7 = 0xbefa4fa4 if (initBytes is String) initBytes = initBytes.bytes var initLen = initBytes.count var newLen = initLen + 1 while (newLen % 64 != 56) newLen = newLen + 1 var msg = List.filled(newLen + 8, 0) for (i in 0...initLen) msg[i] = initBytes[i] msg[initLen] = 0x80 // remaining bytes already 0 var initBits = initLen * 8 var p = 2.pow(32) var u = (initBits/p).floor var l = initBits % p var bytesU = Bytes.fromIntBE(u) var bytesL = Bytes.fromIntBE(l) for (i in 0..3) msg[newLen+i] = bytesU[i] for (i in 0..3) msg[newLen+i+4] = bytesL[i] var offset = 0 var w = List.filled(64, 0) var mask = 0xffffffff while (offset < newLen) { for (i in 0..15) w[i] = Bytes.toIntBE(msg[offset+i*4...offset + i*4 + 4]) for (i in 16..63) { var s0 = Bits.rightRotate(w[i-15], 7) ^ Bits.rightRotate(w[i-15], 18) ^ (w[i-15] >> 3) var s1 = Bits.rightRotate(w[i- 2], 17) ^ Bits.rightRotate(w[i- 2], 19) ^ (w[i- 2] >> 10) w[i] = w[i-16] + s0 + w[i-7] + s1 } var a = h0 var b = h1 var c = h2 var d = h3 var e = h4 var f = h5 var g = h6 var h = h7 for (i in 0..63) { var s1 = Bits.rightRotate(e, 6) ^ Bits.rightRotate(e, 11) ^ Bits.rightRotate(e, 25) var ch = (e & f) ^ ((~e) & g) var temp1 = h + s1 + ch + __k[i] + w[i] var s0 = Bits.rightRotate(a, 2) ^ Bits.rightRotate(a, 13) ^ Bits.rightRotate(a, 22) var maj = (a & b) ^ (a & c) ^ (b & c) var temp2 = s0 + maj h = g g = f f = e e = d + temp1 d = c c = b b = a a = temp1 + temp2 } h0 = (h0 + a) & mask h1 = (h1 + b) & mask h2 = (h2 + c) & mask h3 = (h3 + d) & mask h4 = (h4 + e) & mask h5 = (h5 + f) & mask h6 = (h6 + g) & mask h7 = (h7 + h) & mask offset = offset + 64 } h0 = Bytes.toHexString(h0) h1 = Bytes.toHexString(h1) h2 = Bytes.toHexString(h2) h3 = Bytes.toHexString(h3) h4 = Bytes.toHexString(h4) h5 = Bytes.toHexString(h5) h6 = Bytes.toHexString(h6) return h0 + h1 + h2 + h3 + h4 + h5 + h6 }
}
/* Sha1 implements the SHA-1 hashing algorithm. */ class Sha1 {
// Computes the SHA-1 message digest of a byte sequence or string. static digest(initBytes) { var h0 = 0x67452301 var h1 = 0xefcdab89 var h2 = 0x98badcfe var h3 = 0x10325476 var h4 = 0xc3d2e1f0 if (initBytes is String) initBytes = initBytes.bytes var initLen = initBytes.count var newLen = initLen + 1 while (newLen % 64 != 56) newLen = newLen + 1 var msg = List.filled(newLen + 8, 0) for (i in 0...initLen) msg[i] = initBytes[i] msg[initLen] = 0x80 // remaining bytes already 0 var initBits = initLen * 8 var p = 2.pow(32) var u = (initBits/p).floor var l = initBits % p var bytesU = Bytes.fromIntBE(u) var bytesL = Bytes.fromIntBE(l) for (i in 0..3) msg[newLen+i] = bytesU[i] for (i in 0..3) msg[newLen+i+4] = bytesL[i] var offset = 0 var w = List.filled(80, 0) var mask = 0xffffffff while (offset < newLen) { for (i in 0..15) w[i] = Bytes.toIntBE(msg[offset+i*4...offset + i*4 + 4]) for (i in 16..79) { w[i] = Bits.leftRotate(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1) } var a = h0 var b = h1 var c = h2 var d = h3 var e = h4 var f var k for (i in 0..79) { if (i <= 19) { f = (b & c) | ((~b) & d) k = 0x5a827999 } else if (i <= 39) { f = b ^ c ^ d k = 0x6ed9eba1 } else if (i <= 59) { f = (b & c) | (b & d) | (c & d) k = 0x8f1bbcdc } else { f = b ^ c ^ d k = 0xca62c1d6 } var temp = Bits.leftRotate(a, 5) + f + e + k + w[i] e = d d = c c = Bits.leftRotate(b, 30) b = a a = temp } h0 = (h0 + a) & mask h1 = (h1 + b) & mask h2 = (h2 + c) & mask h3 = (h3 + d) & mask h4 = (h4 + e) & mask offset = offset + 64 } h0 = Bytes.toHexString(h0) h1 = Bytes.toHexString(h1) h2 = Bytes.toHexString(h2) h3 = Bytes.toHexString(h3) h4 = Bytes.toHexString(h4) return h0 + h1 + h2 + h3 + h4 }
}
/* Ripemd160 implements the RIPEMD-160 hashing algorithm. */ class Ripemd160 {
static init_() { __f = [ Fn.new { |x, y, z| x ^ y ^ z }, Fn.new { |x, y, z| (x & y) | ((~x) & z) }, Fn.new { |x, y, z| (x | (~y)) ^ z }, Fn.new { |x, y, z| (x & z) | (y & (~z)) }, Fn.new { |x, y, z| x ^ (y | (~z)) } ]
__k = [ 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e ] __kk = [ 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000 ]
__r = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 ]
__rr = [ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 ]
__s = [ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]
__ss = [ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ] }
// Computes the RIPEMD-160 message digest of a byte sequence or string. static digest(initBytes) { if (!__f) init_() var h0 = 0x67452301 var h1 = 0xefcdab89 var h2 = 0x98badcfe var h3 = 0x10325476 var h4 = 0xc3d2e1f0 if (initBytes is String) initBytes = initBytes.bytes var initLen = initBytes.count var newLen = initLen + 1 while (newLen % 64 != 56) newLen = newLen + 1 var msg = List.filled(newLen + 8, 0) for (i in 0...initLen) msg[i] = initBytes[i] msg[initLen] = 0x80 // remaining bytes already 0 var lenBits = Bytes.fromIntLE(initLen * 8) for (i in newLen...newLen+4) msg[i] = lenBits[i-newLen] var extraBits = Bytes.fromIntLE(initLen >> 29) for (i in newLen+4...newLen+8) msg[i] = extraBits[i-newLen-4] var offset = 0 var x = List.filled(16, 0) var mask = 0xffffffff while (offset < newLen) { for (i in 0...16) x[i] = Bytes.toIntLE(msg[offset+i*4...offset + i*4 + 4]) var a = h0 var b = h1 var c = h2 var d = h3 var e = h4 var aa = h0 var bb = h1 var cc = h2 var dd = h3 var ee = h4 for (j in 0..79) { var i = (j/16).floor var t = a + __f[i].call(b, c, d) + x[__r[j]] + __k[i] t = (Bits.leftRotate(t & mask, __s[j]) + e) & mask a = e e = d d = Bits.leftRotate(c, 10) c = b b = t t = aa + __f[4-i].call(bb, cc, dd) + x[__rr[j]] + __kk[i] t = (Bits.leftRotate(t & mask, __ss[j]) + ee) & mask aa = ee ee = dd dd = Bits.leftRotate(cc, 10) cc = bb bb = t } var temp = (h1 + c + dd) & mask h1 = (h2 + d + ee) & mask h2 = (h3 + e + aa) & mask h3 = (h4 + a + bb) & mask h4 = (h0 + b + cc) & mask h0 = temp offset = offset + 64 } h0 = Bytes.toHexString(Bytes.fromIntLE(h0)) h1 = Bytes.toHexString(Bytes.fromIntLE(h1)) h2 = Bytes.toHexString(Bytes.fromIntLE(h2)) h3 = Bytes.toHexString(Bytes.fromIntLE(h3)) h4 = Bytes.toHexString(Bytes.fromIntLE(h4)) return h0 + h1 + h2 + h3 + h4 }
}
/* Hmac implements the HMAC ('keyed-hash message authentication code') algorithm. */ class Hmac {
// Computes the HMAC message digest of a byte sequence or string for a given key and class // of cryptographic hashing algorithm with a specified block-size in bytes provided such class // has a static digest(initBytes) method. static digest(key, message, hashClass, blockSize) { if (key is String) key = key.bytes.toList if (message is String) message = message.bytes.toList if (key.count > blockSize) key = Bytes.fromHexString(hashClass.digest(key)) if (key.count < blockSize) key = key + [0] * (blockSize - key.count) var outerKeyPad = key.map { |b| b ^ 0x5c }.toList var innerKeyPad = key.map { |b| b ^ 0x36 }.toList var innerHash = Bytes.fromHexString(hashClass.digest(innerKeyPad + message)) return hashClass.digest(outerKeyPad + innerHash) }
// Convenience version of the above method which assumes a block-size of 64 bytes // and is true for all cryptographic hashing algorithms supported by this module. static digest(key, message, hashClass) { digest(key, message, hashClass, 64) }
}</lang>