把 eccrypto 换成 eccrypto-js

This commit is contained in:
陆柯 2021-05-07 16:29:20 +08:00
parent 43b913c4b4
commit 00287a0944
3 changed files with 50 additions and 38 deletions

Binary file not shown.

View File

@ -5,7 +5,7 @@ const nacl = require('tweetnacl')
const bs58check = require('bs58check')
const uuid = require('uuid')
const keccak = require('keccak')
const eccrypto = require('eccrypto') // 用于加解密。不知道怎么用 crypto 本身的加解密。
const eccrypto = require('eccrypto-js') // 用于加解密。eccrypto 在 windows 上和 openssl 的版本兼容性有点麻烦,所以换用 eccrypto-js
const keyman = require('js-crypto-key-utils') // 转换原始密钥和 PER/DER 格式。
// const BitcoreMnemonic = require('bitcore-mnemonic') // https://bitcore.io/api/mnemonic/ https://github.com/bitpay/bitcore-mnemonic // 打包成 app 里常有问题,试图访问 window 变量,无法生成 secword
const bip39 = require('bip39') // https://github.com/bitcoinjs/bip39 // 有更多语言,但不方便选择语言,也不能使用 pass
@ -176,27 +176,32 @@ class TICrypto {
* @return {String}
* @memberof TICrypto
*/
static async encrypt(data, { tool, keytype, key, input, output, cipher } = {}) {
if (keytype === 'pwd') {
static async encrypt(data, { keytype = 'pwd', key, input, output, cipher } = {}) {
if (tool === 'eccrypto') {
// data 应当是 utf8 的字符串。key 必须是 pubkey
// eccrypto 能用 Uint8Array 和 Buffer
// eccrypto-js 只能用 Buffer
// 在浏览器里 https://github.com/bitchan/eccrypto 库报错,即使用了 Uint8Array: Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'
let cipherobject = await eccrypto.encrypt(Buffer.from(this.hex2buf(key)), data) // 对 eccrypto 库,使用
return cipherobject // 返回一个复杂的结构。对同样的key和data每次返回的结果不一样
} else if (keytype === 'pwd') {
if (typeof key === 'string') {
let inputEncoding = my.INPUT_LIST.indexOf(input) >= 0 ? input : my.INPUT // 'utf8' by default, 'ascii', 'latin1' for string or ignored for Buffer/TypedArray/DataView
let outputEncoding = output === 'buf' ? undefined : my.OUTPUT_LIST.indexOf(output) >= 0 ? output : my.OUTPUT // 'latin1', 'base64', 'hex' by default or 'buf' to Buffer explicitly
let ciph = crypto.createCipher(my.CIPHER_LIST.indexOf(cipher) >= 0 ? cipher : my.CIPHER, this.hash(key))
const iv = crypto.randomBytes(16)
let ciph = crypto.createCipheriv(my.CIPHER_LIST.indexOf(cipher) >= 0 ? cipher : my.CIPHER, this.hex2buf(this.hash(key)), iv)
if (typeof data !== 'string' && !(data instanceof Buffer) && !(data instanceof DataView)) data = JSON.stringify(data)
let encrypted = ciph.update(data, inputEncoding, outputEncoding)
encrypted += ciph.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
return encrypted
let ciphertext = ciph.update(data, inputEncoding, outputEncoding)
ciphertext += ciph.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
return { iv: iv.toString('hex'), ciphertext }
}
} else if (tool === 'eccrypto') {
// data 应当是 utf8 的字符串。// 但在浏览器里不能使用 Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'
let cipherobject = await eccrypto.encrypt(this.hex2buf(key), data)
return cipherobject
} else if (keytype === 'seckey') {
// 尚未走通,不能使用 ticCrypto 生成的 Elliptic curve 椭圆曲线算法公私钥,只能用 crypto.generateKeypairs() 生成的 rsa 公私钥
let seckeyPEM = await new keyman.Key('oct', this.hex2buf(key), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
return crypto.privateEncrypt(seckeyPEM, Buffer.from(data))
return crypto.privateEncrypt(seckeyPEM, Buffer.from(data)) // 返回 Buffer。每次结果都一样。
} else if (keytype === 'pubkey') {
let pubkeyPEM = await new keyman.Key('oct', this.hex2buf(key), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
return crypto.publicEncrypt(pubkeyPEM, Buffer.from(data))
let pubkeyPEM = await new keyman.Key('oct', this.hex2buf(key), { namedCurve: 'P-256K' }).export('pem')
return crypto.publicEncrypt(pubkeyPEM, Buffer.from(data)) // 返回 Buffer。每次结果不一样。
}
return null
}
@ -210,34 +215,39 @@ class TICrypto {
* @return {String}
* @memberof TICrypto
*/
static async decrypt(data, { keytype, key, input, output, cipher, format } = {}) {
static async decrypt(data = {}, { keytype = 'pwd', key, input, output, cipher } = {}) {
// data 应当是 encrypt 输出的数据类型
if (keytype === 'pwd') {
if (data && (typeof data === 'string' || data instanceof Buffer) && typeof key === 'string') {
let inputEncoding = my.OUTPUT_LIST.indexOf(input) >= 0 ? input : my.OUTPUT // 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.indexOf(output) >= 0 ? output : my.INPUT // output (=input of encrypt) could be 'latin1', 'ascii', 'utf8' by default or 'buf' to Buffer explicitly
let decipher = crypto.createDecipher(my.CIPHER_LIST.indexOf(cipher) >= 0 ? cipher : my.CIPHER, this.hash(key))
let decrypted = decipher.update(data, inputEncoding, outputEncoding)
decrypted += decipher.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
if (format === 'json') {
// 如果用户输入错误密码deciper也能返回结果。为了判断是否正确结果对应当是 json 格式的原文做解析来验证。
try {
JSON.parse(decrypted)
} catch (exception) {
return null
}
}
return decrypted
}
} else if (keytype === 'seckey') {
// cipherobject 需要是 eccrypto 自身encrypt方法返回的对象
if (tool === 'eccrypto') {
try {
let plaindata = await eccrypto.decrypt(Buffer.from(key, 'hex'), data) // eccrypto 需要调用 Buffer.compare 方法,不能在这里直接用 hex2buf
// eccrypto 只能接受 Buffer, 不接受 Uint8Array, 因为 eccrypto 需要调用 Buffer.compare 方法,不能在这里直接用 hex2buf
// eccrypto 也只能接受 Buffer, 不接受 Uint8Array
let plaindata = await eccrypto.decrypt(Buffer.from(key, 'hex'), data) // data 需要是 eccrypto 自身encrypt方法返回的 cipherobject
return plaindata.toString('utf8')
} catch (exception) {
// eccrypto 对无法解密的,会抛出异常
return null
}
} else if (keytype === 'pwd') {
if ((typeof data.ciphertext === 'string' || data.ciphertext instanceof Buffer) && typeof key === 'string') {
let inputEncoding = my.OUTPUT_LIST.indexOf(input) >= 0 ? input : my.OUTPUT // 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.indexOf(output) >= 0 ? output : my.INPUT // output (=input of encrypt) could be 'latin1', 'ascii', 'utf8' by default or 'buf' to Buffer explicitly
let decipher = crypto.createDecipheriv(
my.CIPHER_LIST.indexOf(cipher) >= 0 ? cipher : my.CIPHER,
this.hex2buf(this.hash(key)),
Buffer.from(data.iv, 'hex')
)
let decrypted = decipher.update(data.ciphertext, inputEncoding, outputEncoding)
decrypted += decipher.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
// 如果用户输入错误密码deciper也能解密无法自动判断是否正确结果。可在返回后人工判断。
return decrypted
}
} else if (keytype === 'seckey') {
// 尚未走通,不能使用 ticCrypto 生成的 Elliptic curve 椭圆曲线算法公私钥
let seckeyPEM = await new keyman.Key('oct', this.hex2buf(key), { namedCurve: 'P-256K' }).export('pem') // 私钥导出的der格式为144字节。
return crypto.privateDecrypt(seckeyPEM, Buffer.from(data)) // 返回 Buffer。每次结果都一样。
} else if (keytype === 'pubkey') {
let pubkeyPEM = await new keyman.Key('oct', this.hex2buf(key), { namedCurve: 'P-256K' }).export('pem')
return crypto.publicDecrypt(pubkeyPEM, Buffer.from(data)) // 返回 Buffer。每次结果不一样。
}
return null
}
@ -957,12 +967,14 @@ class TICrypto {
}
/**
*
* 生成 uuid
*
* @static
* @memberof TICrypto
*/
static randomUuid = uuid.v4
static randomUuid() {
return uuid.v4()
}
/**
* 获取梅克哈希

View File

@ -6,7 +6,7 @@
"big-integer": "^1.6.48",
"bip39": "^3.0.2",
"bs58check": "^2.1.2",
"eccrypto": "^1.1.3",
"eccrypto-js": "^5.4.0",
"hdkey": "^1.1.1",
"js-crypto-key-utils": "^0.7.3",
"keccak": "^2.1.0",