// import { secp256k1 } from '@noble/curves/secp256k1' // import { randomBytes } from '@noble/hashes/utils'; // import { asn1, pki, util } from 'node-forge' // TODO treeshake or find less expensive alternative // const ByteStringBuffer = util.ByteStringBuffer // export const pkcs8fromPrivateKeyBytes = (pkStr: string, pkBytes: Uint8Array) => { // // const dec = new TextDecoder() // // const decPK = dec.decode(pk) // const pkBtoa = btoa(pkStr) // const pkAB = str2ab(pkBtoa) // // pkBtoa: "ZTMxMGJjZjZlNzg2ZmQ0ZWI0ZTVmYjM2NTJkMGRjMWEzYzY2YTZiMDRlNzZkODg2ZTQzNjhjNWQxODYyMDcwYQ==" // // correct: 'MGsCAQEEICYpaA7qX++bvJzY7jtD+VA2dcrxjckW6rSLgb1udloLoUQDQgAEqZ9FI+0Ks2GD6PHONGfG1cAiJePtwyoelgtD7Dlk3Hi0AK4wgXT/bOxaEQ3oN8fwaqjdPyrO1SJ2dNQyhXrqtA==' // const enc64 = util.encode64(pkStr) // const url64 = base64ToUrlBase64(pkBtoa) // const bitStringAsn = asn1.toDer({ bitStringContents: url64 }) // const newAsnPK = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, ab2str(pkAB)) // when not "constructed" it will contain the ASN.1 value as an array of bytes formatted according to the ASN.1 data type. */ // const example = { // 'tagClass': 0, // 'type': 4, // 'constructed': false, // 'composed': false, // 'value': // "0k\u0002\u0001\u0001\u0004 ¡ù¬ÄÊ\u0013LB´,\u0014Ë0\u0004iÿg{\u0011àp¬‰½Òáï g\u0010~¡D\u0003B\u0000\u0004\u000f\u000fp\\ÈC­Eqœ»\r { // const enc = new TextEncoder() // const dec = new TextDecoder() // const localKeyPair = await globalThis.crypto.subtle.generateKey( // { // name: 'ECDH', // namedCurve: 'P-256', // }, // true, // ['deriveKey', 'deriveBits'], // ) // const exportedECDH = await globalThis.crypto.subtle.exportKey('pkcs8', localKeyPair.privateKey) // https://www.openscdp.org/scsh3/jsdoc/overview-summary-pkcs8.js.html // const exportedECDHjwk = await globalThis.crypto.subtle.exportKey('jwk', localKeyPair.privateKey) // // const btoaExp = btoa(exportedECDH) // W29iamVjdCBBcnJheUJ1ZmZlcl0= // const decECDH = dec.decode(exportedECDH) // console.log({ localKeyPair, exportedECDH, exportedECDHjwk, decECDH }) // } // ripped from https://github.com/paulmillr/noble-secp256k1/blob/main/index.ts /*! noble-secp256k1 - MIT License (c) 2019 Paul Miller (paulmillr.com) */ // type Bytes = Uint8Array // type Hex = Bytes | string // type PrivKey = Hex | bigint // const B256 = 2n ** 256n // secp256k1 is short weierstrass curve // const P = B256 - 0x1000003d1n // curve's field prime // const N = B256 - 0x14551231950b75fc4402da1732fc9bebfn // curve (group) order // const mod = (a: bigint, b = P) => { // let r = a % b // return r >= 0n ? r : b + r // } // mod division // const fLen = 32 // const Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n // base point x // const Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n // base point y // const CURVE = { p: P, n: N, a: 0n, b: 7n, Gx, Gy } // exported variables incl. a, b // field / group byte length // const crv = (x: bigint) => mod(mod(x * x) * x + CURVE.b) // x³ + ax + b weierstrass formula; a=0 // const err = (m = ''): never => { // throw new Error(m) // } // error helper, messes-up stack trace // const str = (s: unknown): s is string => typeof s === 'string' // is string // const au8 = (a: unknown, l?: number): Bytes => // // is Uint8Array (of specific length) // !(a instanceof Uint8Array) || (typeof l === 'number' && l > 0 && a.length !== l) ? // err('Uint8Array expected') : // a // const u8n = (data?: any) => new Uint8Array(data) // creates Uint8Array // const toU8 = (a: Hex, len?: number) => au8(str(a) ? h2b(a) : u8n(a), len) // norm(hex/u8a) to u8a // const big = (n: unknown): n is bigint => typeof n === 'bigint' // is big integer // const h2b = (hex: string): Bytes => { // hex to bytes // const l = hex.length // error if not string, // if (!str(hex) || l % 2) err('hex invalid 1') // or has odd length like 3, 5. // const arr = u8n(l / 2) // create result array // for (let i = 0; i < arr.length; i++) { // const j = i * 2 // const h = hex.slice(j, j + 2) // hexByte. slice is faster than substr // const b = Number.parseInt(h, 16) // byte, created from string part // if (Number.isNaN(b) || b < 0) err('hex invalid 2') // byte must be valid 0 <= byte < 256 // arr[i] = b // } // return arr // } // const padh = (n: number | bigint, pad: number) => n.toString(16).padStart(pad, '0') // const n2b = (num: bigint): Bytes => { // number to 32bytes. mustbe 0 <= num < B256 // return big(num) && num >= 0n && num < B256 ? h2b(padh(num, 2 * fLen)) : err('bigint expected') // } // export const b2h = (b: Bytes): string => Array.from(b).map(e => padh(e, 2)).join('') // bytes to hex // const b2n = (b: Bytes): bigint => BigInt('0x' + (b2h(b) || '0')) // bytes to number // export function hashToPrivateKey(hash: Hex): Bytes { // FIPS 186 B.4.1 compliant key generation // hash = toU8(hash) // produces private keys with modulo bias // const minLen = fLen + 8 // being neglible. // if (hash.length < minLen || hash.length > 1024) err('expected proper params') // const num = mod(b2n(hash), N - 1n) + 1n // takes at least n+8 bytes // return n2b(num) // }