u
This commit is contained in:
parent
741eb70245
commit
7a8ea70608
52
ticc.js
52
ticc.js
@ -208,7 +208,7 @@ class TicCrypto {
|
|||||||
* @return {String}
|
* @return {String}
|
||||||
* @memberof TicCrypto
|
* @memberof TicCrypto
|
||||||
*/
|
*/
|
||||||
static async encrypt_easy ({ data, tool = 'crypto', keytype = 'pwd', key, input, output, cipher } = {}) {
|
static async encrypt_easy ({ data, tool = 'crypto', keytype = 'pwd', key, input = my.INPUT, output = my.OUTPUT, cipher = my.CIPHER } = {}) {
|
||||||
if (tool === 'eccrypto') {
|
if (tool === 'eccrypto') {
|
||||||
// data 应当是 utf8 的字符串。key 必须是 pubkey
|
// data 应当是 utf8 的字符串。key 必须是 pubkey
|
||||||
// eccrypto 能用 Uint8Array 和 Buffer
|
// eccrypto 能用 Uint8Array 和 Buffer
|
||||||
@ -219,17 +219,17 @@ class TicCrypto {
|
|||||||
} else if (keytype === 'pwd') {
|
} else if (keytype === 'pwd') {
|
||||||
// 对称加密
|
// 对称加密
|
||||||
if (typeof key === 'string') {
|
if (typeof key === 'string') {
|
||||||
let inputEncoding = my.INPUT_LIST.includes(input) ? input : my.INPUT // 'utf8' by default, 'ascii', 'latin1' for string or ignored for Buffer/TypedArray/DataView
|
let inputEncoding = input // 'utf8' by default, 'ascii', 'latin1' for string or ignored for Buffer/TypedArray/DataView
|
||||||
let outputEncoding = output === 'buf' ? undefined : my.OUTPUT_LIST.includes(output) ? output : my.OUTPUT // 'latin1', 'base64', 'hex' by default or 'buf' to Buffer explicitly
|
let outputEncoding = output === 'buf' ? undefined : output // 'latin1', 'base64', 'hex' by default or 'buf' to Buffer explicitly
|
||||||
const iv = crypto.randomBytes(16)
|
const iv = crypto.randomBytes(16)
|
||||||
let encryptor = crypto.createCipheriv(my.CIPHER_LIST.includes(cipher) ? cipher : my.CIPHER, this.hex_to_buf(this.hash_easy(key)), iv) // cipher 和 key 的长度必须相同,例如 cipher 是 ***-192,那么 key 就必须是 192/8=24 字节 = 48 hex 的。
|
let encryptor = crypto.createCipheriv(cipher, this.hex_to_buf(this.hash_easy(key)), iv) // cipher 和 key 的长度必须相同,例如 cipher 是 ***-192,那么 key 就必须是 192/8=24 字节 = 48 hex 的。
|
||||||
if (typeof data !== 'string' && !(data instanceof Buffer) && !(data instanceof DataView)) data = JSON.stringify(data)
|
if (typeof data !== 'string' && !(data instanceof Buffer) && !(data instanceof DataView)) data = JSON.stringify(data)
|
||||||
let ciphertext = encryptor.update(data, inputEncoding, outputEncoding)
|
let ciphertext = encryptor.update(data, inputEncoding, outputEncoding)
|
||||||
ciphertext += encryptor.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
|
ciphertext += encryptor.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
|
||||||
return { iv: iv.toString('hex'), ciphertext } // 有 iv,显然每次结果不一样
|
return { iv: iv.toString('hex'), ciphertext } // 有 iv,显然每次结果不一样
|
||||||
}
|
}
|
||||||
} else if (keytype === 'seckey') {
|
} else if (keytype === 'seckey') {
|
||||||
// 尚未走通,不能使用 ticc 生成的 Elliptic curve 椭圆曲线算法公私钥,只能用 crypto.generateKeyPair('rsa') 生成的 rsa 公私钥
|
// 尚未走通,不能使用 ticc 生成的 Elliptic curve 椭圆曲线算法公私钥,只能用 crypto.generateKeyPairSync('rsa') 生成的 rsa 公私钥
|
||||||
let seckeyPEM = await new keyman.Key('oct', this.hex_to_buf(key), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
|
let seckeyPEM = await new keyman.Key('oct', this.hex_to_buf(key), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
|
||||||
return crypto.privateEncrypt(seckeyPEM, Buffer.from(data)) // 返回 Buffer。每次结果都一样。
|
return crypto.privateEncrypt(seckeyPEM, Buffer.from(data)) // 返回 Buffer。每次结果都一样。
|
||||||
} else if (keytype === 'pubkey') {
|
} else if (keytype === 'pubkey') {
|
||||||
@ -248,7 +248,7 @@ class TicCrypto {
|
|||||||
* @return {String}
|
* @return {String}
|
||||||
* @memberof TicCrypto
|
* @memberof TicCrypto
|
||||||
*/
|
*/
|
||||||
static async decrypt_easy ({ data = {}, tool = 'crypto', keytype = 'pwd', key, input, output, cipher } = {}) {
|
static async decrypt_easy ({ data = {}, tool = 'crypto', keytype = 'pwd', key, input = my.OUTPUT, output = my.OUTPUT, cipher = my.CIPHER } = {}) {
|
||||||
// data 应当是 encrypt 输出的数据类型
|
// data 应当是 encrypt 输出的数据类型
|
||||||
if (tool === 'eccrypto') {
|
if (tool === 'eccrypto') {
|
||||||
try {
|
try {
|
||||||
@ -264,13 +264,9 @@ class TicCrypto {
|
|||||||
} else if (keytype === 'pwd') {
|
} else if (keytype === 'pwd') {
|
||||||
// 对称解密
|
// 对称解密
|
||||||
if ((typeof data.ciphertext === 'string' || data.ciphertext instanceof Buffer) && typeof key === 'string') {
|
if ((typeof data.ciphertext === 'string' || data.ciphertext instanceof Buffer) && typeof key === 'string') {
|
||||||
let inputEncoding = my.OUTPUT_LIST.includes(input) ? input : my.OUTPUT // input (=output of encrypt) could be 'latin1', 'base64', 'hex' by default for string or ignored for Buffer
|
let inputEncoding = input // input (=output of encrypt) could be 'latin1', 'base64', 'hex' by default for string or ignored for Buffer
|
||||||
let outputEncoding = output === 'buf' ? undefined : my.INPUT_LIST.includes(output) ? output : my.INPUT // output (=input of encrypt) could be 'latin1', 'ascii', 'utf8' by default or 'buf' to Buffer explicitly
|
let outputEncoding = output === 'buf' ? undefined : output // output (=input of encrypt) could be 'latin1', 'ascii', 'utf8' by default or 'buf' to Buffer explicitly
|
||||||
let decryptor = crypto.createDecipheriv(
|
let decryptor = crypto.createDecipheriv(cipher, this.hex_to_buf(this.hash_easy(key)), Buffer.from(data.iv, 'hex'))
|
||||||
my.CIPHER_LIST.includes(cipher) ? cipher : my.CIPHER,
|
|
||||||
this.hex_to_buf(this.hash_easy(key)),
|
|
||||||
Buffer.from(data.iv, 'hex')
|
|
||||||
)
|
|
||||||
let decrypted = decryptor.update(data.ciphertext, inputEncoding, outputEncoding)
|
let decrypted = decryptor.update(data.ciphertext, inputEncoding, outputEncoding)
|
||||||
decrypted += decryptor.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
|
decrypted += decryptor.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
|
||||||
// 如果用户输入错误密码,deciper也能解密,无法自动判断是否正确结果。可在返回后人工判断。
|
// 如果用户输入错误密码,deciper也能解密,无法自动判断是否正确结果。可在返回后人工判断。
|
||||||
@ -297,7 +293,7 @@ class TicCrypto {
|
|||||||
* @return {String}
|
* @return {String}
|
||||||
* @memberof TicCrypto
|
* @memberof TicCrypto
|
||||||
*/
|
*/
|
||||||
static async sign_easy ({ data, seckey, tool = 'crypto', hasher }) {
|
static async sign_easy ({ data, seckey, tool = 'crypto', hasher = my.HASHER }) {
|
||||||
// data can be string or buffer or object, results are the same
|
// data can be string or buffer or object, results are the same
|
||||||
if (this.is_hashable({ data }) && this.is_seckey({ seckey })) {
|
if (this.is_hashable({ data }) && this.is_seckey({ seckey })) {
|
||||||
if (tool === 'nacl' && seckey.length === 128) {
|
if (tool === 'nacl' && seckey.length === 128) {
|
||||||
@ -312,11 +308,11 @@ class TicCrypto {
|
|||||||
} else if (seckey.length === 64) {
|
} else if (seckey.length === 64) {
|
||||||
// 纯 crypto
|
// 纯 crypto
|
||||||
let seckeyPEM = await new keyman.Key('oct', this.hex_to_buf(seckey), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
|
let seckeyPEM = await new keyman.Key('oct', this.hex_to_buf(seckey), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
|
||||||
let signer = crypto.createSign(my.HASHER_LIST.includes(hasher) ? hasher : my.HASHER) // 注意,不知为何,hasher必须含有'sha'才能完成签名,例如 sha1, sha256, sha512, sha3, RSA-SHA1, id-rsassa-pkcs1-v1_5-with-sha3-224, 其他都会报错。
|
let signer = crypto.createSign(hasher) // 注意,不知为何,hasher必须含有'sha'才能完成签名,例如 sha1, sha256, sha512, sha3, RSA-SHA1, id-rsassa-pkcs1-v1_5-with-sha3-224, 其他都会报错。
|
||||||
signer.update(this.hash_easy(data)).end()
|
signer.update(this.hash_easy(data)).end()
|
||||||
let signature = signer.sign(seckeyPEM, 'hex')
|
let signature = signer.sign(seckeyPEM, 'hex')
|
||||||
// since nodejs 12, 有了 crypto.sign 方法,但在浏览器中无效:
|
// since nodejs 12, 有了 crypto.sign 方法,但在浏览器中无效:
|
||||||
// let signature = crypto.sign(my.HASHER_LIST.includes(hasher) ? hasher : my.HASHER, Buffer.from(this.hash_easy(data)), seckeyPEM).toString('hex')
|
// let signature = crypto.sign(hasher, Buffer.from(this.hash_easy(data)), seckeyPEM).toString('hex')
|
||||||
return signature // 发现同样的输入,nodejs里每次调用会生成不同的 signature, 且长度不定(140,142,144 hex) 但都可以通过 verify。但在浏览器里调用,signature却是固定的。
|
return signature // 发现同样的输入,nodejs里每次调用会生成不同的 signature, 且长度不定(140,142,144 hex) 但都可以通过 verify。但在浏览器里调用,signature却是固定的。
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,7 +330,7 @@ class TicCrypto {
|
|||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @memberof TicCrypto
|
* @memberof TicCrypto
|
||||||
*/
|
*/
|
||||||
static async verify_easy ({ data, signature, pubkey, tool = 'crypto', hasher }) {
|
static async verify_easy ({ data, signature, pubkey, tool = 'crypto', hasher = my.HASHER }) {
|
||||||
// data could be anything, but converts to string or remains be Buffer/TypedArray/DataView
|
// data could be anything, but converts to string or remains be Buffer/TypedArray/DataView
|
||||||
if (this.is_hashable({ data }) && this.is_signature({ sig: signature }) && this.is_pubkey({ pubkey })) {
|
if (this.is_hashable({ data }) && this.is_signature({ sig: signature }) && this.is_pubkey({ pubkey })) {
|
||||||
if ('nacl' === tool && signature.length === 128) {
|
if ('nacl' === tool && signature.length === 128) {
|
||||||
@ -355,11 +351,11 @@ class TicCrypto {
|
|||||||
} else if (signature.length >= 140) {
|
} else if (signature.length >= 140) {
|
||||||
// 纯 crypto // 发现大小写不影响 crypto 验签!都能通过
|
// 纯 crypto // 发现大小写不影响 crypto 验签!都能通过
|
||||||
let pubkeyPEM = await new keyman.Key('oct', this.hex_to_buf(pubkey), { namedCurve: 'P-256K' }).export('pem') // 公钥导出的der格式为88字节。经测试,同一对压缩和非压缩公钥得出的结果一模一样。
|
let pubkeyPEM = await new keyman.Key('oct', this.hex_to_buf(pubkey), { namedCurve: 'P-256K' }).export('pem') // 公钥导出的der格式为88字节。经测试,同一对压缩和非压缩公钥得出的结果一模一样。
|
||||||
let verifier = crypto.createVerify(my.HASHER_LIST.includes(hasher) ? hasher : my.HASHER)
|
let verifier = crypto.createVerify(hasher)
|
||||||
verifier.update(this.hash_easy(data)).end() // end() 在 nodejs 12 里返回verifier自身,但在浏览器里返回 undefined,因此不能串联运行。
|
verifier.update(this.hash_easy(data)).end() // end() 在 nodejs 12 里返回verifier自身,但在浏览器里返回 undefined,因此不能串联运行。
|
||||||
let verified = verifier.verify(pubkeyPEM, signature, 'hex') // 如果给signature添加1位hex,crypto 的 verify结果也是true! 估计因为一位hex不被转成字节。但减少1位会导致false
|
let verified = verifier.verify(pubkeyPEM, signature, 'hex') // 如果给signature添加1位hex,crypto 的 verify结果也是true! 估计因为一位hex不被转成字节。但减少1位会导致false
|
||||||
// since nodejs 12, 有了 crypto.verify 方法,但在浏览器中无效:
|
// since nodejs 12, 有了 crypto.verify 方法,但在浏览器中无效:
|
||||||
// let verified = crypto.verify(my.HASHER_LIST.includes(hasher) ? hasher : my.HASHER, Buffer.from(this.hash_easy(data)), pubkeyPEM, Buffer.from(signature, 'hex'))
|
// let verified = crypto.verify(hasher, Buffer.from(this.hash_easy(data)), pubkeyPEM, Buffer.from(signature, 'hex'))
|
||||||
return verified
|
return verified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,10 +371,9 @@ class TicCrypto {
|
|||||||
* @return {Object} {pubkey, seckey, address,}
|
* @return {Object} {pubkey, seckey, address,}
|
||||||
* @memberof TicCrypto
|
* @memberof TicCrypto
|
||||||
*/
|
*/
|
||||||
static pass_to_keypair ({ pass, hasher } = {}) {
|
static pass_to_keypair ({ pass, hasher = my.HASHER } = {}) {
|
||||||
// 如果使用其他机制,例如密码、随机数,不使用secword,也可生成keypair
|
// 如果使用其他机制,例如密码、随机数,不使用secword,也可生成keypair
|
||||||
if (this.is_hashable({ data: pass })) {
|
if (this.is_hashable({ data: pass })) {
|
||||||
hasher = my.HASHER_LIST.includes(hasher) ? hasher : my.HASHER
|
|
||||||
var hashBuf = crypto
|
var hashBuf = crypto
|
||||||
.createHash(hasher)
|
.createHash(hasher)
|
||||||
.update(pass)
|
.update(pass)
|
||||||
@ -433,7 +428,7 @@ class TicCrypto {
|
|||||||
* @return {Object} {pubkey, seckey,}
|
* @return {Object} {pubkey, seckey,}
|
||||||
* @memberof TicCrypto
|
* @memberof TicCrypto
|
||||||
*/
|
*/
|
||||||
static secword_to_keypair ({ secword, coin, pass, pathRoot, pathIndex, path, tool, hasher } = {}) {
|
static secword_to_keypair ({ secword, coin, pass, pathRoot, pathIndex, path, tool, hasher = my.HASHER } = {}) {
|
||||||
// coin 币种;
|
// coin 币种;
|
||||||
// passphase 密码,默认为空;
|
// passphase 密码,默认为空;
|
||||||
// path 规范为 m/Purpose'/CoinType'/Account'/Change/Index (https://learnblockchain.cn/2018/09/28/hdwallet/), 其中
|
// path 规范为 m/Purpose'/CoinType'/Account'/Change/Index (https://learnblockchain.cn/2018/09/28/hdwallet/), 其中
|
||||||
@ -448,7 +443,6 @@ class TicCrypto {
|
|||||||
|
|
||||||
if (tool === 'nacl') {
|
if (tool === 'nacl') {
|
||||||
// 采用自己的算法:bip39算法从secword到种子,hash后用 nacl.sign.keyPair.fromSeed()方法。
|
// 采用自己的算法:bip39算法从secword到种子,hash后用 nacl.sign.keyPair.fromSeed()方法。
|
||||||
hasher = my.HASHER_LIST.includes(hasher) ? hasher : my.HASHER
|
|
||||||
let hashBuf = crypto
|
let hashBuf = crypto
|
||||||
.createHash(hasher)
|
.createHash(hasher)
|
||||||
.update(this.secword_to_seed({ secword, pass }))
|
.update(this.secword_to_seed({ secword, pass }))
|
||||||
@ -674,13 +668,13 @@ class TicCrypto {
|
|||||||
.digest('hex')
|
.digest('hex')
|
||||||
.slice(-40)
|
.slice(-40)
|
||||||
} else {
|
} else {
|
||||||
let h256 = crypto
|
let h256buf = crypto
|
||||||
.createHash('sha256')
|
.createHash('sha256')
|
||||||
.update(Buffer.from(pubkey, 'hex'))
|
.update(Buffer.from(pubkey, 'hex'))
|
||||||
.digest()
|
.digest()
|
||||||
let h160 = crypto
|
let h160 = crypto
|
||||||
.createHash('ripemd160')
|
.createHash('ripemd160')
|
||||||
.update(h256)
|
.update(h256buf)
|
||||||
.digest('hex')
|
.digest('hex')
|
||||||
return h160
|
return h160
|
||||||
}
|
}
|
||||||
@ -1024,14 +1018,14 @@ class TicCrypto {
|
|||||||
* @return {*}
|
* @return {*}
|
||||||
* @memberof TicCrypto
|
* @memberof TicCrypto
|
||||||
*/
|
*/
|
||||||
static get_merkle_hash ({ hashList, output, hasher } = {}) {
|
static get_merkle_hash ({ hashList, output = my.OUTPUT, hasher = my.HASHER } = {}) {
|
||||||
// merkle算法略有难度,暂时用最简单的hash代替
|
// merkle算法略有难度,暂时用最简单的hash代替
|
||||||
if (Array.isArray(hashList)) {
|
if (Array.isArray(hashList)) {
|
||||||
myhasher = crypto.createHash(my.HASHER_LIST.includes(hasher) ? hasher : my.HASHER)
|
const myhasher = crypto.createHash(hasher)
|
||||||
for (var hash of hashList) {
|
for (let hash of hashList) {
|
||||||
myhasher.update(hash)
|
myhasher.update(hash)
|
||||||
}
|
}
|
||||||
return myhasher.digest(output === 'buf' ? undefined : output || my.OUTPUT)
|
return myhasher.digest(output === 'buf' ? undefined : output)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user