This commit is contained in:
陆柯 2022-08-17 12:22:44 +08:00
parent d54cc58c80
commit a43a43ed16

42
ticc.js
View File

@ -44,15 +44,17 @@ my.REGEXP_ALPHABET = {
b64t: /^[A-Za-z0-9\._]+$/, b64t: /^[A-Za-z0-9\._]+$/,
} }
let lm = {} let lm = {}
lm.chinese = lm.cn = lm.zh = lm.china = lm.zhcn = lm.chinese_simplified = 'chinese_simplified' lm.cn = lm.zh = lm.zhcn = lm.china = lm.chinese = lm.chinese_simplified = 'chinese_simplified'
lm.taiwanese = lm.tw = lm.zhtw = lm.chinese_traditional = 'chinese_traditional' lm.tw = lm.zhtw = lm.taiwanese = lm.chinese_traditional = 'chinese_traditional'
lm.en = lm.us = lm.uk = lm.enus = lm.enlish = 'english' lm.en = lm.us = lm.uk = lm.enus = lm.enlish = 'english'
lm.fr = lm.france = lm.frfr = lm.french = 'french' lm.fr = lm.frfr = lm.france = lm.french = 'french'
lm.it = lm.italy = lm.itit = lm.italian = 'italian' lm.it = lm.itit = lm.italy = lm.italian = 'italian'
lm.ko = lm.kr = lm.korean = lm.kokr = lm.koren = 'korean' lm.ko = lm.kr = lm.kokr = lm.korean = lm.koren = 'korean'
lm.ja = lm.jp = lm.japan = lm.jajp = lm.japanese = 'japanese' lm.ja = lm.jp = lm.jajp = lm.japan = lm.japanese = 'japanese'
lm.es = lm.eses = lm.spanish = 'spanish' lm.es = lm.eses = lm.spanish = 'spanish'
my.langMap = lm my.langMap = lm
my.langList = [lm.cn, lm.tw, lm.en, lm.fr, lm.it, lm.ko, lm.ja, lm.es]
my.LANG = 'english'
/** /**
* *
@ -122,13 +124,13 @@ class TicCrypto {
//// for bip39. 注意bip39对当前defaultWordlist之外其他语言的合法 mnemonic 也返回 false这一点不如 bitcore-mnemonic. 所以不能直接 bip39.validateMnemonic(secword) //// for bip39. 注意bip39对当前defaultWordlist之外其他语言的合法 mnemonic 也返回 false这一点不如 bitcore-mnemonic. 所以不能直接 bip39.validateMnemonic(secword)
if (typeof secword === 'string' && !/(^\s)|\s\s|(\s$)/.test(secword) && [12, 15, 18, 21, 24].includes(secword.split(/\s+/).length)) { if (typeof secword === 'string' && !/(^\s)|\s\s|(\s$)/.test(secword) && [12, 15, 18, 21, 24].includes(secword.split(/\s+/).length)) {
if (mode === 'easy') return true // easy模式不检查校验等等严格的合法性了反正 secword_to_seed 是接受一切字符串的 if (mode === 'easy') return true // easy模式不检查校验等等严格的合法性了反正 secword_to_seed 是接受一切字符串的
if (my.langMap[lang?.toLowerCase()]) { if (my.langMap[lang?.toLowerCase?.()]) {
// 指定了语言则针对该语言词库检查 // 指定了语言则针对该语言词库检查
return bip39.validateMnemonic(secword, bip39.wordlists[my.langMap[lang?.toLowerCase()]]) return bip39.validateMnemonic(secword, bip39.wordlists[my.langMap[lang.toLowerCase()]])
} else { } else {
// 未指定语言则检查所有可能语言词库 // 未指定语言则检查所有可能语言词库
for (let lang of Object.keys(bip39.wordlists)) { for (let lang of my.langList) {
return bip39.validateMnemonic(secword, bip39.wordlists[my.langMap[lang?.toLowerCase()]]) return bip39.validateMnemonic(secword, bip39.wordlists[lang])
} }
} }
} }
@ -410,10 +412,10 @@ class TicCrypto {
* @return {*} * @return {*}
* @memberof TicCrypto * @memberof TicCrypto
*/ */
static secword_to_entropy ({ secword, lang } = {}) { static secword_to_entropy ({ secword, lang = my.LANG } = {}) {
// secword could be of length 12|15|18|21|24which outputs hex of length 32|40|48|56|64. // secword could be of length 12|15|18|21|24which outputs hex of length 32|40|48|56|64.
try { try {
return bip39.mnemonicToEntropy(secword, bip39.wordlists[my.langMap[lang?.toLowerCase()] || 'english']) // results are the same for the same secword return bip39.mnemonicToEntropy(secword, bip39.wordlists[my.langMap[lang.toLowerCase()]]) // results are the same for the same secword
} catch (exception) { } catch (exception) {
// 如果助记词不合法(例如,语言不符合,长度非法,校验码不正确),会抛出异常。 // 如果助记词不合法(例如,语言不符合,长度非法,校验码不正确),会抛出异常。
return '' return ''
@ -514,7 +516,7 @@ class TicCrypto {
if (Number.isInteger(pathIndex) && 0 <= pathIndex && pathIndex <= 0x7fffffff) { if (Number.isInteger(pathIndex) && 0 <= pathIndex && pathIndex <= 0x7fffffff) {
path += `/${pathIndex}` path += `/${pathIndex}`
} }
coin = coin?.toUpperCase() coin = coin?.toUpperCase?.()
if (coin === 'BTC') { if (coin === 'BTC') {
return `m/44'/0'/${path}` return `m/44'/0'/${path}`
} else if (coin === 'ETH') { } else if (coin === 'ETH') {
@ -628,7 +630,7 @@ class TicCrypto {
* @memberof TicCrypto * @memberof TicCrypto
*/ */
static prikey_to_address ({ prikey, coin, world } = {}) { static prikey_to_address ({ prikey, coin, world } = {}) {
coin = coin?.toUpperCase() || my.COIN coin = coin?.toUpperCase?.() || my.COIN
if (this.is_prikey({ prikey })) { if (this.is_prikey({ prikey })) {
/** @type {*} */ /** @type {*} */
let pubkey let pubkey
@ -655,7 +657,7 @@ class TicCrypto {
*/ */
static pubkey_to_position ({ pubkey, coin } = {}) { static pubkey_to_position ({ pubkey, coin } = {}) {
// tic, btc, eth 的 position 都是 20节=40字符的。 // tic, btc, eth 的 position 都是 20节=40字符的。
coin = coin?.toUpperCase() || my.COIN coin = coin?.toUpperCase?.() || my.COIN
if (this.is_pubkey({ pubkey })) { if (this.is_pubkey({ pubkey })) {
if (coin === 'ETH') { if (coin === 'ETH') {
// 注意必须要用非压缩的64字节的公钥的buffer并去掉开头的 04。 // 注意必须要用非压缩的64字节的公钥的buffer并去掉开头的 04。
@ -864,17 +866,17 @@ class TicCrypto {
* @return {*} * @return {*}
* @memberof TicCrypto * @memberof TicCrypto
*/ */
static randomize_secword ({ lang, wordCount = 12 } = {}) { static randomize_secword ({ lang = my.LANG, wordCount = 12 } = {}) {
//// for BitcoreMnemonic //// for BitcoreMnemonic
// lang=lang?.toUpperCase() // lang=lang?.toUpperCase?.()
// let language = { ZHCN: 'CHINESE', ENUS: 'ENGLISH', FRFR: 'FRENCH', ITIT: 'ITALIAN', JAJP: 'JAPANESE', KOKR: 'KOREAN', ESES: 'SPANISH' }[lang] // let language = { ZHCN: 'CHINESE', ENUS: 'ENGLISH', FRFR: 'FRENCH', ITIT: 'ITALIAN', JAJP: 'JAPANESE', KOKR: 'KOREAN', ESES: 'SPANISH' }[lang]
// || (BitcoreMnemonic.Words.hasOwnProperty(lang?.toUpperCase()) ? lang?.toUpperCase() : 'ENGLISH') // || (BitcoreMnemonic.Words.hasOwnProperty(lang?.toUpperCase?.()) ? lang?.toUpperCase?.() : 'ENGLISH')
// return new BitcoreMnemonic(BitcoreMnemonic.Words[language]).phrase // return new BitcoreMnemonic(BitcoreMnemonic.Words[language]).phrase
// for bip39 // for bip39
const bitLength = { 12: 128, 15: 160, 18: 192, 21: 224, 24: 256 }[wordCount] || 128 const bitLength = { 12: 128, 15: 160, 18: 192, 21: 224, 24: 256 }[wordCount] || 128
// bip39.setDefaultWordlist(langMap[lang?.toLowerCase()] || 'english') // bip39.setDefaultWordlist(langMap[lang.toLowerCase()])
return bip39.generateMnemonic(bitLength, undefined, bip39.wordlists[my.langMap[lang?.toLowerCase()] || 'english']) // 内部使用 crypto.randomBytes 来获取随机墒 return bip39.generateMnemonic(bitLength, undefined, bip39.wordlists[my.langMap[lang.toLowerCase()]]) // 内部使用 crypto.randomBytes 来获取随机墒
} }
/** /**