swtc-keypairs
Version:
swtc keypairs
166 lines • 7.08 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const assert_1 = __importDefault(require("assert"));
const brorand_1 = __importDefault(require("brorand"));
const hash_js_1 = __importDefault(require("hash.js"));
const elliptic_1 = require("elliptic");
const swtc_address_codec_1 = require("swtc-address-codec");
const swtc_chains_1 = require("swtc-chains");
const secp256k1_1 = require("./secp256k1");
const utils_1 = require("./utils");
const Ed25519 = elliptic_1.eddsa("ed25519");
const Secp256k1 = elliptic_1.ec("secp256k1");
function hash(message) {
return hash_js_1.default
.sha512()
.update(message)
.digest()
.slice(0, 32);
}
const secp256k1 = {
deriveKeypair: (entropy, options = {}) => {
const prefix = "00";
const privateKey = prefix +
secp256k1_1.derivePrivateKey(entropy, options)
.toString(16, 64)
.toUpperCase();
const publicKey = swtc_chains_1.funcBytesToHex(Secp256k1.keyFromPrivate(privateKey.slice(2))
.getPublic()
.encodeCompressed());
return { privateKey, publicKey };
},
sign: (message, privateKey) => {
return swtc_chains_1.funcBytesToHex(Secp256k1.sign(hash(message), swtc_chains_1.funcHexToBytes(privateKey), {
canonical: true
}).toDER());
},
verify: (message, signature, publicKey) => {
return Secp256k1.verify(hash(message), signature, swtc_chains_1.funcHexToBytes(publicKey));
},
signTx: (message, privateKey) => {
return swtc_chains_1.funcBytesToHex(Secp256k1.sign(message, swtc_chains_1.funcHexToBytes(privateKey), {
canonical: true
}).toDER());
},
verifyTx: (message, signature, publicKey) => {
return Secp256k1.verify(message, signature, swtc_chains_1.funcHexToBytes(publicKey));
}
};
const ed25519 = {
deriveKeypair: entropy => {
const prefix = "ED";
const rawPrivateKey = hash(entropy);
const privateKey = prefix + swtc_chains_1.funcBytesToHex(rawPrivateKey);
const publicKey = prefix + swtc_chains_1.funcBytesToHex(Ed25519.keyFromSecret(rawPrivateKey).pubBytes());
return { privateKey, publicKey };
},
sign: (message, privateKey) => {
// caution: Ed25519.sign interprets all strings as hex, stripping
// any non-hex characters without warning
assert_1.default(Array.isArray(message), "message must be array of octets");
return swtc_chains_1.funcBytesToHex(Ed25519.sign(message, swtc_chains_1.funcHexToBytes(privateKey).slice(1)).toBytes());
},
verify: (message, signature, publicKey) => {
return Ed25519.verify(message, swtc_chains_1.funcHexToBytes(signature), swtc_chains_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, swtc_chains_1.funcHexToBytes(privateKey).slice(1)).toHex();
},
verifyTx: (message, signature, publicKey) => {
return Ed25519.verify(message, swtc_chains_1.funcHexToBytes(signature), swtc_chains_1.funcHexToBytes(publicKey).slice(1));
}
};
function select(algorithm) {
const methods = { "ecdsa-secp256k1": secp256k1, ed25519 };
return methods[algorithm];
}
function getAlgorithmFromKey(key) {
const bytes = swtc_chains_1.funcHexToBytes(key);
return bytes.length === 33 && bytes[0] === 0xed
? "ed25519"
: "ecdsa-secp256k1";
}
function sign(messageHex, privateKey) {
const algorithm = getAlgorithmFromKey(privateKey);
return select(algorithm).sign(swtc_chains_1.funcHexToBytes(messageHex), privateKey);
}
function verify(messageHex, signature, publicKey) {
const algorithm = getAlgorithmFromKey(publicKey);
return select(algorithm).verify(swtc_chains_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 Factory(chain_or_token = "jingtum") {
const addressCodec = swtc_address_codec_1.Factory(chain_or_token);
function generateSeed(options = {}) {
assert_1.default(!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" : "secp256k1";
return addressCodec.encodeSeed(entropy, type);
}
function deriveKeypair(seed, options = {}) {
const decoded = addressCodec.decodeSeed(seed);
const algorithm = decoded.type === "ed25519" ? "ed25519" : "ecdsa-secp256k1";
const method = select(algorithm);
const keypair = method.deriveKeypair(decoded.bytes, options);
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(utils_1.computePublicKeyHash(publicKeyBytes)));
}
function deriveAddress(publicKey) {
return deriveAddressFromBytes(swtc_chains_1.funcHexToBytes(publicKey));
}
function deriveNodeAddress(publicKey) {
const generatorBytes = addressCodec.decodeNodePublic(publicKey);
const accountPublicBytes = 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,
// ed25519,
// decodeSeed: addressCodec.decodeSeed
// for swtc libs
addressCodec,
chain: addressCodec.chain,
deriveKeyPair: deriveKeypair,
hash,
signTx,
verifyTx,
convertAddressToBytes,
convertBytesToAddress,
checkAddress: addressCodec.isValidAddress,
isValidAddress: addressCodec.isValidAddress,
// standards
deriveKeypair,
generateSeed,
sign,
verify,
deriveAddress,
deriveNodeAddress
};
}
exports.Factory = Factory;
//# sourceMappingURL=keypairs.js.map