-
-
Save shovon/b05a998ab0557b290244cc4e3fcd2e13 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// secp256k1 | |
import * as bigintConversion from "bigint-conversion"; | |
function concatUint8Array(a: Uint8Array, b: Uint8Array): Uint8Array { | |
const merged = new Uint8Array(a.length + b.length); | |
merged.set(a); | |
merged.set(b, a.length); | |
return merged; | |
} | |
function randIntInRange(range: bigint): bigint { | |
const buf = bigintConversion.bigintToBuf(range, true) as ArrayBuffer; | |
const u8a = new Uint8Array(buf).slice(1); | |
const randVal = crypto.getRandomValues(u8a); | |
return bigintConversion.bufToBigint( | |
concatUint8Array(new Uint8Array([(Math.random() * (u8a[0] - 0b10000000)) | 0]), randVal) | |
); | |
} | |
function extendedGcd( | |
a: bigint, | |
b: bigint | |
): { result: bigint; x: bigint; y: bigint } { | |
if (a === 0n) { | |
return { result: b, x: 0n, y: 1n }; | |
} | |
const { result, x: x1, y: y1 } = extendedGcd(b % a, a); | |
return { result, x: y1 - (b / a) * x1, y: x1 }; | |
} | |
function fastModularInverse(a: bigint, m: bigint): bigint { | |
const { result: g, x } = extendedGcd(a, m); | |
if (g != 1n) { | |
throw new Error("Inverse does not exist!"); | |
} | |
return ((x % m) + m) % m; | |
} | |
const n = | |
115792089237316195423570985008687907852837564279074904382605163141518161494337n; | |
const G = { | |
x: 55066263022277343669578718895168534326250603453777594175500187360389116729240n, | |
y: 32670510020758816978083085130507043184471273380659243275938904335757337482424n, | |
}; | |
function sign(privKey: bigint, hash: bigint): { r: bigint; s: bigint } { | |
const k = randIntInRange(n); | |
const r = (k * G.x) % n; | |
const s = (fastModularInverse(k, n) * (hash + r * privKey)) % n; | |
return { r, s }; | |
} | |
function verify( | |
pubKey: { x: bigint; y: bigint }, | |
hash: bigint, | |
{ r, s }: { r: bigint; s: bigint } | |
): boolean { | |
const u1 = hash * fastModularInverse(s, n); | |
const u2 = r * fastModularInverse(s, n); | |
const x = u1 * G.x + u2 * pubKey.x; | |
return r % n === x % n; | |
} | |
const privKey = randIntInRange(n); | |
const pubKey = { | |
x: privKey * G.x, | |
y: privKey * G.y, | |
}; | |
console.log(pubKey); | |
console.log("Computing"); | |
let v = new Uint8Array(256 / 8); | |
v = crypto.getRandomValues(v); | |
const signature = sign(privKey, bigintConversion.bufToBigint(v)); | |
console.log(verify(pubKey, bigintConversion.bufToBigint(v), signature)); | |
export {}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment