发现 BigInt=require('big-integer') 可能导致和原生 BigInt 的命名冲突,改为 bigint,同时把可以用原生 BigInt 的都用 BigInt。发现 /^[b|B]/ 这种写法会识别 |,改为 /^[bB]/

This commit is contained in:
Luk 2024-10-05 15:47:17 +08:00
parent 43b9bd6898
commit 40197b2905
2 changed files with 41 additions and 19 deletions

View File

@ -6,7 +6,7 @@
"dependencies": {
"base32-decode": "^1.0.0",
"base32-encode": "^1.2.0",
"big-integer": "^1.6.51",
"big-integer": "^1.6.52",
"bip39": "^3.0.4",
"bs58check": "^2.1.2",
"eccrypto-js": "^5.4.0",

58
ticc.js
View File

@ -1,5 +1,5 @@
// const BigNumber=require('bignumber.js') // 处理整数 https://github.com/MikeMcl/bignumber.js // size: 360K
const BigInt = require('big-integer') // 处理整数 https://github.com/peterolson/BigInteger.js // size: 188K. ethers.js 24M.
// const bignum=require('bignumber.js') // 处理整数 https://github.com/MikeMcl/bignumber.js // size: 360K
const bigint = require('big-integer') // 处理整数 https://github.com/peterolson/BigInteger.js // size: 188K. ethers.js 24M. // 20241005 发现,在 node 控制台里,导入本库命名为 BigInt 后运行 BigInt(xxx) 会导致失败!因为现在已经有 JS 的新 primitive 也叫 BigInt, 不知道作为 server 运行时,怎么没有报错。改名为 bigint
const crypto = require('crypto')
const nacl = require('tweetnacl')
const bs58check = require('bs58check')
@ -536,12 +536,11 @@ class TicCrypto {
return `m/44'/60'/${path}`
} else if (coin === 'TIC') {
return `m/44'/60000'/${path}`
} else if (coin === 'MATIC') { // Polygon 测试网 (Mumbai): 80001
} else if (coin === 'MATIC' || coin === 'POL') {
// Polygon 测试网 (Mumbai): 80001
return `m/44'/137'/${path}`
} else if (/[A-Z]{3}/.test(coin)) {
return `m/44'/60${this.alpha_to_digit(coin)}'/${path}`
} else {
return ''
return `m/44'/60${this.alpha_to_digit(coin)}'/${path}`
}
}
@ -1102,7 +1101,8 @@ class TicCrypto {
// hash为64hex字符sig为128hex字符。返回用hex表达的距离。
if (this.is_signature({ sig: sig }) && this.is_hash({ hash })) {
var hashSig = this.hash_easy(sig) // 把签名也转成32字节的哈希同样长度方便比较
return (new BigInt(hash, 16) - new BigInt(hashSig, 16)).toString(16).replace(/^-/, '') // if using bignumber.js: (BigInt('0x' + hash) - BigInt('0x' + hashSig)).toString(16)
// 20241005 注意到,原来通过 require('big-integer') 进行直接减法,可能是错误的!换用原生 BigInt 配合直接减法。
return (BigInt('0x' + hash) - BigInt('0x' + hashSig)).toString(16).replace(/^-/, '') // if using bignumber.js: (bignum('0x' + hash) - bignum('0x' + hashSig)).toString(16)
}
return null
}
@ -1423,7 +1423,7 @@ class TicCrypto {
// 把 04xy 的非压缩公钥 转成 02x 或 03x 的压缩公钥
let [all, x, y] = uncompressed.toLowerCase().match(/^04(.{64})(.{64})$/)
let compressed
if (/[1,3,5,7,9,b,d,f]$/.test(y)) {
if (/[13579bdf]$/.test(y)) {
compressed = '03' + x // y为奇数=>前缀03
} else {
compressed = '02' + x // y为偶数=>前缀02
@ -1447,11 +1447,27 @@ class TicCrypto {
// https://en.bitcoin.it/wiki/Secp256k1
// 把 02x 或 03x 的压缩公钥 转成 04xy 的非压缩公钥
// Consts for secp256k1 curve. Adjust accordingly
const prime = new BigInt('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16) // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
const pIdent = new BigInt('3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c', 16) // prime.add(1).divide(4);
const prime = bigint('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16) // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
const pIdent = bigint('3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c', 16) // prime.add(1).divide(4);
var signY = new Number(compressed[1]) - 2
var x = new BigInt(compressed.substr(2), 16)
// 需要用到 big-integer 的 modPow 方法。如果直接用原生的 BigInt 会 "Maximum BigInt size exceeded"
var x = bigint(compressed.substr(2), 16)
// 需要用到 big-integer 的 modPow 方法。如果想用原生的 BigInt可以自己实现 modPow:
/*
function modPow(base, exponent, modulus) {
let result = BigInt(1);
base = BigInt(base);
while (exponent > 0n) {
if (exponent & BigInt(1)) {
result = (result * base) % modulus;
}
base = (base * base) % modulus;
exponent = exponent >> BigInt(1);
}
return result;
}
*/
var y = x.modPow(3, prime).add(7).mod(prime).modPow(pIdent, prime) // y mod p = +-(x^3 + 7)^((p+1)/4) mod p
if (y.mod(2).toJSNumber() !== signY) {
// If the parity doesn't match it's the *other* root
@ -1462,16 +1478,18 @@ class TicCrypto {
// cosh: content hash. 最核心的纯hex的内容地址没有任何额外标记。同一个内容的cosh是唯一的而cid是在cosh基础上有各种不同的编码。cid建议叫做 coid.
static cid_to_cosh ({ cid }) {
if (/^[Q|1]/.test(cid)) {
if (/^[Q1]/.test(cid)) {
return this.b58_to_hex(cid).slice(4) // 前2字节是 cid0 的字节序数标记
} else if (/^[b|B]/.test(cid)) {
} else if (/^[bB]/.test(cid)) {
return this.b32_to_hex(cid.substr(1)).slice(8) // 前4字节是 cid1 的标记
} else if (/^z/.test(cid)) {
return this.b58_to_hex(cid.substr(1)).slice(8)
} else if (/^[m|M|u|U]/.test(cid)) {
} else if (/^[mMuU]/.test(cid)) {
return Buffer.from(cid.substr(1), 'base64').toString('hex')
} else if (/^[fF]/) {
return cid.substr(9).toLowerCase()
} else if (/^9/.test(cid)) {
return new BigInt(cid.substr(1)).toString(16).slice(7) // BigInt toString(16) 后,去掉了 01551220... 的打头的 0所以只有7位需要跳过了
return BigInt(cid.slice(1)).toString(16).slice(7) // toString(16) 后,去掉了 01551220... 的打头的 0所以只有7位需要跳过了
}
}
@ -1520,7 +1538,11 @@ class TicCrypto {
} else if (cidVersion === 1) {
const fullHex = `01${multicodec[cidCodec]}${multialgo[cidAlgo]}${Number(cosh.length / 2).toString(16)}${cosh}`
let converted = ''
if (cidBase === 'b32') {
if (cidBase === 'b16') {
converted = fullHex.toLowerCase()
} else if (cidBase === 'B16') {
converted = fullHex.toUpperCase()
} else if (cidBase === 'b32') {
converted = this.hex_to_b32(fullHex).toLowerCase().replace(/=/g, '')
} else if (cidBase === 'B32') {
converted = this.hex_to_b32(fullHex).toUpperCase().replace(/=/g, '')
@ -1531,7 +1553,7 @@ class TicCrypto {
} else if (cidBase === 'b64') {
converted = Buffer.from(fullHex, 'hex').toString('base64').replace(/=/g, '')
} else if (cidBase === 'b10') {
converted = new BigInt(fullHex, 16).toString()
converted = BigInt('0x' + fullHex).toString()
}
return multibase[cidBase] + converted
}