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, } } }