From 40197b290587c2cf37c2894d016504e1119a9faf Mon Sep 17 00:00:00 2001 From: Luk Date: Sat, 5 Oct 2024 15:47:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E7=8E=B0=20BigInt=3Drequire('big-inte?= =?UTF-8?q?ger')=20=E5=8F=AF=E8=83=BD=E5=AF=BC=E8=87=B4=E5=92=8C=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=20BigInt=20=E7=9A=84=E5=91=BD=E5=90=8D=E5=86=B2?= =?UTF-8?q?=E7=AA=81=EF=BC=8C=E6=94=B9=E4=B8=BA=20bigint=EF=BC=8C=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E6=8A=8A=E5=8F=AF=E4=BB=A5=E7=94=A8=E5=8E=9F=E7=94=9F?= =?UTF-8?q?=20BigInt=20=E7=9A=84=E9=83=BD=E7=94=A8=20BigInt=E3=80=82?= =?UTF-8?q?=E5=8F=91=E7=8E=B0=20/^[b|B]/=20=E8=BF=99=E7=A7=8D=E5=86=99?= =?UTF-8?q?=E6=B3=95=E4=BC=9A=E8=AF=86=E5=88=AB=20|=EF=BC=8C=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=20/^[bB]/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- ticc.js | 58 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 3190782..12f2774 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/ticc.js b/ticc.js index 5e45cf2..417a5be 100644 --- a/ticc.js +++ b/ticc.js @@ -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 }