UNPKG

tezos-sign

Version:
233 lines (212 loc) 6.57 kB
/*! * tezos-sign 1.4.0 (https://github.com/yugasun/tezos-sign) * API https://github.com/yugasun/tezos-sign/blob/master/doc/api.md * Copyright 2017-2019 yugasun. All Rights Reserved * Licensed under MIT (https://github.com/yugasun/tezos-sign/blob/master/LICENSE) */ import sodium from 'libsodium-wrappers'; import bs58check from 'bs58check'; import bip39 from 'bip39'; var prefix = { tz1: new Uint8Array([6, 161, 159]), edsk: new Uint8Array([43, 246, 78, 7]), edsk2: new Uint8Array([13, 15, 58, 7]), edpk: new Uint8Array([13, 15, 37, 217]), edsig: new Uint8Array([9, 245, 205, 134, 18]), o: new Uint8Array([5, 116]) }; var utility = { b58cencode: function b58cencode(payload, prefix) { var n = new Uint8Array(prefix.length + payload.length); n.set(prefix); n.set(payload, prefix.length); return bs58check.encode(Buffer.from(n, 'hex')); }, b58cdecode: function b58cdecode(enc, prefix) { return bs58check.decode(enc).slice(prefix.length); }, buf2hex: function buf2hex(buffer) { var byteArray = new Uint8Array(buffer); var hexParts = []; for (var i = 0; i < byteArray.length; i += 1) { var hex = byteArray[i].toString(16); var paddedHex = ('00' + hex).slice(-2); hexParts.push(paddedHex); } return hexParts.join(''); }, hex2buf: function hex2buf(hex) { var t = hex.match(/[\da-f]{2}/gi).map(function (h) { return parseInt(h, 16); }); var b = new Uint8Array(t); return b; }, mergebuf: function mergebuf(b1, b2) { var r = new Uint8Array(b1.length + b2.length); r.set(b1); r.set(b2, b1.length); return r; }, generateMnemonic: function generateMnemonic() { return bip39.generateMnemonic(160); } }; /** * generate keys * * @param {string} name passphrase * @return {object} */ function generateKeys(name) { try { var m = utility.generateMnemonic(); var s = bip39.mnemonicToSeed(m, name).slice(0, 32); var kp = sodium.crypto_sign_seed_keypair(s); var sk = utility.b58cencode(kp.privateKey, prefix.edsk); var pk = utility.b58cencode(kp.publicKey, prefix.edpk); var hash = sodium.crypto_generichash(20, kp.publicKey); var pkh = utility.b58cencode(hash, prefix.tz1); return { mnemonic: m, passphrase: name, sk: sk, pk: pk, pkh: pkh }; } catch (e) { throw new Error('Generate failed: ' + e.message); } } /** * generate keys without seed * * @return {object} */ function generateKeysNoSeed() { try { var kp = sodium.crypto_sign_keypair(); var sk = utility.b58cencode(kp.privateKey, prefix.edsk); var pk = utility.b58cencode(kp.publicKey, prefix.edpk); var hash = sodium.crypto_generichash(20, kp.publicKey); var pkh = utility.b58cencode(hash, prefix.tz1); return { sk: sk, pk: pk, pkh: pkh }; } catch (e) { throw new Error('Generate failed: ' + e.message); } } /** * extract keys * * @param {string} sk private key * @return {object} */ function extractKeys(sk) { try { var pref = sk.substr(0, 4); switch (pref) { case 'edsk': if (sk.length === 98) { var decodeEdsk = utility.b58cdecode(sk, prefix.edsk).slice(32); var pk = utility.b58cencode(decodeEdsk, prefix.edpk); var hash = sodium.crypto_generichash(20, decodeEdsk); var pkh = utility.b58cencode(hash, prefix.tz1); return { pk: pk, pkh: pkh, sk: sk }; } if (sk.length === 54) { // seed var s = utility.b58cdecode(sk, prefix.edsk2); var kp = sodium.crypto_sign_seed_keypair(s); var _hash = sodium.crypto_generichash(20, kp.publicKey); var sk1 = utility.b58cencode(kp.privateKey, prefix.edsk); var _pk = utility.b58cencode(kp.publicKey, prefix.edpk); var _pkh = utility.b58cencode(_hash, prefix.tz1); return { sk: sk1, pk: _pk, pkh: _pkh }; } break; default: return false; } } catch (e) { throw new Error('Extract private key failed: ' + e.message); } } /** * tezos offline sign * * @param {string} bytes operation bytes * @param {string} sk private key * @return {object} */ function sign(bytes, sk) { try { var bb = utility.hex2buf(bytes); var wm = new Uint8Array([3]); if (typeof wm !== 'undefined') bb = utility.mergebuf(wm, bb); var chash = sodium.crypto_generichash(32, bb); var edsk = utility.b58cdecode(sk, prefix.edsk); var sig = sodium.crypto_sign_detached(chash, edsk, 'uint8array'); var edsig = utility.b58cencode(sig, prefix.edsig); var sbytes = bytes + utility.buf2hex(sig); return { bytes: bytes, sig: sig, edsig: edsig, sbytes: sbytes }; } catch (e) { throw new Error('Sign failed: ' + e.message); } } /** * validate address * * @param {string} a address * @return {bool} */ function checkAddress(a) { try { utility.b58cdecode(a, prefix.tz1); return true; } catch (e) { return false; } } /** * generate tx hash * * @param {string} sbytes signed op bytes * @return {string} */ function generateTxHash(sbytes) { try { var hexBuffer = utility.hex2buf(sbytes); var soHash = sodium.crypto_generichash(32, hexBuffer); var hash = utility.b58cencode(soHash, prefix.o); return hash; } catch (e) { throw new Error('Generate transaction hash failed: ' + e.message); } } var index = { generateKeys: generateKeys, generateKeysNoSeed: generateKeysNoSeed, extractKeys: extractKeys, sign: sign, checkAddress: checkAddress, generateTxHash: generateTxHash }; export default index; export { generateKeys, generateKeysNoSeed, extractKeys, sign, checkAddress, generateTxHash };