删掉所有 option 参数,换用具体的 {...}

This commit is contained in:
陆柯 2021-05-08 22:34:01 +08:00
parent 8780cd1c40
commit 8873cd8884

169
index.js
View File

@ -17,11 +17,11 @@ const secp256k1 = require('secp256k1')
const my = {} const my = {}
my.HASHER = 'sha256' // 默认的哈希算法。could be md5, sha1, sha256, sha512, ripemd160 and much more。 可用 Crypto.getHashes/Ciphers/Curves() 查看支持的种类。 my.HASHER = 'sha256' // 默认的哈希算法。could be md5, sha1, sha256, sha512, ripemd160 and much more。 可用 Crypto.getHashes/Ciphers/Curves() 查看支持的种类。
my.HASHER_LIST = crypto.getHashes() my.HASHER_LIST = typeof crypto.getHashes === 'function' ? crypto.getHashes() : [my.HASHER]
my.CIPHER = 'aes-256-cfb' // 默认的加解密算法 my.CIPHER = 'aes-256-cfb' // 默认的加解密算法
my.CIPHER_LIST = crypto.getCiphers() my.CIPHER_LIST = typeof crypto.getCiphers === 'function' ? crypto.getCiphers() : [my.CIPHER]
my.CURVE = 'secp256k1' // 默认的ECDH曲线用于把私钥转成公钥。 my.CURVE = 'secp256k1' // 默认的ECDH曲线用于把私钥转成公钥。
my.CURVE_LIST = ['secp256k1'] // crypto.getCurves() 引入到浏览器里后出错,不支持 getCurves. my.CURVE_LIST = typeof crypto.getCurves === 'function' ? crypto.getCurves() : [my.CURVE] // crypto.getCurves() 引入到浏览器里后出错,不支持 getCurves.
my.OUTPUT = 'hex' // 默认的哈希或加密的输入格式 my.OUTPUT = 'hex' // 默认的哈希或加密的输入格式
my.OUTPUT_LIST = ['hex', 'latin1', 'base64'] // or 'buf' to Buffer explicitly my.OUTPUT_LIST = ['hex', 'latin1', 'base64'] // or 'buf' to Buffer explicitly
my.INPUT = 'utf8' // 默认的加密方法的明文格式。utf8 能够兼容 latin1, ascii 的情形 my.INPUT = 'utf8' // 默认的加密方法的明文格式。utf8 能够兼容 latin1, ascii 的情形
@ -30,7 +30,6 @@ my.COIN = 'TIC' // 默认的币种
my.COIN_LIST = ['TIC', 'BTC', 'ETH'] my.COIN_LIST = ['TIC', 'BTC', 'ETH']
/** /**
*
* *
* @class TICrypto * @class TICrypto
*/ */
@ -160,8 +159,8 @@ class TICrypto {
if (this.isHashable(data)) { if (this.isHashable(data)) {
if (typeof data !== 'string' && !(data instanceof Buffer) && !(data instanceof DataView)) data = JSON.stringify(data) if (typeof data !== 'string' && !(data instanceof Buffer) && !(data instanceof DataView)) data = JSON.stringify(data)
if (salt && typeof salt === 'string') data = data + this.hash(salt) if (salt && typeof salt === 'string') data = data + this.hash(salt)
let inputEncoding = input // my.INPUT_LIST.indexOf(option.input)>=0?option.input:my.INPUT // 'utf8', 'ascii' or 'latin1' for string data, default to utf8 if not specified; ignored for Buffer, TypedArray, or DataView. let inputEncoding = input // my.INPUT_LIST.indexOf(input)>=0?input:my.INPUT // 'utf8', 'ascii' or 'latin1' for string data, default to utf8 if not specified; ignored for Buffer, TypedArray, or DataView.
let outputEncoding = output === 'buf' ? undefined : output // (my.OUTPUT_LIST.indexOf(output)>=0?output:my.OUTPUT) // option.output: 留空=》默认输出hex格式或者手动指定 'buf', hex', 'latin1' or 'base64' let outputEncoding = output === 'buf' ? undefined : output // (my.OUTPUT_LIST.indexOf(output)>=0?output:my.OUTPUT) // output: 留空=》默认输出hex格式或者手动指定 'buf', hex', 'latin1' or 'base64'
return crypto.createHash(hasher).update(data, inputEncoding).digest(outputEncoding) return crypto.createHash(hasher).update(data, inputEncoding).digest(outputEncoding)
} }
return null return null
@ -280,9 +279,11 @@ class TICrypto {
} else if (seckey.length === 64) { } else if (seckey.length === 64) {
// 纯 crypto // 纯 crypto
let seckeyPEM = await new keyman.Key('oct', this.hex2buf(seckey), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。 let seckeyPEM = await new keyman.Key('oct', this.hex2buf(seckey), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
let signer = crypto.createSign(['sha1', 'sha256', 'sha512'].indexOf(hasher) >= 0 ? hasher : my.HASHER) // let signer = crypto.createSign(my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER) // 注意不知为何hasher必须含有'sha'才能完成签名,例如 sha1, sha256, sha512, sha3, RSA-SHA1, id-rsassa-pkcs1-v1_5-with-sha3-224, 其他都会报错。
signer.update(this.hash(data)).end() // signer.update(this.hash(data)).end()
let signature = signer.sign(seckeyPEM, 'hex') // let signature = signer.sign(seckeyPEM, 'hex')
// since nodejs 12, 有了 crypto.sign 方法:
let signature = crypto.sign(my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER, Buffer.from(this.hash(data)), seckeyPEM).toString('hex')
return signature // 发现同样的输入nodejs里每次调用会生成不同的 signature, 且长度不定(140,142,144 hex) 但都可以通过 verify。但在浏览器里调用signature却是固定的。 return signature // 发现同样的输入nodejs里每次调用会生成不同的 signature, 且长度不定(140,142,144 hex) 但都可以通过 verify。但在浏览器里调用signature却是固定的。
} }
} }
@ -310,7 +311,7 @@ class TICrypto {
let verified = nacl.sign.detached.verify(bufHash, bufSignature, bufPubkey) let verified = nacl.sign.detached.verify(bufHash, bufSignature, bufPubkey)
return verified return verified
} else if ('eccrypto' === tool && signature.length >= 140) { } else if ('eccrypto' === tool && signature.length >= 140) {
// 默认使用 eccrypto // 默认使用 eccrypto // 发现大小写不影响 eccrypto 验签!都能通过
try { try {
let result = await eccrypto.verify(Buffer.from(pubkey, 'hex'), this.hash(data, { output: 'buf' }), Buffer.from(signature, 'hex')) // 如果给signature添加1位hexeccrypto 的 verify结果也是true! 估计因为一位hex不被转成字节。 let result = await eccrypto.verify(Buffer.from(pubkey, 'hex'), this.hash(data, { output: 'buf' }), Buffer.from(signature, 'hex')) // 如果给signature添加1位hexeccrypto 的 verify结果也是true! 估计因为一位hex不被转成字节。
return true return true
@ -319,11 +320,18 @@ class TICrypto {
return false return false
} }
} else if (signature.length >= 140) { } else if (signature.length >= 140) {
// 纯 crypto // 纯 crypto // 发现大小写不影响 crypto 验签!都能通过
let pubkeyPEM = await new keyman.Key('oct', this.hex2buf(pubkey), { namedCurve: 'P-256K' }).export('pem') // 公钥导出的der格式为88字节。经测试同一对压缩和非压缩公钥得出的结果一模一样。 let pubkeyPEM = await new keyman.Key('oct', this.hex2buf(pubkey), { namedCurve: 'P-256K' }).export('pem') // 公钥导出的der格式为88字节。经测试同一对压缩和非压缩公钥得出的结果一模一样。
let verifier = crypto.createVerify(['sha1', 'sha256', 'sha512'].indexOf(hasher) >= 0 ? hasher : my.HASHER) // let verifier = crypto.createVerify(my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER)
verifier.update(this.hash(data)).end() // end() 在 nodejs 12 里返回verifier自身但在浏览器里返回 undefined因此不能串联运行。 // verifier.update(this.hash(data)).end() // end() 在 nodejs 12 里返回verifier自身但在浏览器里返回 undefined因此不能串联运行。
let verified = verifier.verify(pubkeyPEM, signature, 'hex') // 如果给signature添加1位hexcrypto 的 verify结果也是true! 估计因为一位hex不被转成字节。但减少1位会导致false // let verified = verifier.verify(pubkeyPEM, signature, 'hex') // 如果给signature添加1位hexcrypto 的 verify结果也是true! 估计因为一位hex不被转成字节。但减少1位会导致false
// since nodejs 12, 有了 crypto.verify 方法:
let verified = crypto.verify(
my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER,
Buffer.from(this.hash(data)),
pubkeyPEM,
Buffer.from(signature, 'hex')
)
return verified return verified
} }
} }
@ -339,12 +347,11 @@ class TICrypto {
* @return {Object} {pubkey, seckey, address,} * @return {Object} {pubkey, seckey, address,}
* @memberof TICrypto * @memberof TICrypto
*/ */
static pass2keypair(pass, option) { static pass2keypair(pass, { hasher } = {}) {
// 如果使用其他机制例如密码、随机数不使用secword也可生成keypair // 如果使用其他机制例如密码、随机数不使用secword也可生成keypair
if (this.isHashable(pass)) { if (this.isHashable(pass)) {
option = option || {} hasher = my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER
option.hasher = my.HASHER_LIST.indexOf(option.hasher) >= 0 ? option.hasher : my.HASHER var hashBuf = crypto.createHash(hasher).update(pass).digest()
var hashBuf = crypto.createHash(option.hasher).update(pass).digest()
var keypair = nacl.sign.keyPair.fromSeed(hashBuf) // nacl的seed要求是32字节 var keypair = nacl.sign.keyPair.fromSeed(hashBuf) // nacl的seed要求是32字节
return { return {
hash: hashBuf.toString('hex'), hash: hashBuf.toString('hex'),
@ -390,10 +397,10 @@ class TICrypto {
* @return {Object} {pubkey, seckey,} * @return {Object} {pubkey, seckey,}
* @memberof TICrypto * @memberof TICrypto
*/ */
static secword2keypair(secword, option) { static secword2keypair(secword, { coin, pass, path, tool, hasher } = {}) {
// option.coin 币种; // coin 币种;
// option.passphase 密码,默认为空; // passphase 密码,默认为空;
// option.path==='master' 生成 HD master key不定义则默认为相应币种的第一对公私钥。 // path==='master' 生成 HD master key不定义则默认为相应币种的第一对公私钥。
// path 规范为 m/Purpose'/CoinType'/Account'/Change/Index (https://learnblockchain.cn/2018/09/28/hdwallet/), 其中 // path 规范为 m/Purpose'/CoinType'/Account'/Change/Index (https://learnblockchain.cn/2018/09/28/hdwallet/), 其中
// Purpose===44 for BIP44, // Purpose===44 for BIP44,
// CoinType===0 for BTC, 60 for ETH. (https://github.com/satoshilabs/slips/blob/master/slip-0044.md) // CoinType===0 for BTC, 60 for ETH. (https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
@ -402,30 +409,28 @@ class TICrypto {
// 据测试, Purpose和CoinType都可以任意其他值不必要如规范所示' 引号可有可无,导致的密钥不一样; // 据测试, Purpose和CoinType都可以任意其他值不必要如规范所示' 引号可有可无,导致的密钥不一样;
// Account 最大为 0x7FFFFFFF, Change/Index 最大均为 0xFFFFFFFF(=4294967295) // Account 最大为 0x7FFFFFFF, Change/Index 最大均为 0xFFFFFFFF(=4294967295)
// 但可以不断延伸下去:/xxx/xxx/xxx/xxx/... // 但可以不断延伸下去:/xxx/xxx/xxx/xxx/...
option = option || {} coin = my.COIN_LIST.indexOf(coin?.toUpperCase()) >= 0 ? coin.toUpperCase() : my.COIN
if (option.coin) option.coin = option.coin.toUpperCase()
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN
if (option.tool === 'nacl') { if (tool === 'nacl') {
// 采用自己的算法bip39算法从secword到种子hash后用 nacl.sign.keyPair.fromSeed()方法。 // 采用自己的算法bip39算法从secword到种子hash后用 nacl.sign.keyPair.fromSeed()方法。
option.hasher = my.HASHER_LIST.indexOf(option.hasher) >= 0 ? option.hasher : my.HASHER hasher = my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER
let hashBuf = crypto.createHash(option.hasher).update(this.secword2seed(secword, option.pass)).digest() let hashBuf = crypto.createHash(hasher).update(this.secword2seed(secword, pass)).digest()
let keypair = nacl.sign.keyPair.fromSeed(hashBuf) // nacl.sign.keyPair.fromSeed 要求32字节的种子而 this.secword2seed生成的是64字节种子所以要先做一次sha256 let keypair = nacl.sign.keyPair.fromSeed(hashBuf) // nacl.sign.keyPair.fromSeed 要求32字节的种子而 this.secword2seed生成的是64字节种子所以要先做一次sha256
return { return {
coin: option.coin, coin: coin,
secword: secword, secword: secword,
pubkey: Buffer.from(keypair.publicKey).toString('hex'), // 测试过 不能直接keypair.publicKey.toString('hex')不是buffer类型 pubkey: Buffer.from(keypair.publicKey).toString('hex'), // 测试过 不能直接keypair.publicKey.toString('hex')不是buffer类型
seckey: Buffer.from(keypair.secretKey).toString('hex'), // nacl.sign.keyPair.fromSeed 得到的 seckey 是64字节的不同于比特币/以太坊的32字节密钥。 seckey: Buffer.from(keypair.secretKey).toString('hex'), // nacl.sign.keyPair.fromSeed 得到的 seckey 是64字节的不同于比特币/以太坊的32字节密钥。
} }
} else { } else {
// 用 bip39 算法从 secword 到种子,再用 bip32 算法从种子到根私钥。这是比特币、以太坊的标准方式,结果一致。 // 用 bip39 算法从 secword 到种子,再用 bip32 算法从种子到根私钥。这是比特币、以太坊的标准方式,结果一致。
let hdmaster = hdkey.fromMasterSeed(Buffer.from(this.secword2seed(secword, option.pass), 'hex')) // 和 new BitcoreMnemonic(secword).toHDPrivateKey 求出的公私钥一样! let hdmaster = hdkey.fromMasterSeed(Buffer.from(this.secword2seed(secword, pass), 'hex')) // 和 new BitcoreMnemonic(secword).toHDPrivateKey 求出的公私钥一样!
// let hdmaster=new BitcoreMnemonic(secword).toHDPrivateKey(option.pass) // 和 ethers.HDNode.fromMnemonic(secword)的公私钥一样。而 ethers.HDNode.fromMnemonic(secword).derivePath("m/44'/60'/0'/0/0")的公私钥===ethers.Wallet.fromMnemonic(secword [,"m/44'/60'/0'/0/0"]) // let hdmaster=new BitcoreMnemonic(secword).toHDPrivateKey(pass) // 和 ethers.HDNode.fromMnemonic(secword)的公私钥一样。而 ethers.HDNode.fromMnemonic(secword).derivePath("m/44'/60'/0'/0/0")的公私钥===ethers.Wallet.fromMnemonic(secword [,"m/44'/60'/0'/0/0"])
let key = hdmaster let key = hdmaster
if (option.path === 'master') { if (path === 'master') {
key = hdmaster key = hdmaster
} else if (!option.path) { } else if (!path) {
switch (option.coin) { switch (coin) {
case 'BTC': case 'BTC':
key = hdmaster.derive("m/44'/0'/0'/0/0") key = hdmaster.derive("m/44'/0'/0'/0/0")
break break
@ -438,11 +443,11 @@ class TICrypto {
break break
} }
} else { } else {
// 指定了路径 option.path例如 "m/44'/0'/0'/0/6" 或 "m/0/2147483647'/1" // 指定了路径 path例如 "m/44'/0'/0'/0/6" 或 "m/0/2147483647'/1"
key = hdmaster.derive(option.path) key = hdmaster.derive(path)
} }
return { return {
coin: option.coin, coin: coin,
secword: secword, secword: secword,
seckey: key.privateKey.toString('hex'), // 或者 key.toJSON().privateKey。或者 key.privateKey.slice(2) 删除开头的'0x'如果是ethers.HDNode.fromMnemonic(secword)的结果 seckey: key.privateKey.toString('hex'), // 或者 key.toJSON().privateKey。或者 key.privateKey.slice(2) 删除开头的'0x'如果是ethers.HDNode.fromMnemonic(secword)的结果
pubkey: key.publicKey.toString('hex'), pubkey: key.publicKey.toString('hex'),
@ -493,18 +498,16 @@ class TICrypto {
* @return {Object} * @return {Object}
* @memberof TICrypto * @memberof TICrypto
*/ */
static secword2account(secword, option) { static secword2account(secword, { coin, pass, path, tool, hasher } = {}) {
// account 比 keypair 多了 address 字段。 // account 比 keypair 多了 address 字段。
option = option || {} coin = my.COIN_LIST.indexOf(coin?.toUpperCase()) >= 0 ? coin.toUpperCase() : my.COIN
if (option.coin) option.coin = option.coin.toUpperCase() let kp = this.secword2keypair(secword, { coin, pass, path, tool, hasher })
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN
let kp = this.secword2keypair(secword, option)
if (kp) { if (kp) {
if (option.coin === 'ETH') { if (coin === 'ETH') {
let uncompressedPubkey = this.decompressPubkey(kp.pubkey) let uncompressedPubkey = this.decompressPubkey(kp.pubkey)
kp.address = this.pubkey2address(uncompressedPubkey, { coin: 'ETH' }) kp.address = this.pubkey2address(uncompressedPubkey, { coin: 'ETH' })
} else { } else {
kp.address = this.pubkey2address(kp.pubkey, option) kp.address = this.pubkey2address(kp.pubkey, { coin })
} }
return kp return kp
} }
@ -520,17 +523,15 @@ class TICrypto {
* @return {String} address * @return {String} address
* @memberof TICrypto * @memberof TICrypto
*/ */
static secword2address(secword, option) { static secword2address(secword, { coin, pass, path, tool, hasher }) {
option = option || {} coin = my.COIN_LIST.indexOf(coin?.toUpperCase()) >= 0 ? coin.toUpperCase() : my.COIN
if (option.coin) option.coin = option.coin.toUpperCase() let kp = this.secword2keypair(secword, { coin, pass, path, tool, hasher })
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN
let kp = this.secword2keypair(secword, option)
if (kp) { if (kp) {
let address let address
if (option.coin === 'ETH') { if (coin === 'ETH') {
address = this.pubkey2address(this.decompressPubkey(kp.pubkey), { coin: 'ETH' }) address = this.pubkey2address(this.decompressPubkey(kp.pubkey), { coin: 'ETH' })
} else { } else {
address = this.pubkey2address(kp.pubkey, option) address = this.pubkey2address(kp.pubkey, { coin })
} }
return address return address
} }
@ -546,18 +547,16 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static seckey2pubkey(seckey, option = {}) { static seckey2pubkey(seckey, { curve, compress } = {}) {
if (option.coin) option.coin = option.coin.toUpperCase()
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN
if (this.isSeckey(seckey) && seckey.length === 64) { if (this.isSeckey(seckey) && seckey.length === 64) {
// 只能用于32字节的私钥BTC, ETH)。也就是不能用于 TIC 的私钥。 // 只能用于32字节的私钥BTC, ETH)。也就是不能用于 TIC 的私钥。
let curve = my.CURVE_LIST.indexOf(option.curve) >= 0 ? option.curve : my.CURVE // 默认为 secp256k1 curve = my.CURVE_LIST.indexOf(curve) >= 0 ? curve : my.CURVE // 默认为 secp256k1
// return new crypto.createECDH(curve).setPrivateKey(seckey,'hex').getPublicKey('hex', option.compress===false?'uncompressed':'compressed') // ecdh.getPublicKey(不加参数) 默认为 'compressed'。用 HBuilderX 2.6.4 打包成ios或安卓 app 后 setPrivateKey() 报错TypeError: null is not an object (evaluating 'this.rand.getBytes') // return new crypto.createECDH(curve).setPrivateKey(seckey,'hex').getPublicKey('hex', compress===false?'uncompressed':'compressed') // ecdh.getPublicKey(不加参数) 默认为 'compressed'。用 HBuilderX 2.6.4 打包成ios或安卓 app 后 setPrivateKey() 报错TypeError: null is not an object (evaluating 'this.rand.getBytes')
// 从 nodejs 10.0 开始,还有 crypto.ECDH.convertKey 方法,更直接。但可惜,浏览器里不存在 crypto.ECDH。 // 从 nodejs 10.0 开始,还有 crypto.ECDH.convertKey 方法,更直接。但可惜,浏览器里不存在 crypto.ECDH。
return this.buf2hex(secp256k1.publicKeyCreate(Buffer.from(seckey, 'hex'), option.compress !== false)) // 可用于浏览器。secp256k1缺省或true时输出压缩公钥false时输出非压缩公钥。 return this.buf2hex(secp256k1.publicKeyCreate(Buffer.from(seckey, 'hex'), compress !== false)) // 可用于浏览器。缺省输出压缩公钥,compress=false时输出非压缩公钥。
// 或者 bitcorelib.PublicKey.fromPrivateKey(new bitcorelib.PrivateKey(seckey)).toString('hex') // 可用于浏览器 // 或者 bitcorelib.PublicKey.fromPrivateKey(new bitcorelib.PrivateKey(seckey)).toString('hex') // 可用于浏览器
// 或者 const ecc = require('eccrypto') // 或者 const ecc = require('eccrypto')
// if (option.compress===false){ // if (compress===false){
// return ecc.getPublic(this.hex2buf(seckey)).toString('hex') // return ecc.getPublic(this.hex2buf(seckey)).toString('hex')
// }else{ // }else{
// return ecc.getPublicCompressed(this.hex2buf(seckey)).toString('hex') // return ecc.getPublicCompressed(this.hex2buf(seckey)).toString('hex')
@ -580,19 +579,17 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static seckey2address(seckey, option) { static seckey2address(seckey, { coin } = {}) {
option = option || {} coin = my.COIN_LIST.indexOf(coin?.toUpperCase()) >= 0 ? coin.toUpperCase() : my.COIN
if (option.coin) option.coin = option.coin.toUpperCase()
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN
if (this.isSeckey(seckey)) { if (this.isSeckey(seckey)) {
/** @type {*} */ /** @type {*} */
let pubkey let pubkey
if (option.coin === 'ETH') { if (coin === 'ETH') {
pubkey = this.seckey2pubkey(seckey, { compress: false }) pubkey = this.seckey2pubkey(seckey, { compress: false })
return this.pubkey2address(pubkey, option) return this.pubkey2address(pubkey, { coin })
} else { } else {
pubkey = this.seckey2pubkey(seckey, { compress: true }) pubkey = this.seckey2pubkey(seckey, { compress: true })
return this.pubkey2address(pubkey, option) return this.pubkey2address(pubkey, { coin })
} }
} }
return null return null
@ -609,8 +606,7 @@ class TICrypto {
*/ */
static pubkey2position(pubkey, { coin } = {}) { static pubkey2position(pubkey, { coin } = {}) {
// tic, btc, eth 的 position 都是 20节=40字符的。 // tic, btc, eth 的 position 都是 20节=40字符的。
if (coin) coin = coin.toUpperCase() coin = my.COIN_LIST.indexOf(coin?.toUpperCase()) >= 0 ? coin.toUpperCase() : my.COIN
coin = my.COIN_LIST.indexOf(coin) >= 0 ? coin : my.COIN
if (this.isPubkey(pubkey)) { if (this.isPubkey(pubkey)) {
if (coin === 'ETH') { if (coin === 'ETH') {
// 注意必须要用非压缩的64字节的公钥的buffer并去掉开头的 04。 // 注意必须要用非压缩的64字节的公钥的buffer并去掉开头的 04。
@ -774,11 +770,10 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static pubkey2address(pubkey, option = {}) { static pubkey2address(pubkey, { coin } = {}) {
// pubkey 应当是string类型 // pubkey 应当是string类型
if (option.coin) option.coin = option.coin.toUpperCase() coin = my.COIN_LIST.indexOf(coin?.toUpperCase()) >= 0 ? coin.toUpperCase() : my.COIN
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN return this.position2address(this.pubkey2position(pubkey, { coin }), { coin })
return this.position2address(this.pubkey2position(pubkey, option), option)
} }
/** /**
@ -847,11 +842,10 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static randomSeckey(option = {}) { static randomSeckey({ coin, tool } = {}) {
// 跳过 secword 直接产生随机密钥 // 跳过 secword 直接产生随机密钥
if (option.coin) option.coin = option.coin.toUpperCase() coin = my.COIN_LIST.indexOf(coin?.toUpperCase()) >= 0 ? coin : my.COIN
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN if (tool === 'nacl') {
if (option.tool === 'nacl') {
return crypto.randomBytes(64).toString('hex') // Buffer.from(nacl.sign.keyPair().secretKey).toString('hex') // 64字节 return crypto.randomBytes(64).toString('hex') // Buffer.from(nacl.sign.keyPair().secretKey).toString('hex') // 64字节
} else { } else {
return crypto.randomBytes(32).toString('hex') // Buffer.from(nacl.box.keyPair().secretKey).toString('hex') // 32字节 return crypto.randomBytes(32).toString('hex') // Buffer.from(nacl.box.keyPair().secretKey).toString('hex') // 32字节
@ -866,12 +860,10 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static randomKeypair(option = {}) { static randomKeypair({ tool, purpose } = {}) {
if (option.coin) option.coin = option.coin.toUpperCase()
option.coin = my.COIN_LIST.indexOf(option.coin) >= 0 ? option.coin : my.COIN
let kp let kp
if (option.tool === 'nacl') { if (tool === 'nacl') {
if (option.purpose === 'encrypt') { if (purpose === 'encrypt') {
kp = nacl.box.keyPair() kp = nacl.box.keyPair()
} else { } else {
kp = nacl.sign.keyPair() kp = nacl.sign.keyPair()
@ -898,9 +890,9 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static randomAccount(option = {}) { static randomAccount({ lang, coin, pass, path, tool, hasher } = {}) {
let secword = this.randomSecword(option.lang) let secword = this.randomSecword(lang)
return this.secword2account(secword, option) return this.secword2account(secword, { coin, pass, path, tool, hasher })
} }
/** /**
@ -984,15 +976,14 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static getMerkleHash(hashList, option = {}) { static getMerkleHash(hashList, { output, hasher } = {}) {
// merkle算法略有难度暂时用最简单的hash代替 // merkle算法略有难度暂时用最简单的hash代替
if (Array.isArray(hashList)) { if (Array.isArray(hashList)) {
let output = option.output === 'buf' ? undefined : option.output || my.OUTPUT myhasher = crypto.createHash(my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER)
let hasher = crypto.createHash(my.HASHER_LIST.indexOf(option.hasher) >= 0 ? option.hasher : my.HASHER)
for (var hash of hashList) { for (var hash of hashList) {
hasher.update(hash) myhasher.update(hash)
} }
return hasher.digest(output) return myhasher.digest(output === 'buf' ? undefined : output || my.OUTPUT)
} }
return null return null
} }
@ -1006,7 +997,7 @@ class TICrypto {
* @return {*} * @return {*}
* @memberof TICrypto * @memberof TICrypto
*/ */
static getMerkleRoot(todoHashList, option) { static getMerkleRoot(todoHashList) {
//深拷贝传入数组,防止引用对象被改变 //深拷贝传入数组,防止引用对象被改变
let hashList = [...todoHashList] let hashList = [...todoHashList]
if (!Array.isArray(hashList)) return null if (!Array.isArray(hashList)) return null