From 1f1fe657f848c66e94da557a8894c76b7587d641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Tue, 15 Jan 2019 18:05:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=B9gcm=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Readme.md | 33 +++++++++++++++++++++++++-------- index.js | 47 +++++++++++++++++++++++++++++++++-------------- package.json | 2 +- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/Readme.md b/Readme.md index 872a335..c8b1c74 100644 --- a/Readme.md +++ b/Readme.md @@ -173,7 +173,7 @@ crypto.hmac('md5', '123456', 'sdfvkjfhd') > 在上面的2种算法中,加密都是不可逆的,也就是说,加密后的字符,我们是没办法再还原回去了,但是有很多场景,需要我们对拿到的加密字符,还原到明文状态。 > 所以出现了公钥加密这种算法; 而`Node.js`本身给我们提供了4种与公钥加密相关的类:`Cipher/Decipher、Sign、Verify`,这里只讲前面2个,以及它们衍生出来的`Cipheriv/Decipheriv`; -#### cipher(mode, data[, key][, inEncode][, outEncode]) +#### cipher(mode, data[, key, inEncode, outEncode]) - mode `` - data `` | `` - key `` 可选 @@ -182,24 +182,32 @@ crypto.hmac('md5', '123456', 'sdfvkjfhd') > `mode`为算法类型,常见的有`aes-128-cbc、aes-128-gcm`等等地,很多,具体有哪些可以通过 `this.crypto.getCiphers()` 来查看。 > 其他的参数与上面的HMAC算法相似; `inEncode`即声明要加密的数据是什么编码的,默认根据要加密的数据进行判断。 +>> 需要注意的是, 算法类型为`aes-***-gcm`时, 返回的不是一个字符串, 而是一个对象{ enStr, authTag }, 解密时, 需要提供这个 authTag方可解密 ```javascript -//这里给出一个AES-128-CBC的加密例子 -// +// 这里给出一个AES-128-CBC的加密例子 + crypto.cipher('aes-128-cbc', '123456', 'abcdefg') -//mqA9ZPh9VV+fwKlfpicGVg== +// mqA9ZPh9VV+fwKlfpicGVg== crypto.cipher('aes-128-cbc', '123456', 'abcdefg', 'utf8', 'hex') -//9aa03d64f87d555f9fc0a95fa6270656 +// 9aa03d64f87d555f9fc0a95fa6270656 + +// 要注意gcm算法的结果 +crypto.cipher('aes-128-gcm', '123456', 'abcdefg') +// { enStr: 'qmo1a4Jz', +// authTag: +// } ``` -#### decipher(mode, data[, key][, inEncode][, outEncode]) +#### decipher(mode, data[, key, tag, inEncode, outEncode]) - mode `` - data `` | `` - key `` 可选 +- tag `` 可选(mode为gcm算法时必填) - inEncode '' 可选, 默认是base64 - outEncode '' 可选,默认utf8 @@ -212,9 +220,18 @@ crypto.decipher('aes-128-cbc', 'mqA9ZPh9VV+fwKlfpicGVg==', 'abcdefg') // 这里一定要指定,因为之前加密的时候,指定输出为hex,所以这里也要指定输入的是hex编码 crypto.decipher('aes-128-cbc', '9aa03d64f87d555f9fc0a95fa6270656', 'abcdefg', 'hex') -//123456 +// 123456 + + + +// 要注意gcm算法的结果 +// authTag: +crypto.decipher('aes-128-gcm', 'qmo1a4Jz', 'abcdefg', authTag) +// 123456 + ``` -> 至于另外的`cipheriv/decipheriv`这2个方法,这里就不细讲了,和上面的这2个是同样的用法,只是要多1个参数`向量(iv)`, **`特别要注意的一点是,选择128位的加密算法,那key的长度就必须是16位,256则是32位,依此类推; 向量iv是16位`,具体的请看相关文档** \ No newline at end of file +> 至于另外的`cipheriv/decipheriv`这2个方法,这里就不细讲了,和上面的这2个是同样的用法,只是要多1个参数`向量(iv)` +>> **`特别要注意的一点是,选择128位的加密算法,那key的长度就必须是16位,256则是32位,依此类推; 算法类型为gcm时,返回的是对象,解密时需要提供authTag `,具体的请看相关文档** \ No newline at end of file diff --git a/index.js b/index.js index 0c568a2..c6aeabf 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,7 @@ const CRYPTO = require('crypto') const FS = require('fs') +const GCM_MODE = ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'] module.exports = { origin: CRYPTO, @@ -37,20 +38,29 @@ module.exports = { inEncode = isBuffer ? 'binary' : inEncode || 'utf8' outEncode = outEncode || 'base64' - let cp = CRYPTO.createCipher(mode, key) - let res = cp.update(data, inEncode, outEncode) - return res + cp.final(outEncode) + let cc = CRYPTO.createCipher(mode, key) + let enStr = cc.update(data, inEncode, outEncode) + enStr += cc.final(outEncode) + if (GCM_MODE.indexOf(mode) > -1) { + let authTag = cc.getAuthTag() + return { enStr: enStr, authTag: authTag } + } + return enStr }, - decipher(mode, data, key, inEncode, outEncode) { + decipher(mode, data, key, tag, inEncode, outEncode) { key = key || '' let isBuffer = Buffer.isBuffer(data) inEncode = isBuffer ? 'binary' : inEncode || 'base64' outEncode = outEncode || 'utf8' - let dcp = CRYPTO.createDecipher(mode, key) - let res = dcp.update(data, inEncode, outEncode) - return res + dcp.final(outEncode) + let cd = CRYPTO.createDecipher(mode, key) + if (GCM_MODE.indexOf(mode) > -1) { + cd.setAuthTag(tag) + } + let deStr = cd.update(data, inEncode, outEncode) + deStr += cd.final(outEncode) + return deStr }, cipheriv(mode, data, key, iv, inEncode, outEncode) { @@ -60,21 +70,30 @@ module.exports = { inEncode = isBuffer ? 'binary' : inEncode || 'utf8' outEncode = outEncode || 'base64' - let cp = CRYPTO.createCipheriv(mode, key, iv) - let res = cp.update(data, inEncode, outEncode) - return res + cp.final(outEncode) + let cciv = CRYPTO.createCipheriv(mode, key, iv) + let enStr = cciv.update(data, inEncode, outEncode) + enStr += cciv.final(outEncode) + if (GCM_MODE.indexOf(mode) > -1) { + let authTag = cciv.getAuthTag() + return { enStr: enStr, authTag: authTag } + } + return enStr }, - decipheriv(mode, data, key, iv, inEncode, outEncode) { + decipheriv(mode, data, key, iv, tag, inEncode, outEncode) { key = key || '0000000000000000' iv = iv || '' let isBuffer = Buffer.isBuffer(data) inEncode = isBuffer ? 'binary' : inEncode || 'base64' outEncode = outEncode || 'utf8' - let dcp = CRYPTO.createDecipheriv(mode, key, iv) - let res = dcp.update(data, inEncode, outEncode) - return res + dcp.final(outEncode) + let dcpiv = CRYPTO.createDecipheriv(mode, key, iv) + if (GCM_MODE.indexOf(mode) > -1) { + dcpiv.setAuthTag(tag) + } + let deStr = dcpiv.update(data, inEncode, outEncode) + deStr += dcpiv.final(outEncode) + return deStr }, /** diff --git a/package.json b/package.json index 7ebe047..def7048 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "crypto.js", - "version": "1.1.6", + "version": "1.2.0", "description": "原生crypto加密模块的二次封装,简化常用加密函数的使用", "keywords": ["md5", "sha1", "base64", "fivejs", "crypto"], "author": "yutent ",