在 secword2seed 和 secword2keypair 里 放松对 isSecword 的检查,因为isSecword在安卓和安卓微信里不成功!
This commit is contained in:
parent
7e1d2ef6e1
commit
e96b61ed0d
83
index.js
83
index.js
@ -242,44 +242,42 @@ module.exports = {
|
|||||||
// 据测试, Purpose和CoinType都可以任意其他值,不必要如规范所示;' 引号可有可无,导致的密钥不一样;
|
// 据测试, Purpose和CoinType都可以任意其他值,不必要如规范所示;' 引号可有可无,导致的密钥不一样;
|
||||||
// Account 最大为 0x7FFFFFFF, Change/Index 最大均为 0xFFFFFFFF(=4294967295)
|
// Account 最大为 0x7FFFFFFF, Change/Index 最大均为 0xFFFFFFFF(=4294967295)
|
||||||
// 但可以不断延伸下去:/xxx/xxx/xxx/xxx/...
|
// 但可以不断延伸下去:/xxx/xxx/xxx/xxx/...
|
||||||
if (this.isSecword(secword)){
|
option=option||{}
|
||||||
option=option||{}
|
option.coin=my.COIN_LIST.indexOf(option.coin)>=0?option.coin:my.COIN
|
||||||
option.coin=my.COIN_LIST.indexOf(option.coin)>=0?option.coin:my.COIN
|
|
||||||
|
|
||||||
if(option.tool==='nacl') {
|
if(option.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
|
option.hasher=my.HASHER_LIST.indexOf(option.hasher)>=0?option.hasher:my.HASHER
|
||||||
let hashBuf=crypto.createHash(option.hasher).update(this.secword2seed(secword, option.pass)).digest()
|
let hashBuf=crypto.createHash(option.hasher).update(this.secword2seed(secword, option.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: option.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, option.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(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 key=hdmaster
|
let key=hdmaster
|
||||||
if (option.path==='master'){
|
if (option.path==='master'){
|
||||||
key=hdmaster
|
key=hdmaster
|
||||||
}else if (!option.path) {
|
}else if (!option.path) {
|
||||||
switch(option.coin){
|
switch(option.coin){
|
||||||
case 'BTC': key=hdmaster.derive("m/44'/0'/0'/0/0"); break
|
case 'BTC': key=hdmaster.derive("m/44'/0'/0'/0/0"); break
|
||||||
case 'ETH': key=hdmaster.derive("m/44'/60'/0'/0/0"); break
|
case 'ETH': key=hdmaster.derive("m/44'/60'/0'/0/0"); break
|
||||||
case 'TIC': key=hdmaster.derive("m/44'/66'/0'/0/0"); break
|
case 'TIC': key=hdmaster.derive("m/44'/66'/0'/0/0"); break
|
||||||
default: key=hdmaster.derive("m/44'/99'/0'/0/0"); break
|
default: key=hdmaster.derive("m/44'/99'/0'/0/0"); break
|
||||||
}
|
|
||||||
}else { // 指定了路径 option.path,例如 "m/44'/0'/0'/0/6" 或 "m/0/2147483647'/1"
|
|
||||||
key=hdmaster.derive(option.path)
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
coin: option.coin,
|
|
||||||
secword: secword,
|
|
||||||
seckey: key.privateKey.toString('hex'), // 或者 key.toJSON().privateKey。或者 key.privateKey.slice(2) 删除开头的'0x'如果是ethers.HDNode.fromMnemonic(secword)的结果
|
|
||||||
pubkey: key.publicKey.toString('hex')
|
|
||||||
}
|
}
|
||||||
|
}else { // 指定了路径 option.path,例如 "m/44'/0'/0'/0/6" 或 "m/0/2147483647'/1"
|
||||||
|
key=hdmaster.derive(option.path)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
coin: option.coin,
|
||||||
|
secword: secword,
|
||||||
|
seckey: key.privateKey.toString('hex'), // 或者 key.toJSON().privateKey。或者 key.privateKey.slice(2) 删除开头的'0x'如果是ethers.HDNode.fromMnemonic(secword)的结果
|
||||||
|
pubkey: key.publicKey.toString('hex')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@ -322,9 +320,9 @@ module.exports = {
|
|||||||
option.coin=my.COIN_LIST.indexOf(option.coin)>=0?option.coin:my.COIN
|
option.coin=my.COIN_LIST.indexOf(option.coin)>=0?option.coin:my.COIN
|
||||||
if (this.isSeckey(seckey) && seckey.length===64){ // 只能用于32字节的私钥(BTC, ETH)。也就是不能用于 TIC 的私钥。
|
if (this.isSeckey(seckey) && seckey.length===64){ // 只能用于32字节的私钥(BTC, ETH)。也就是不能用于 TIC 的私钥。
|
||||||
let curve = my.CURVE_LIST.indexOf(option.curve)>=0?option.curve:my.CURVE // 默认为 secp256k1
|
let curve = my.CURVE_LIST.indexOf(option.curve)>=0?option.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 打包成 app 后 setPrivateKey() 报错:TypeError: null is not an object (evaluating 'this.rand.getBytes')
|
// 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')
|
||||||
// 从 nodejs 10.0 开始,还有 crypto.ECDH.convertKey 方法,更直接。但可惜,浏览器里不存在 crypto.ECDH。
|
// 从 nodejs 10.0 开始,还有 crypto.ECDH.convertKey 方法,更直接。但可惜,浏览器里不存在 crypto.ECDH。
|
||||||
return this.buf2hex(require('secp256k1').publicKeyCreate(Buffer.from(seckey, 'hex'), option.compress!==false)) // 可用于浏览器。secp256k1缺省或true时输出压缩公钥,false时输出非压缩公钥。
|
return this.buf2hex(secp256k1.publicKeyCreate(Buffer.from(seckey, 'hex'), option.compress!==false)) // 可用于浏览器。secp256k1缺省或true时输出压缩公钥,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 (option.compress===false){
|
||||||
@ -450,7 +448,8 @@ module.exports = {
|
|||||||
let b64 = address.replace('-', '+').replace('_', '/')
|
let b64 = address.replace('-', '+').replace('_', '/')
|
||||||
let hex = Buffer.from(b64, 'base64').toString('hex')
|
let hex = Buffer.from(b64, 'base64').toString('hex')
|
||||||
let [all, prefix, position, checksum] = hex.match(/^([\da-fA-F]{2})([\da-fA-F]{40})([\da-fA-F]{6})$/) // 内容合法
|
let [all, prefix, position, checksum] = hex.match(/^([\da-fA-F]{2})([\da-fA-F]{40})([\da-fA-F]{6})$/) // 内容合法
|
||||||
return this.hash(this.hash(prefix+position)).slice(0,6) === checksum // [todo] 校验码里要不要包含 prefix?
|
if (this.hash(this.hash(prefix+position)).slice(0,6) === checksum) // [todo] 校验码里要不要包含 prefix?
|
||||||
|
return 'TIC'
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -460,12 +459,8 @@ module.exports = {
|
|||||||
return this.position2address(this.pubkey2position(pubkey, option), option)
|
return this.position2address(this.pubkey2position(pubkey, option), option)
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
secword2seed(secword, pass) { // 遵循bip39的算法。和 ether.HDNode.mnemonic2Seed 结果一样,是64字节的种子。
|
secword2seed(secword, pass) { // 遵循bip39的算法。和 ether.HDNode.mnemonic2Seed 结果一样,是64字节的种子。其实
|
||||||
if (this.isSecword(secword)) { // bip39.validateMnemonic(secword)) {
|
return bip39.mnemonicToSeedSync(secword, pass).toString('hex') // 结果一致于 new BitcoreMnemonic(secword).toSeed(pass).toString('hex') 或 ethers.HDNode.mnemonic2Seed(secword)。其实,bip39.mnemonicToSeedSync 也接受不合法的 secword,只要是个string就行。
|
||||||
return bip39.mnemonicToSeedSync(secword, pass).toString('hex') // 结果一致于 new BitcoreMnemonic(secword).toSeed(pass).toString('hex') 或 ethers.HDNode.mnemonic2Seed(secword)
|
|
||||||
// return new BitcoreMnemonic(secword).toSeed(pass).toString('hex')
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
randomSecword(lang='english'){ // accepts case-insensitive lang, such as 'chinese, cn, tw, en'
|
randomSecword(lang='english'){ // accepts case-insensitive lang, such as 'chinese, cn, tw, en'
|
||||||
|
Loading…
Reference in New Issue
Block a user