添加 cid 转换函数
This commit is contained in:
parent
447a3eb442
commit
74694866bc
125
index.js
125
index.js
@ -31,6 +31,17 @@ my.INPUT = 'utf8' // 默认的加密方法的明文格式。utf8 能够兼容 la
|
||||
my.INPUT_LIST = ['utf8', 'ascii', 'latin1'] // ignored for Buffer/TypedArray/DataView
|
||||
my.COIN = 'TIC' // 默认的币种
|
||||
my.COIN_LIST = ['TIC', 'EXT', 'BTC', 'ETH']
|
||||
my.REGEXP_ALPHABET = {
|
||||
hex: /^[0-9a-fA-F]+$/,
|
||||
b32: /^[A-Za-z2-7=]+$/,
|
||||
b32h: /^[0-9A-Va-v=]+$/,
|
||||
b36: /^[0-9A-Z-a-z]+$/,
|
||||
b58: /^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/,
|
||||
b62: /^[A-Za-z0-9]+$/,
|
||||
b64: /^[A-Za-z0-9\+\/=]+$/,
|
||||
b64u: /^[A-Za-z0-9\-_]+$/,
|
||||
b64t: /^[A-Za-z0-9\._]+$/,
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@ -164,7 +175,10 @@ class TICrypto {
|
||||
if (salt && typeof salt === 'string') data = data + this.hash(salt)
|
||||
let inputEncoding = input // my.INPUT_LIST.indexOf(input)>=0?input:my.INPUT // 'utf8', 'ascii' or 'latin1' for string data, default to utf8 if not specified; ignored for Buffer, TypedArray, or DataView.
|
||||
let outputEncoding = output === 'buf' ? undefined : output // (my.OUTPUT_LIST.indexOf(output)>=0?output:my.OUTPUT) // output: 留空=》默认输出hex格式;或者手动指定 'buf', hex', 'latin1' or 'base64'
|
||||
return crypto.createHash(hasher).update(data, inputEncoding).digest(outputEncoding)
|
||||
return crypto
|
||||
.createHash(hasher)
|
||||
.update(data, inputEncoding)
|
||||
.digest(outputEncoding)
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -349,7 +363,10 @@ class TICrypto {
|
||||
// 如果使用其他机制,例如密码、随机数,不使用secword,也可生成keypair
|
||||
if (this.isHashable(pass)) {
|
||||
hasher = my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER
|
||||
var hashBuf = crypto.createHash(hasher).update(pass).digest()
|
||||
var hashBuf = crypto
|
||||
.createHash(hasher)
|
||||
.update(pass)
|
||||
.digest()
|
||||
var keypair = nacl.sign.keyPair.fromSeed(hashBuf) // nacl的seed要求是32字节
|
||||
return {
|
||||
hash: hashBuf.toString('hex'),
|
||||
@ -412,7 +429,10 @@ class TICrypto {
|
||||
if (tool === 'nacl') {
|
||||
// 采用自己的算法:bip39算法从secword到种子,hash后用 nacl.sign.keyPair.fromSeed()方法。
|
||||
hasher = my.HASHER_LIST.indexOf(hasher) >= 0 ? hasher : my.HASHER
|
||||
let hashBuf = crypto.createHash(hasher).update(this.secword2seed(secword, pass)).digest()
|
||||
let hashBuf = crypto
|
||||
.createHash(hasher)
|
||||
.update(this.secword2seed(secword, pass))
|
||||
.digest()
|
||||
let keypair = nacl.sign.keyPair.fromSeed(hashBuf) // nacl.sign.keyPair.fromSeed 要求32字节的种子,而 this.secword2seed生成的是64字节种子,所以要先做一次sha256
|
||||
return {
|
||||
coin: coin,
|
||||
@ -622,8 +642,14 @@ class TICrypto {
|
||||
.digest('hex')
|
||||
.slice(-40)
|
||||
} else {
|
||||
let h256 = crypto.createHash('sha256').update(Buffer.from(pubkey, 'hex')).digest()
|
||||
let h160 = crypto.createHash('ripemd160').update(h256).digest('hex')
|
||||
let h256 = crypto
|
||||
.createHash('sha256')
|
||||
.update(Buffer.from(pubkey, 'hex'))
|
||||
.digest()
|
||||
let h160 = crypto
|
||||
.createHash('ripemd160')
|
||||
.update(h256)
|
||||
.digest('hex')
|
||||
return h160
|
||||
}
|
||||
}
|
||||
@ -647,7 +673,9 @@ class TICrypto {
|
||||
if (coin === 'ETH') {
|
||||
// 对以太坊,按照 EIP55,把纯位置转换为大小写敏感能自我验证的hex地址。仍然为20节=40符。
|
||||
position = position.toLowerCase().replace('0x', '')
|
||||
let hash = keccak('keccak256').update(position).digest('hex')
|
||||
let hash = keccak('keccak256')
|
||||
.update(position)
|
||||
.digest('hex')
|
||||
address = '0x'
|
||||
for (var i = 0; i < position.length; i++) {
|
||||
if (parseInt(hash[i], 16) >= 8) {
|
||||
@ -720,15 +748,18 @@ class TICrypto {
|
||||
* 地址和PubKeyHash(即position)之间能互相转化
|
||||
*/
|
||||
static address2position () {
|
||||
if (/^0x[\da-fA-F]{40}$/.test(address)) { // ETH
|
||||
if (/^0x[\da-fA-F]{40}$/.test(address)) {
|
||||
// ETH
|
||||
// todo: 如果是大小写敏感的,进行有效性验证
|
||||
return address.toLowerCase()
|
||||
} else if (/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{26,34}$/.test(address)) { // BTC
|
||||
} else if (/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{26,34}$/.test(address)) {
|
||||
// BTC
|
||||
let hex = this.b58c_to_hex(address)
|
||||
if (hex) {
|
||||
return hex.slice(2) // 去除网络前缀
|
||||
}
|
||||
} else if (/^[Tt][0-9a-zA-Z\._]{31}$/.test(address)) { // TIC
|
||||
} else if (/^[Tt][0-9a-zA-Z\._]{31}$/.test(address)) {
|
||||
// TIC
|
||||
// 格式合法
|
||||
let hex = this.b64t_to_hex(address)
|
||||
let [all, prefix, position, checksum] = hex.match(/^([\da-fA-F]{2})([\da-fA-F]{40})([\da-fA-F]{6})$/)
|
||||
@ -1045,7 +1076,10 @@ class TICrypto {
|
||||
// hash为64hex字符,sig为128hex字符。返回用hex表达的距离。
|
||||
if (this.isSignature(sig) && this.isHash(hash)) {
|
||||
var hashSig = this.hash(sig) // 把签名也转成32字节的哈希,同样长度方便比较
|
||||
return new BigInt(hash, 16).subtract(new BigInt(hashSig, 16)).abs().toString(16)
|
||||
return new BigInt(hash, 16)
|
||||
.subtract(new BigInt(hashSig, 16))
|
||||
.abs()
|
||||
.toString(16)
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -1264,7 +1298,10 @@ class TICrypto {
|
||||
* @returns
|
||||
*/
|
||||
static b64_to_b64t (b64 = '') {
|
||||
return b64.replace(/\+/g, '.').replace(/\//g, '_').replace(/=/g, '')
|
||||
return b64
|
||||
.replace(/\+/g, '.')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=/g, '')
|
||||
}
|
||||
|
||||
static b64t_to_b64 (b64t = '') {
|
||||
@ -1338,7 +1375,9 @@ class TICrypto {
|
||||
static hex_to_eip55 (hex) {
|
||||
if (/^(0x)?[\da-fA-F]+$/.test(hex)) {
|
||||
hex = hex.toLowerCase().replace('0x', '')
|
||||
let hash = keccak('keccak256').update(hex).digest('hex')
|
||||
let hash = keccak('keccak256')
|
||||
.update(hex)
|
||||
.digest('hex')
|
||||
let result = ''
|
||||
for (var i = 0; i < hex.length; i++) {
|
||||
if (parseInt(hash[i], 16) >= 8) {
|
||||
@ -1394,13 +1433,73 @@ class TICrypto {
|
||||
const pIdent = new BigInt('3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c', 16) // prime.add(1).divide(4);
|
||||
var signY = new Number(compressed[1]) - 2
|
||||
var x = new BigInt(compressed.substr(2), 16)
|
||||
var y = x.modPow(3, prime).add(7).mod(prime).modPow(pIdent, prime) // y mod p = +-(x^3 + 7)^((p+1)/4) mod p
|
||||
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
|
||||
y = prime.subtract(y) // y = prime - y
|
||||
}
|
||||
return '04' + this.padStart(x.toString(16), 64, '0') + this.padStart(y.toString(16), 64, '0')
|
||||
}
|
||||
|
||||
static cid_to_cosh ({ cid }) {
|
||||
if (/^[Q|1]/.test(cid)) {
|
||||
return this.b58_to_hex(cid).slice(4)
|
||||
} else if (/^b/.test(cid)) {
|
||||
return this.b32_to_hex(cid.substr(1)).slice(8)
|
||||
} else if (/^z/.test(cid)) {
|
||||
return this.b58_to_hex(cid.substr(1)).slice(8)
|
||||
}
|
||||
}
|
||||
|
||||
static cosh_to_cid ({ cosh, cidBase = 'b32', cidVersion = 1, cidCodec = 'raw', cidAlgo = 'sha256' }) {
|
||||
const multibase = {
|
||||
identity: 0x00,
|
||||
b2: '0',
|
||||
b8: '7',
|
||||
b10: '9',
|
||||
b16: 'f',
|
||||
B16: 'F',
|
||||
b32: 'b',
|
||||
B32: 'B',
|
||||
b32h: 'v',
|
||||
B32h: 'V',
|
||||
b36: 'k',
|
||||
b64: 'm',
|
||||
b64p: 'M',
|
||||
b64u: 'u',
|
||||
b64up: 'U',
|
||||
b58: 'z',
|
||||
}
|
||||
const multicodec = {
|
||||
dagpb: '70',
|
||||
p2pkey: '72',
|
||||
raw: '55'
|
||||
}
|
||||
const multialgo = {
|
||||
identify: '00',
|
||||
sha256: '12'
|
||||
}
|
||||
if (cidVersion === 0) {
|
||||
return this.hex_to_b58(`${multialgo[cidAlgo]}${Number(cosh.length/2).toString(16)}${cosh}`)
|
||||
}
|
||||
if (cidVersion === 1) {
|
||||
let fullHex = `01${multicodec[cidCodec]}${multialgo[cidAlgo]}${Number(cosh.length/2).toString(16)}${cosh}`
|
||||
if (cidBase==='b32') {
|
||||
return multibase[cidBase] + this.hex_to_b32(fullHex).toLowerCase().replace(/=/g,'')
|
||||
}else if (cidBase==='b58') {
|
||||
return multibase[cidBase] + this.hex_to_b58(fullHex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static string_to_raw_cid (str) {
|
||||
return this.cosh_to_cid({ cosh: this.hash(str), cidVersion:1, cidCodec:'raw' })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 必须单独写 module.exports,不要和类定义写在一起,否则会导致 jsdoc 解析不到类内文档。
|
||||
|
Loading…
Reference in New Issue
Block a user