var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; // For ESM compatibility import pkg from 'elliptic'; const { ec } = pkg; import { BeeError } from "../utils/error.js"; import { isBytes, assertBytes, wrapBytesWithHelpers } from "../utils/bytes.js"; import { keccak256Hash } from "../utils/hash.js"; import { hexToBytes, makeHexString } from "../utils/hex.js"; import { SIGNATURE_BYTES_LENGTH, SIGNATURE_HEX_LENGTH } from "../types/index.js"; import { isStrictlyObject } from "../utils/type.js"; const UNCOMPRESSED_RECOVERY_ID = 27; function hashWithEthereumPrefix(data) { const ethereumSignedMessagePrefix = `\x19Ethereum Signed Message:\n${data.length}`; const prefixBytes = new TextEncoder().encode(ethereumSignedMessagePrefix); return keccak256Hash(prefixBytes, data); } /** * The default signer function that can be used for integrating with * other applications (e.g. wallets). * * @param data The data to be signed * @param privateKey The private key used for signing the data */ export function defaultSign(data, privateKey) { const curve = new ec('secp256k1'); const keyPair = curve.keyFromPrivate(privateKey); const hashedDigest = hashWithEthereumPrefix(data); const sigRaw = curve.sign(hashedDigest, keyPair, { canonical: true, pers: undefined }); if (sigRaw.recoveryParam === null) { throw new BeeError('signDigest recovery param was null'); } const signature = new Uint8Array([...sigRaw.r.toArray('be', 32), ...sigRaw.s.toArray('be', 32), sigRaw.recoveryParam + UNCOMPRESSED_RECOVERY_ID]); return signature; } function publicKeyToAddress(pubKey) { const pubBytes = pubKey.encode('array', false); return keccak256Hash(pubBytes.slice(1)).slice(12); } /** * Recovers the ethereum address from a given signature. * * Can be used for verifying a piece of data when the public key is * known. * * @param signature The signature * @param digest The digest of the data * * @returns the recovered address */ export function recoverAddress(signature, digest) { const curve = new ec('secp256k1'); const sig = { r: signature.slice(0, 32), s: signature.slice(32, 64) }; const recoveryParam = signature[64] - UNCOMPRESSED_RECOVERY_ID; const hash = hashWithEthereumPrefix(digest); const recPubKey = curve.recoverPubKey(hash, sig, recoveryParam); return publicKeyToAddress(recPubKey); } /** * Creates a singer object that can be used when the private key is known. * * @param privateKey The private key */ export function makePrivateKeySigner(privateKey) { const curve = new ec('secp256k1'); const keyPair = curve.keyFromPrivate(privateKey); const address = publicKeyToAddress(keyPair.getPublic()); return { sign: digest => defaultSign(digest, privateKey), address }; } export function assertSigner(signer) { if (!isStrictlyObject(signer)) { throw new TypeError('Signer must be an object!'); } const typedSigner = signer; if (!isBytes(typedSigner.address, 20)) { throw new TypeError("Signer's address must be Uint8Array with 20 bytes!"); } if (typeof typedSigner.sign !== 'function') { throw new TypeError('Signer sign property needs to be function!'); } } export function makeSigner(signer) { if (typeof signer === 'string') { const hexKey = makeHexString(signer, 64); const keyBytes = hexToBytes(hexKey); // HexString is verified for 64 length => 32 is guaranteed return makePrivateKeySigner(keyBytes); } else if (signer instanceof Uint8Array) { assertBytes(signer, 32); return makePrivateKeySigner(signer); } assertSigner(signer); return signer; } export function sign(signer, data) { return __awaiter(this, void 0, void 0, function* () { const result = yield signer.sign(wrapBytesWithHelpers(data)); if (typeof result === 'string') { const hexString = makeHexString(result, SIGNATURE_HEX_LENGTH); return hexToBytes(hexString); } if (result instanceof Uint8Array) { assertBytes(result, SIGNATURE_BYTES_LENGTH); return result; } throw new TypeError('Invalid output of sign function!'); }); }