UNPKG

1.48 kBPlain TextView Raw
1import { leftpad, toJose } from '../util.js'
2import { Signer } from '../JWT.js'
3import { sha256 } from '../Digest.js'
4import { secp256k1 } from '@noble/curves/secp256k1'
5
6/**
7 * Creates a configured signer function for signing data using the ES256K (secp256k1 + sha256) algorithm.
8 *
9 * The signing function itself takes the data as a `Uint8Array` or `string` and returns a `base64Url`-encoded signature
10 *
11 * @example
12 * ```typescript
13 * const sign: Signer = ES256KSigner(process.env.PRIVATE_KEY)
14 * const signature: string = await sign(data)
15 * ```
16 *
17 * @param {String} privateKey a private key as `Uint8Array`
18 * @param {Boolean} recoverable an optional flag to add the recovery param to the generated signatures
19 * @return {Function} a configured signer function `(data: string | Uint8Array): Promise<string>`
20 */
21export function ES256KSigner(privateKey: Uint8Array, recoverable = false): Signer {
22 const privateKeyBytes: Uint8Array = privateKey
23 if (privateKeyBytes.length !== 32) {
24 throw new Error(`bad_key: Invalid private key format. Expecting 32 bytes, but got ${privateKeyBytes.length}`)
25 }
26
27 return async (data: string | Uint8Array): Promise<string> => {
28 const signature = secp256k1.sign(sha256(data), privateKeyBytes)
29 return toJose(
30 {
31 r: leftpad(signature.r.toString(16)),
32 s: leftpad(signature.s.toString(16)),
33 recoveryParam: signature.recovery,
34 },
35 recoverable
36 )
37 }
38}