This commit is contained in:
陆柯 2020-05-04 15:37:09 +08:00
parent b6b90b6a38
commit 6154eaef29
2 changed files with 28 additions and 31 deletions

View File

@ -99,9 +99,9 @@ module.exports = {
return null
}
,
async encrypt(data, {keytype, key, input, output, cipher}={}){
async encrypt(data, {tool, keytype, key, input, output, cipher}={}){
if (keytype==='pwd') {
if (this.isHashable(data) && typeof(key)==='string') {
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(
@ -113,9 +113,15 @@ module.exports = {
encrypted += ciph.final(outputEncoding) // 但是 Buffer + Buffer 还是会变成string
return encrypted
}
}else if (keytype==='pubkey') { // data 应当是 utf8 的字符串。// 但在浏览器里不能使用 Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'
}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'){
let seckeyPEM = await new keyman.Key('oct', this.hex2buf(key), {namedCurve:'P-256K'}).export('pem') // 私钥导出的der格式为144字节。
return crypto.privateEncrypt(seckeyPEM, Buffer.from(data))
}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))
}
return null
}
@ -151,15 +157,16 @@ module.exports = {
}
,
async sign(data, seckey, option={}) { // data can be string or buffer or object, results are the same
if (this.isHashable(data) && this.isSeckey(seckey) && seckey.length===64) {
if (option.tool==='nacl') {
// 这样不行无法和verify共享一套公私钥。
// let naclSeckey = this.buf2hex(nacl.sign.keyPair.fromSeed(seckey).seckey)
// return await this.sign(data, naclSeckey, option)
}else if (option.tool==='eccrypto') { // eccrypto 对同一组data,seckey生成的签名是固定的观察到hex长度为140或142是der格式。
if (this.isHashable(data) && this.isSeckey(seckey)) {
if (option.tool==='nacl' && seckey.length===128) { // 使用nacl的签名算法。注意nacl.sign需要的seckey是64字节=128字符。
option.output='buf' // 哈希必须输出为 buffer
let hashBuf = this.hash(data, option)
let signature = nacl.sign.detached(hashBuf, Buffer.from(seckey, 'hex'))
return Buffer.from(signature).toString('hex') // 签名是64节128个hex字符
}else if (option.tool==='eccrypto' && seckey.length===64) { // eccrypto 对同一组data,seckey生成的签名是固定的观察到hex长度为140或142是der格式。
let signature = await eccrypto.sign(Buffer.from(seckey,'hex'), this.hash(data, {output:'buf'}))
return signature.toString('hex')
}else { // 纯 crypto
}else if (seckey.length===64){ // 纯 crypto
let seckeyPEM = await new keyman.Key('oct', this.hex2buf(seckey), {namedCurve:'P-256K'}).export('pem') // 私钥导出的der格式为144字节。
let hasher=my.HASHER_LIST.indexOf(option.hasher)>=0?option.hasher:my.HASHER
let signer=crypto.createSign(hasher)
@ -168,28 +175,26 @@ module.exports = {
return signature // 发现同样的输入nodejs里每次调用会生成不同的 signature, 且长度不定(140,142,144 hex) 但都可以通过 verify。但在浏览器里调用signature却是固定的。
}
}
if (this.isHashable(data) && this.isSeckey(seckey) && seckey.length===128) { // 使用nacl的签名算法。注意nacl.sign需要的seckey是64字节=128字符。
option.output='buf' // 哈希必须输出为 buffer
let hashBuf = this.hash(data, option)
let signature = nacl.sign.detached(hashBuf, Buffer.from(seckey, 'hex'))
return Buffer.from(signature).toString('hex') // 签名是64节128个hex字符
}
return null
}
,
async verify (data, signature, pubkey, option={}) { // data could be anything, but converts to string or remains be Buffer/TypedArray/DataView
if (this.isHashable(data) && this.isSignature(signature) && this.isPubkey(pubkey) && signature.length>=140){
if ('nacl' === option.tool) {
// 这样不行无法和sign共享一套公私钥
// let naclPubkey = nacl.sign.keyPair.fromSeed()
}else if ('eccrypto' === option.tool) { // 默认使用 eccrypto
if (this.isHashable(data) && this.isSignature(signature) && this.isPubkey(pubkey)){
if ('nacl' === option.tool && signature.length === 128) {
option.output='buf' // 哈希必须输出为 buffer
let bufHash=this.hash(data, option)
let bufSignature = Buffer.from(signature, 'hex')
let bufPubkey = Buffer.from(pubkey, 'hex')
let verified = nacl.sign.detached.verify(bufHash, bufSignature, bufPubkey)
return verified
}else if ('eccrypto' === option.tool && signature.length >= 140) { // 默认使用 eccrypto
try {
let result = await eccrypto.verify(Buffer.from(pubkey, 'hex'), this.hash(data, {output:'buf'}), Buffer.from(signature, 'hex')) // 如果给signature添加1位hexeccrypto 的 verify结果也是true! 估计因为一位hex不被转成字节。
return true
}catch(exception){ // 对能够验证的eccrypto返回 null对无法验证的抛出异常
return false
}
}else { // 纯 crypto
}else if (signature.length >= 140) { // 纯 crypto
let pubkeyPEM = await new keyman.Key('oct', this.hex2buf(pubkey), {namedCurve:'P-256K'}).export('pem') // 公钥导出的der格式为88字节。经测试同一对压缩和非压缩公钥得出的结果一模一样。
let hasher=my.HASHER_LIST.indexOf(option.hasher)>=0?option.hasher:my.HASHER
let verifier = crypto.createVerify(hasher)
@ -197,15 +202,6 @@ module.exports = {
let verified = verifier.verify(pubkeyPEM, signature, 'hex') // 如果给signature添加1位hexcrypto 的 verify结果也是true! 估计因为一位hex不被转成字节。
return verified
}
return false
}
if (this.isHashable(data) && this.isSignature(signature) && this.isPubkey(pubkey) && signature.length===128){ // nacl
option.output='buf' // 哈希必须输出为 buffer
let bufHash=this.hash(data, option)
let bufSignature = Buffer.from(signature, 'hex')
let bufPubkey = Buffer.from(pubkey, 'hex')
let verified = nacl.sign.detached.verify(bufHash, bufSignature, bufPubkey)
return verified
}
return false
}

View File

@ -10,6 +10,7 @@
"hdkey": "^1.1.1",
"js-crypto-key-utils": "^0.7.3",
"keccak": "^2.1.0",
"secp256k1": "^4.0.1",
"tweetnacl": "^1.0.3",
"uuid": "^3.3.2"
},