UNPKG

@swtc/keypairs

Version:
334 lines 15.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Factory = void 0; const brorand_1 = __importDefault(require("brorand")); const hash_js_1 = __importDefault(require("hash.js")); const elliptic_1 = require("elliptic"); const sm_js_1 = require("@swtc/sm.js"); const bn_js_1 = __importDefault(require("bn.js")); const address_codec_1 = require("@swtc/address-codec"); const common_1 = require("@swtc/common"); const secp256k1_1 = require("./secp256k1"); const sm2p256v1_1 = require("./sm2p256v1"); const utils_1 = require("./utils"); const Ed25519 = elliptic_1.eddsa("ed25519"); const Secp256k1 = elliptic_1.ec("secp256k1"); // const Secp256k1Gm = sm2 function hashOpen(message) { return hash_js_1.default.sha512().update(message).digest().slice(0, 32); } function hashGm(message) { return new common_1.SM3().update(message).digest().slice(0, 32); } function Factory(chain_or_token = "jingtum") { const addressCodec = address_codec_1.Factory(chain_or_token); const guomi = addressCodec.guomi; const token = addressCodec.token; const hash = guomi ? hashGm : hashOpen; const secp256k1 = { deriveKeypair: (entropy, options = {}) => { const prefix = "00"; const privateKey = prefix + secp256k1_1.derivePrivateKey(entropy, options).toString(16, 64).toUpperCase(); const publicKey = common_1.funcBytesToHex(Secp256k1.keyFromPrivate(privateKey.slice(2)) .getPublic() .encodeCompressed()); return { privateKey, publicKey }; }, deriveKeypairWithPrivateKey: (rawPrivateKey) => { const prefix = "00"; const privateKey = prefix + rawPrivateKey.toUpperCase(); const publicKey = common_1.funcBytesToHex(Secp256k1.keyFromPrivate(privateKey.slice(2)) .getPublic() .encodeCompressed()); return { privateKey, publicKey }; }, sign: (message, privateKey) => { return common_1.funcBytesToHex(Secp256k1.sign(hash(message), common_1.funcHexToBytes(privateKey), { canonical: true }).toDER()); }, verify: (message, signature, publicKey) => { return Secp256k1.verify(hash(message), signature, common_1.funcHexToBytes(publicKey)); }, signTx: (message, privateKey) => { return common_1.funcBytesToHex(Secp256k1.sign(message, common_1.funcHexToBytes(privateKey), { canonical: true }).toDER()); }, verifyTx: (message, signature, publicKey) => { return Secp256k1.verify(message, signature, common_1.funcHexToBytes(publicKey)); } }; const sm2p256v1 = { deriveKeypair: (entropy, options = {}) => { const prefix = "00"; const pri = sm2p256v1_1.derivePrivateKey(entropy, options); const privateKey = prefix + pri.toString(16, 64).toUpperCase(); const publicKey = common_1.funcBytesToHex(sm_js_1.sm2.SM2KeyPair(null, pri).pub.encodeCompressed()); return { privateKey, publicKey }; }, deriveKeypairWithPrivateKey: (rawPrivateKey) => { const prefix = "00"; const pri = new bn_js_1.default(rawPrivateKey, "hex"); const privateKey = prefix + rawPrivateKey.toUpperCase(); const publicKey = common_1.funcBytesToHex(sm_js_1.sm2.SM2KeyPair(null, pri).pub.encodeCompressed()); return { privateKey, publicKey }; }, sign: (message, privateKey) => { const keypair = sm_js_1.sm2.SM2KeyPair(null, new bn_js_1.default(privateKey, "hex")); return common_1.funcBytesToHex(new sm_js_1.Signature(keypair.sign(hash(message))).toDER()); }, verify: (message, signature, publicKey) => { const keypair = sm_js_1.sm2.SM2KeyPair(publicKey); const sig = new sm_js_1.Signature(signature, "hex"); return keypair.verify(hash(message), sig.r, sig.s); }, signTx: (message, privateKey) => { if (typeof message === "string" && /^[0-9A-F]{16}/i.test(message)) { // if in hex format message = common_1.funcHexToBytes(message); } const keypair = sm_js_1.sm2.SM2KeyPair(null, new bn_js_1.default(privateKey, "hex")); return common_1.funcBytesToHex(new sm_js_1.Signature(keypair.sign(message)).toDER()); // return this.sign(message, privateKey) }, verifyTx: (message, signature, publicKey) => { if (typeof message === "string" && /^[0-9A-F]{16}/i.test(message)) { // if in hex format message = common_1.funcHexToBytes(message); } // if (typeof signature === "string" && /^[0-9A-F]{16}/i.test(signature)) { // // if in hex format // signature = hexToBytes(signature) // } const keypair = sm_js_1.sm2.SM2KeyPair(publicKey); const sig = new sm_js_1.Signature(signature, "hex"); return keypair.verify(hash(message), sig.r, sig.s); } }; const ed25519 = { deriveKeypair: (entropy) => { const prefix = "ED"; const rawPrivateKey = hash(entropy); const privateKey = prefix + common_1.funcBytesToHex(rawPrivateKey); const publicKey = prefix + common_1.funcBytesToHex(Ed25519.keyFromSecret(rawPrivateKey).pubBytes()); return { privateKey, publicKey }; }, deriveKeypairWithPrivateKey: (rawPrivateKey) => { const prefix = "ED"; const privateKey = prefix + rawPrivateKey.toUpperCase(); const publicKey = prefix + common_1.funcBytesToHex(Ed25519.keyFromSecret(common_1.funcHexToBytes(rawPrivateKey)).pubBytes()); return { privateKey, publicKey }; }, sign: (message, privateKey) => { // caution: Ed25519.sign interprets all strings as hex, stripping // any non-hex characters without warning common_1.funcAssert(Array.isArray(message), "message must be array of octets"); return common_1.funcBytesToHex(Ed25519.sign(message, common_1.funcHexToBytes(privateKey).slice(1)).toBytes()); }, verify: (message, signature, publicKey) => { return Ed25519.verify(message, common_1.funcHexToBytes(signature), common_1.funcHexToBytes(publicKey).slice(1)); }, signTx: (message, privateKey) => { // caution: Ed25519.sign interprets all strings as hex, stripping // any non-hex characters without warning return Ed25519.sign(message, common_1.funcHexToBytes(privateKey).slice(1)).toHex(); }, verifyTx: (message, signature, publicKey) => { return Ed25519.verify(message, common_1.funcHexToBytes(signature), common_1.funcHexToBytes(publicKey).slice(1)); } }; const ed25519guomi = { deriveKeypair: (entropy) => { const prefix = "ED"; const rawPrivateKey = hash(entropy); const privateKey = prefix + common_1.funcBytesToHex(rawPrivateKey); const publicKey = prefix + common_1.funcBytesToHex(Ed25519.keyFromSecret(rawPrivateKey).pubBytes()); return { privateKey, publicKey }; }, deriveKeypairWithPrivateKey: (rawPrivateKey) => { const prefix = "ED"; const privateKey = prefix + rawPrivateKey.toUpperCase(); const publicKey = prefix + common_1.funcBytesToHex(Ed25519.keyFromSecret(common_1.funcHexToBytes(rawPrivateKey)).pubBytes()); return { privateKey, publicKey }; }, sign: (message, privateKey) => { // caution: Ed25519.sign interprets all strings as hex, stripping // any non-hex characters without warning common_1.funcAssert(Array.isArray(message), "message must be array of octets"); return common_1.funcBytesToHex(Ed25519.sign(message, common_1.funcHexToBytes(privateKey).slice(1)).toBytes()); }, verify: (message, signature, publicKey) => { return Ed25519.verify(message, common_1.funcHexToBytes(signature), common_1.funcHexToBytes(publicKey).slice(1)); }, signTx: (message, privateKey) => { // caution: Ed25519.sign interprets all strings as hex, stripping // any non-hex characters without warning return Ed25519.sign(message, common_1.funcHexToBytes(privateKey).slice(1)).toHex(); }, verifyTx: (message, signature, publicKey) => { return Ed25519.verify(message, common_1.funcHexToBytes(signature), common_1.funcHexToBytes(publicKey).slice(1)); } }; function generateSeed(options = {}) { common_1.funcAssert(!options.entropy || options.entropy.length >= 16, "entropy too short"); const entropy = options.entropy ? options.entropy.slice(0, 16) : brorand_1.default(16); const type = options.algorithm === "ed25519" ? "ed25519" : guomi ? "sm2p256v1" : "secp256k1"; return addressCodec.encodeSeed(entropy, type); } function select(algorithm) { const methods = { secp256k1, sm2p256v1, ed25519, ed25519guomi }; // return guomi ? methods[`${algorithm}guomi`] : methods[algorithm] return algorithm === "ed25519" ? guomi ? methods.ed25519guomi : methods.ed25519 : methods[algorithm]; } function getAlgorithmFromKey(key) { const bytes = common_1.funcHexToBytes(key); return bytes.length === 33 && bytes[0] === 0xed ? "ed25519" : guomi ? "sm2p256v1" : "secp256k1"; } function sign(messageHex, privateKey) { const algorithm = getAlgorithmFromKey(privateKey); return select(algorithm).sign(common_1.funcHexToBytes(messageHex), privateKey); } function verify(messageHex, signature, publicKey) { const algorithm = getAlgorithmFromKey(publicKey); return select(algorithm).verify(common_1.funcHexToBytes(messageHex), signature, publicKey); } function signTx(messageHex, privateKey) { const algorithm = getAlgorithmFromKey(privateKey); return select(algorithm).signTx(messageHex, privateKey); } function verifyTx(messageHex, signature, publicKey) { const algorithm = getAlgorithmFromKey(publicKey); return select(algorithm).verifyTx(messageHex, signature, publicKey); } function deriveKeypair(secret_or_private_key, algorithm = guomi ? "sm2p256v1" : "secp256k1") { const secret = secret_or_private_key; let private_key = secret_or_private_key; let keypair; let method; if (typeof secret_or_private_key !== "string") { // use privateKey to generate keypairs, using algorithm throw new Error("deriving keypair requires secret or private key"); } else if (/^s/.test(secret_or_private_key)) { // use secret to derive, secret has algorithm information already const decoded = addressCodec.decodeSeed(secret); algorithm = decoded.type === "ed25519" ? "ed25519" : guomi ? "sm2p256v1" : "secp256k1"; method = select(algorithm); keypair = method.deriveKeypair(decoded.bytes); } else { // use private key to derive, could be raw privateKey or prefixed privateKey if (secret_or_private_key.length === 64) { // raw private key, has no information on algorithm algorithm = algorithm === "ed25519" ? "ed25519" : guomi ? "sm2p256v1" : "secp256k1"; } else if (secret_or_private_key.length === 66) { // prefixed private key, has information on algorithm if (secret_or_private_key.slice(0, 2) === "00") { algorithm = guomi ? "sm2p256v1" : "secp256k1"; } else if (secret_or_private_key.slice(0, 2).toUpperCase() === "ED") { algorithm = "ed25519"; } else { throw new Error("deriving keypair requires correct prefixed private key"); } private_key = secret_or_private_key.slice(2); } else { throw new Error("deriving keypair requires valid private key"); } method = select(algorithm); keypair = method.deriveKeypairWithPrivateKey(private_key); } const messageToVerify = hash("This test message should verify."); const signature = method.sign(messageToVerify, keypair.privateKey); if (method.verify(messageToVerify, signature, keypair.publicKey) !== true) { throw new Error("derived keypair did not generate verifiable signature"); } return keypair; } function deriveAddressFromBytes(publicKeyBytes) { return addressCodec.encodeAccountID(Buffer.from(guomi ? utils_1.computePublicKeyHashGm(publicKeyBytes) : utils_1.computePublicKeyHash(publicKeyBytes))); } function deriveAddress(publicKey) { return deriveAddressFromBytes(common_1.funcHexToBytes(publicKey)); } function deriveNodeAddress(publicKey) { const generatorBytes = addressCodec.decodeNodePublic(publicKey); const accountPublicBytes = guomi ? sm2p256v1_1.accountPublicFromPublicGenerator(generatorBytes) : secp256k1_1.accountPublicFromPublicGenerator(generatorBytes); return deriveAddressFromBytes(accountPublicBytes); } function convertAddressToBytes(address) { return addressCodec.decodeAddress(address).toJSON().data; } function convertBytesToAddress(bytes) { return addressCodec.encodeAddress(bytes); } return { // secp256k1, // secp256k1guomi, // ed25519, // decodeSeed: addressCodec.decodeSeed guomi, token, // for swtc libs addressCodec, deriveKeyPair: deriveKeypair, hash, seedFromPhrase: guomi ? utils_1.seedFromPhraseGm : utils_1.seedFromPhrase, signTx, verifyTx, convertAddressToBytes, convertBytesToAddress, checkAddress: addressCodec.isValidAddress, isValidAddress: addressCodec.isValidAddress, // standards deriveKeypair, generateSeed, sign, verify, deriveAddress, deriveNodeAddress }; } exports.Factory = Factory; //# sourceMappingURL=keypairs.js.map