Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | 41x 41x 41x 41x 9x 9x 9x 9x 9x 9x 41x 9x 9x 9x 9x | import { getPublicKey as getPublicKeyFromPrivate, verify, sign } from '@noble/secp256k1';
import { bytesToHex, arrayBufferToUint8, utf8ToBytes } from 'micro-stacks/common';
import { hashSha256 } from 'micro-stacks/crypto-sha';
/**
* Sign content using ECDSA
*
* @param {String} privateKey - secp256k1 private key hex string
* @param {Object} content - content to sign
* @return {Object} contains:
* signature - Hex encoded DER signature
* public key - Hex encoded private string taken from privateKey
* @private
* @ignore
*/
interface SignECDSA {
privateKey: string;
contents: string | ArrayBuffer | Uint8Array;
}
interface SignedResponse {
signature: string;
publicKey: string;
}
export async function signECDSA(params: SignECDSA): Promise<SignedResponse> {
const { contents, privateKey } = params;
const contentBuffer =
contents instanceof ArrayBuffer
? arrayBufferToUint8(contents)
: typeof contents === 'string'
? utf8ToBytes(contents)
: contents;
const publicKey = bytesToHex(getPublicKeyFromPrivate(privateKey, true));
const contentsHash = hashSha256(contentBuffer);
const signature = await sign(contentsHash, privateKey, {
// whether a signature s should be no more than 1/2 prime order.
// true makes signatures compatible with libsecp256k1
// false makes signatures compatible with openssl <-- stacks currently uses this
canonical: false,
// https://github.com/paulmillr/noble-secp256k1#signmsghash-privatekey
// additional entropy k' for deterministic signature, follows section 3.6 of RFC6979. When true, it would automatically be filled with 32 bytes of cryptographically secure entropy
// TODO: how can we make this default true?
// extraEntropy: true,
});
return {
signature: bytesToHex(signature),
publicKey,
};
}
/**
* Verify content using ECDSA
* @param {String | Buffer} content - Content to verify was signed
* @param {String} publicKey - secp256k1 private key hex string
* @param {String} signature - Hex encoded DER signature
* @param {Boolean} strict - whether a signature s should be no more than 1/2 prime order. true makes signatures compatible with libsecp256k1, false makes signatures compatible with openssl
* @return {Boolean} returns true when signature matches publickey + content, false if not
* @private
* @ignore
*/
interface VerifyESDSA {
contents: string | ArrayBuffer | Uint8Array;
publicKey: string;
signature: string;
}
export function verifyECDSA(params: VerifyESDSA, strict = false): boolean {
const { contents, publicKey, signature } = params;
const contentBuffer =
contents instanceof ArrayBuffer
? arrayBufferToUint8(contents)
: typeof contents === 'string'
? utf8ToBytes(contents)
: contents;
const contentHash = hashSha256(contentBuffer);
return verify(
signature,
contentHash,
publicKey,
// TODO: should this be true by default?
// is not compat with legacy implementations.
// change reflected here https://github.com/paulmillr/noble-secp256k1/releases/tag/1.4.0
{ strict }
);
}
|