@signumjs/crypto
Version:
Cryptographic functions for building Signum Network apps.
141 lines • 4.94 kB
JavaScript
"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