UNPKG

js-moi-signer

Version:

This package enables users to sign and verify messages in their applications.

107 lines (89 loc) 3.59 kB
import { blake2b } from "@noble/hashes/blake2b"; import { hmac } from '@noble/hashes/hmac'; import { sha256 } from '@noble/hashes/sha256'; import * as nobleECC from '@noble/secp256k1'; import { Buffer } from "buffer"; import { hexToBytes } from "js-moi-utils"; import { SigType } from "../types"; import Signature from "./signature"; import { JoinSignature, SigDigest, bip66Decode, bip66Encode, fromDER, toDER } from "./utils"; /** * Setting the `hmacSha256Sync` with custom hashing logic * @param key * @param msgs */ nobleECC.utils.hmacSha256Sync = (key, ...msgs) => hmac(sha256, key, nobleECC.utils.concatBytes(...msgs)); /** * ECDSA_S256 * * Represents the ECDSA_S256 signature type. */ export default class ECDSA_S256 implements SigType { prefix: number; sigName: string; constructor() { this.prefix = 1; this.sigName = "ECDSA_S256"; } /** * sign * * Signs a message using the ECDSA_S256 signature algorithm. * * @param message - The message to be signed, as a Buffer. * @param signingKey - The private key used for signing, either as * a hexadecimal string or a Buffer. * @returns A Signature instance with ECDSA_S256 prefix and parity byte as extra data */ public sign(message: Buffer, signingKey: Buffer | string): Signature { let _signingKey: Uint8Array if(typeof signingKey === "string") { _signingKey = hexToBytes(signingKey) }else { _signingKey = signingKey } const messageHash = blake2b(message, { dkLen: 1 << 5, // Hashing raw message with blake2b to get 32 bytes digest }); const sigParts = nobleECC.signSync(messageHash, _signingKey, { der: false }); const digest: SigDigest = { _r: toDER(sigParts.slice(0, 32)), _s: toDER(sigParts.slice(32, 64)) } const signature = bip66Encode(digest); const prefixArray = new Uint8Array(2); prefixArray[0] = this.prefix; prefixArray[1] = signature.length; const pubKey = nobleECC.getPublicKey(_signingKey, true); const parityByte = new Uint8Array([pubKey[0]]); const sig = new Signature(prefixArray, signature, parityByte, this.sigName); return sig; } /** * verify * * Verifies the ECDSA signature with the given secp256k1 publicKey * * @param message the message being signed * @param signature the Signature instance with parity byte * as extra data to determine the public key's X & Y co-ordinates * having same or different sign * @param publicKey the compressed public key * @returns boolean, to determine whether verification is success/failure */ verify(message: Uint8Array, signature: Signature, publicKey: Uint8Array): boolean { let verificationKey = new Uint8Array(signature.Extra().length + publicKey.length); verificationKey.set(signature.Extra()); verificationKey.set(publicKey, signature.Extra().length); let derSignature = signature.Digest(); const messageHash = blake2b(message, { dkLen: 1 << 5, // Hashing raw message with blake2b to get 32 bytes digest }); const _digest = bip66Decode(derSignature) const sigDigest: SigDigest = { _r: fromDER(_digest._r), _s: fromDER(_digest._s) } return nobleECC.verify(JoinSignature(sigDigest), messageHash, verificationKey, { strict: true }) } }