diff --git a/README.horizontal.drawio b/README.horizontal.drawio
deleted file mode 100644
index 1af10ad..0000000
--- a/README.horizontal.drawio
+++ /dev/null
@@ -1,234 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.vertical.drawio b/README.vertical.drawio
deleted file mode 100644
index 94a727c..0000000
--- a/README.vertical.drawio
+++ /dev/null
@@ -1,230 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README_cryptoflow.drawio.png b/README_cryptoflow.drawio.png
new file mode 100644
index 0000000..493d85c
Binary files /dev/null and b/README_cryptoflow.drawio.png differ
diff --git a/test.js b/test.js
index cf6c1ab..cd689c3 100644
--- a/test.js
+++ b/test.js
@@ -16,11 +16,7 @@ function ECPointDecompress (comp) {
var x = new bigInt(comp.substring(2), 16)
// y mod p = +-(x^3 + 7)^((p+1)/4) mod p
console.log('ECP x=', x.toString(), ' = ', x.toString(16))
- var y = x
- .modPow(3, prime)
- .add(7)
- .mod(prime)
- .modPow(pIdent, prime)
+ var y = x.modPow(3, prime).add(7).mod(prime).modPow(pIdent, prime)
// If the parity doesn't match it's the *other* root
console.log('ECP y=', y.toString(), ' = ', y.toString(16))
if (y.mod(2).toJSNumber() !== signY) {
@@ -40,32 +36,17 @@ BigNumber = require('bignumber.js')
function uncompressPubkey (comp) {
// Consts for P256 curve. Adjust accordingly
const prime = new BigNumber('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16).integerValue(),
- pIdent = prime
- .plus(1)
- .idiv(4)
- .integerValue()
+ pIdent = prime.plus(1).idiv(4).integerValue()
console.log('pIdent=', pIdent.toString(), ' = ', pIdent.toString(16))
var signY = new Number(comp[1]) - 2
var x = new BigNumber(comp.substring(2), 16).integerValue()
console.log('x=', x.toString(), ' = ', x.toString(16))
// y^2 = x^3 - 3x + b
- var y = x
- .pow(3)
- .mod(prime)
- .plus(7)
- .mod(prime)
- .pow(pIdent)
- .mod(prime)
- .integerValue()
+ var y = x.pow(3).mod(prime).plus(7).mod(prime).pow(pIdent).mod(prime).integerValue()
console.log('y=', y.toString(), ' = ', y.toString(16))
// If the parity doesn't match it's the *other* root
- if (
- y
- .mod(2)
- .integerValue()
- .toNumber() !== signY
- ) {
+ if (y.mod(2).integerValue().toNumber() !== signY) {
// y = prime - y
y = prime.minus(y).integerValue()
}
@@ -129,10 +110,7 @@ crypto.createCipheriv('aes-256-cfb', Buffer.from(acc.prikey, 'hex'), Buffer.allo
////////////////////// crypto + PEM
toPEM = function (kp) {
- let pubkey = crypto
- .createECDH('secp256k1')
- .setPrivateKey(kp.prikey, 'hex')
- .getPublicKey('hex', 'compressed')
+ let pubkey = crypto.createECDH('secp256k1').setPrivateKey(kp.prikey, 'hex').getPublicKey('hex', 'compressed')
console.log('ECDH created publickey = ', pubkey)
let mykey = '308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420' + kp.prikey + 'a144034200' + pubkey
console.log(mykey)
diff --git a/ticc.js b/ticc.js
index 9b0414e..ee8e1dd 100644
--- a/ticc.js
+++ b/ticc.js
@@ -976,6 +976,17 @@ class TicCrypto {
return text
}
+ static randomize_hex ({ length = 64 } = {}) {
+ // 长度为 length 的随机 hex 字符串。注意 randomBytes 在一些环境里可能不存在,例如在 HBuilderX 的内置浏览器里。
+ if (crypto.randomBytes) {
+ return crypto
+ .randomBytes(Math.ceil(length / 2))
+ .toString('hex')
+ .slice(0, length)
+ }
+ return this.randomize_string({ length, alphabet: '0123456789abcdef' })
+ }
+
/**
* 生成随机的数字
*
@@ -1275,7 +1286,7 @@ class TicCrypto {
try {
return bs58check.encode(Buffer.from(hex, 'hex'))
} catch (exception) {
- return null
+ return ''
}
}
@@ -1283,7 +1294,7 @@ class TicCrypto {
try {
return bs58.encode(Buffer.from(hex, 'hex'))
} catch (exception) {
- return null
+ return ''
}
}
@@ -1299,7 +1310,7 @@ class TicCrypto {
try {
return bs58check.decode(box).toString('hex')
} catch (exception) {
- return null
+ return ''
}
}
@@ -1307,7 +1318,7 @@ class TicCrypto {
try {
return bs58.decode(box).toString('hex')
} catch (exception) {
- return null
+ return ''
}
}
@@ -1336,10 +1347,10 @@ class TicCrypto {
* @memberof TicCrypto
*/
static hex_to_b64t (hex) {
- if (/^[0-9a-fA-F]+$/.test(hex)) {
+ if (my.REGEXP_ALPHABET.hex.test(hex)) {
return this.b64_to_b64t(Buffer.from(hex, 'hex').toString('base64'))
}
- return null
+ return ''
}
/**
@@ -1354,33 +1365,33 @@ class TicCrypto {
if (/^[0-9a-zA-Z\._]+$/.test(b64t)) {
return Buffer.from(this.b64t_to_b64(b64t), 'base64').toString('hex')
}
- return null
+ return ''
}
// https://en.wikipedia.org/wiki/Base32
static hex_to_b32 (hex) {
- if (/^[0-9a-fA-F]+$/.test(hex)) {
+ if (my.REGEXP_ALPHABET.hex.test(hex)) {
return base32encode(Buffer.from(hex, 'hex'), 'RFC4648')
}
- return null
+ return ''
}
static b32_to_hex (b32) {
- if (/^[A-Za-z2-7=]+$/.test(b32)) {
+ if (my.REGEXP_ALPHABET.b32.test(b32)) {
return Buffer.from(base32decode(b32.toUpperCase(), 'RFC4648')).toString('hex')
}
- return null
+ return ''
}
static hex_to_b32h (hex) {
- if (/^[0-9a-fA-F]+$/.test(hex)) {
+ if (my.REGEXP_ALPHABET.hex.test(hex)) {
return base32encode(Buffer.from(hex, 'hex'), 'RFC4648-HEX')
}
- return null
+ return ''
}
static b32h_to_hex (b32h) {
- if (/^[0-9A-Va-v=]+$/.test(b32h)) {
+ if (my.REGEXP_ALPHABET.b32h.test(b32h)) {
return Buffer.from(base32decode(b32.toUpperCase(), 'RFC4648-HEX')).toString('hex')
}
- return null
+ return ''
}
/**
@@ -1405,7 +1416,7 @@ class TicCrypto {
}
return result
}
- return null
+ return ''
}
/**
@@ -1430,7 +1441,7 @@ class TicCrypto {
if (this.decompress_pubkey(compressed) === uncompressed) {
return compressed
}
- return null // 非压缩公钥有错误。
+ return '' // 非压缩公钥有错误。
}
/**
@@ -1562,29 +1573,62 @@ class TicCrypto {
ripemd160: '1053',
md5: 'd5',
}
- if (cidVersion === 0) {
- return this.hex_to_b58(`${multialgo[cidAlgo]}${Number(cosh.length / 2).toString(16)}${cosh}`)
- } else if (cidVersion === 1) {
- const fullHex = `01${multicodec[cidCodec]}${multialgo[cidAlgo]}${Number(cosh.length / 2).toString(16)}${cosh}`
- let converted = ''
- 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, '')
- } else if (cidBase === 'b58') {
- converted = this.hex_to_b58(fullHex)
- } else if (cidBase === 'b64p') {
- converted = Buffer.from(fullHex, 'hex').toString('base64')
- } else if (cidBase === 'b64') {
- converted = Buffer.from(fullHex, 'hex').toString('base64').replace(/=/g, '')
- } else if (cidBase === 'b10') {
- converted = BigInt('0x' + fullHex).toString()
+ try {
+ if (cidVersion === 0) {
+ return this.hex_to_b58(`${multialgo[cidAlgo]}${Number(cosh.length / 2).toString(16)}${cosh}`)
+ } else if (cidVersion === 1) {
+ const fullHex = `01${multicodec[cidCodec]}${multialgo[cidAlgo]}${Number(cosh.length / 2).toString(16)}${cosh}`
+ let converted = ''
+ 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, '')
+ } else if (cidBase === 'b58') {
+ converted = this.hex_to_b58(fullHex)
+ } else if (cidBase === 'b64p') {
+ converted = Buffer.from(fullHex, 'hex').toString('base64')
+ } else if (cidBase === 'b64') {
+ converted = Buffer.from(fullHex, 'hex').toString('base64').replace(/=/g, '')
+ } else if (cidBase === 'b10') {
+ converted = BigInt('0x' + fullHex).toString()
+ }
+ if (converted) {
+ return multibase[cidBase] + converted
+ } else {
+ return ''
+ }
}
- return multibase[cidBase] + converted
+ } catch {
+ return ''
+ }
+ }
+
+ static convert_pexid (key) {
+ key = key.toLowerCase()
+ let pextokenCid, pextokenCosh, nftToid
+ if (key.length < 64 && /^bafkrei/.test(key)) {
+ pextokenCid = key
+ pextokenCosh = this.cid_to_cosh({ cid: pextokenCid })
+ nftToid = BigInt('0x' + pextokenCosh).toString()
+ } else if (key.length > 64 && /^\d+$/.test(key)) {
+ nftToid = key
+ pextokenCosh = BigInt(nftToid).toString(16)
+ pextokenCid = this.cosh_to_cid({ cosh: pextokenCosh })
+ } else if (/^[0-9a-f]{64}$/.test(key)) {
+ pextokenCosh = key
+ pextokenCid = this.cosh_to_cid({ cosh: pextokenCosh })
+ nftToid = BigInt('0x' + pextokenCosh).toString()
+ }
+ const tokenURI = 'https://ipfs.tic.cc/ipfs/f01551220' + pextokenCosh
+ return {
+ pextokenCid,
+ pextokenCosh,
+ nftToid,
+ tokenURI,
}
}
}