1 | import { sha256 as sha256Hash } from '@noble/hashes/sha256'
|
2 | export { ripemd160 } from '@noble/hashes/ripemd160'
|
3 | import { keccak_256 } from '@noble/hashes/sha3'
|
4 | import { fromString, toString, concat } from 'uint8arrays'
|
5 |
|
6 | export function sha256(payload: string | Uint8Array): Uint8Array {
|
7 | const data = typeof payload === 'string' ? fromString(payload) : payload
|
8 | return sha256Hash(data)
|
9 | }
|
10 |
|
11 | export const keccak = keccak_256
|
12 |
|
13 | export function toEthereumAddress(hexPublicKey: string): string {
|
14 | const hashInput = fromString(hexPublicKey.slice(2), 'base16')
|
15 | return `0x${toString(keccak(hashInput).slice(-20), 'base16')}`
|
16 | }
|
17 |
|
18 | function writeUint32BE(value: number, array = new Uint8Array(4)): Uint8Array {
|
19 | const encoded = fromString(value.toString(), 'base10')
|
20 | array.set(encoded, 4 - encoded.length)
|
21 | return array
|
22 | }
|
23 |
|
24 | const lengthAndInput = (input: Uint8Array): Uint8Array => concat([writeUint32BE(input.length), input])
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | export function concatKDF(
|
30 | secret: Uint8Array,
|
31 | keyLen: number,
|
32 | alg: string,
|
33 | producerInfo?: Uint8Array,
|
34 | consumerInfo?: Uint8Array
|
35 | ): Uint8Array {
|
36 | if (keyLen !== 256) throw new Error(`Unsupported key length: ${keyLen}`)
|
37 | const value = concat([
|
38 | lengthAndInput(fromString(alg)),
|
39 | lengthAndInput(typeof producerInfo === 'undefined' ? new Uint8Array(0) : producerInfo),
|
40 | lengthAndInput(typeof consumerInfo === 'undefined' ? new Uint8Array(0) : consumerInfo),
|
41 | writeUint32BE(keyLen),
|
42 | ])
|
43 |
|
44 |
|
45 | const roundNumber = 1
|
46 | return sha256(concat([writeUint32BE(roundNumber), secret, value]))
|
47 | }
|