UNPKG

@signumjs/crypto

Version:

Cryptographic functions for building Signum Network apps.

141 lines 4.94 kB
"use strict"; /** * Original work Copyright (c) 2024 Signum Network */ Object.defineProperty(exports, "__esModule", { value: true }); exports.generateSignedTransactionBytes = void 0; exports.generateSignKeys = generateSignKeys; exports.getAccountIdFromPublicKey = getAccountIdFromPublicKey; exports.generateSignature = generateSignature; exports.verifySignature = verifySignature; const sha256_1 = require("./sha256"); const base_1 = require("./base"); function hexToDec(s) { const digits = [0]; for (let i = 0; i < s.length; i += 1) { let carry = parseInt(s.charAt(i), 16); for (let j = 0; j < digits.length; j += 1) { digits[j] = digits[j] * 16 + carry; carry = digits[j] / 10 | 0; digits[j] %= 10; } while (carry > 0) { digits.push(carry % 10); carry = carry / 10 | 0; } } return digits.reverse().join(''); } function toBytes(hex) { return new Uint8Array(Buffer.from(hex, 'hex')); } function mergeArrays(a, b) { const merged = new Uint8Array(a.length + b.length); merged.set(a); merged.set(b, a.length); return merged; } /** * Generate the Signum Sign Keys from an initial Passphrase. * @param passPhrase The passphrase * @return EC-KCDSA sign key pair + agreement key * * @category signing */ function generateSignKeys(passPhrase) { const hashedPassPhrase = (0, sha256_1.sha256AsBytes)(passPhrase); const keys = base_1.ECKCDSA.keygen(hashedPassPhrase); return { publicKey: Buffer.from(keys.p).toString('hex'), signPrivateKey: Buffer.from(keys.s).toString('hex'), agreementPrivateKey: Buffer.from(keys.k).toString('hex') }; } /** * Computes the Account ID from Public Key * @param publicKey The public Key generated with {@link generateSignKeys} * @return A numeric string - The Account ID */ function getAccountIdFromPublicKey(publicKey) { const hashedArray = (0, sha256_1.sha256Binary)(publicKey); const slicedArray = hashedArray.slice(0, 8).reverse(); return hexToDec(Buffer.from(slicedArray).toString('hex')); } /** * Generate a signature for a transaction * * Method: * ``` * s = sign(sha256(sha256(transactionHex)_keygen(sha256(sha256(transactionHex)_privateKey)).publicKey), * sha256(sha256(transactionHex)_privateKey), * privateKey) * p = sha256(sha256(transactionHex)_keygen(sha256(transactionHex_privateKey)).publicKey) * ``` * @see {@link verifySignature} * @param messageHex The data in hexadecimal representation * @param privateKeyHex The private key for signing in hexadecimal representation * @return The signature in hexadecimal format * * @category signing */ function generateSignature(messageHex, privateKeyHex) { const m = (0, sha256_1.sha256Binary)(messageHex); const s = toBytes(privateKeyHex); const m_s = mergeArrays(m, s); const x = (0, sha256_1.sha256Binary)(m_s); const y = Buffer.from(base_1.ECKCDSA.keygen(x).p); const m_y = mergeArrays(m, y); const h = (0, sha256_1.sha256Binary)(m_y); const v = Buffer.from(base_1.ECKCDSA.sign(h, x, s)); return Buffer.from(mergeArrays(v, h)).toString('hex'); } /** * Verify a signature for given message * * * Method: * ``` * * h1 = sha256(sha256(transactionHex)_keygen(sha256(transactionHex_privateKey)).publicKey) * == * sha256(sha256(transactionHex)_verify(v, h1, publickey)) = h2 * ``` * @see {@link generateSignature} * @param signature The signature to be verified * @param messageHex The message data in hexadecimal representation * @param publicKeyHex The public key * @return _true_, if signature is valid, otherwise _false_ * * @category signing */ function verifySignature(signature, messageHex, publicKeyHex) { const signatureBytes = toBytes(signature); const publicKeyBytes = toBytes(publicKeyHex); const v = signatureBytes.slice(0, 32); const h1 = signatureBytes.slice(32); const y = Buffer.from(base_1.ECKCDSA.verify(v, h1, publicKeyBytes)); const m = (0, sha256_1.sha256Binary)(messageHex); const m_y = mergeArrays(m, y); const h2 = (0, sha256_1.sha256Binary)(m_y); // fast comparison if (h1.length !== h2.length) { return false; } for (let i = 0; i < h1.length; i++) { if (h1[i] !== h2[i]) { return false; } } return true; } /** * Generates a signed message digest, which can be sent to Signum Node API then * * @see {@link generateSignature} * @param unsignedTransactionHex The unsigned message * @param signature The signature * @return The signed message digest * * @category signing */ const generateSignedTransactionBytes = (unsignedTransactionHex, signature) => unsignedTransactionHex.substr(0, 192) + signature + unsignedTransactionHex.substr(320); exports.generateSignedTransactionBytes = generateSignedTransactionBytes; //# sourceMappingURL=sign.js.map