did-jwt
Version:
Library for Signing and Verifying JWTs that use DIDs as issuers and JWEs that use DIDs as recipients
48 lines (40 loc) • 1.83 kB
text/typescript
import { sha256 as sha256Hash } from '@noble/hashes/sha256'
export { ripemd160 } from '@noble/hashes/ripemd160'
import { keccak_256 } from '@noble/hashes/sha3'
import { fromString, toString, concat } from 'uint8arrays'
export function sha256(payload: string | Uint8Array): Uint8Array {
const data = typeof payload === 'string' ? fromString(payload) : payload
return sha256Hash(data)
}
export const keccak = keccak_256
export function toEthereumAddress(hexPublicKey: string): string {
const hashInput = fromString(hexPublicKey.slice(2), 'base16')
return `0x${toString(keccak(hashInput).slice(-20), 'base16')}`
}
function writeUint32BE(value: number, array = new Uint8Array(4)): Uint8Array {
const encoded = fromString(value.toString(), 'base10')
array.set(encoded, 4 - encoded.length)
return array
}
const lengthAndInput = (input: Uint8Array): Uint8Array => concat([writeUint32BE(input.length), input])
// This implementation of concatKDF was inspired by these two implementations:
// https://github.com/digitalbazaar/minimal-cipher/blob/master/algorithms/ecdhkdf.js
// https://github.com/panva/jose/blob/master/lib/jwa/ecdh/derive.js
export function concatKDF(
secret: Uint8Array,
keyLen: number,
alg: string,
producerInfo?: Uint8Array,
consumerInfo?: Uint8Array
): Uint8Array {
if (keyLen !== 256) throw new Error(`Unsupported key length: ${keyLen}`)
const value = concat([
lengthAndInput(fromString(alg)),
lengthAndInput(typeof producerInfo === 'undefined' ? new Uint8Array(0) : producerInfo), // apu
lengthAndInput(typeof consumerInfo === 'undefined' ? new Uint8Array(0) : consumerInfo), // apv
writeUint32BE(keyLen),
])
// since our key lenght is 256 we only have to do one round
const roundNumber = 1
return sha256(concat([writeUint32BE(roundNumber), secret, value]))
}