Compare commits

..

7 Commits

Author SHA1 Message Date
yutent f26091f81c fixed fs 2024-07-17 12:21:49 +08:00
yutent 54a8feb5ca update 2024-03-11 16:50:44 +08:00
yutent 6740bed15b 更新文档 2024-03-11 16:48:18 +08:00
yutent 725d2e1231 优化字符 2023-12-27 10:30:11 +08:00
yutent b29fa3d163 更新readme 2023-12-27 10:28:54 +08:00
yutent ccb17bfd12 3.2.0 2023-12-27 10:27:33 +08:00
yutent 9f891e75f5 更新 2023-12-26 15:53:43 +08:00
6 changed files with 153 additions and 104 deletions

View File

@ -3,6 +3,12 @@
## 更新日志 ## 更新日志
+ v3.2.0
- 调整`cipher,decipher,cipheriv,decipheriv`的传参和返回结果, `aes-gcm`等算法,`tag`会拼接在密文后面。
- 增加`crypto`属性返回, 该属性为`原生crypto对象`
- 原`origin`属性标识为`Deprecated`,v4.0之后会直接移除。
- `cipher,cipheriv`, 默认的密钥和向量均为`Buffer.alloc(16)`
+ v3.1.2 + v3.1.2
- 优化`uuid()`, 增加有序性 - 优化`uuid()`, 增加有序性
@ -34,6 +40,7 @@ npm install crypto.js
// 1、 传统的 commonJS引入, 所有的方法都在上面 // 1、 传统的 commonJS引入, 所有的方法都在上面
var { var {
origin, // 原生crypto对象 origin, // 原生crypto对象
crypto, // 原生crypto对象
uuid, uuid,
rand, rand,
md5, md5,
@ -50,7 +57,8 @@ var {
// 2、 全新的 ESM 方式 // 2、 全新的 ESM 方式
import crypto from 'crypto.js' import crypto from 'crypto.js'
import crypto, { import crypto, {
origin, origin, // 原生crypto对象
crypto, // 原生crypto对象
uuid, uuid,
rand, rand,
md5, md5,
@ -68,7 +76,13 @@ import crypto, {
## 属性 ## 属性
> 其实就一个属性,即 `origin`,即为原生的`crypto`对象,方便在封装的方法中无法满足需求时,可以自行调用原生的`crypto`实现。
### `origin` (Deprecated)
> 即为原生的`crypto`对象,方便在封装的方法中无法满足需求时,可以自行调用原生的`crypto`实现。
### `crypto` (v3.2.0新增)
> 即为原生的`crypto`对象,方便在封装的方法中无法满足需求时,可以自行调用原生的`crypto`实现。
## 常用API方法 ## 常用API方法
> 对使用频率非常高的几种加密/编码进行更加简便的封装。 > 对使用频率非常高的几种加密/编码进行更加简便的封装。
@ -233,18 +247,20 @@ crypto.hmac('md5', '123456', 'sdfvkjfhd')
> 在上面的2种算法中加密都是不可逆的也就是说加密后的字符我们是没办法再还原回去了但是有很多场景需要我们对拿到的加密字符还原到明文状态。 > 在上面的2种算法中加密都是不可逆的也就是说加密后的字符我们是没办法再还原回去了但是有很多场景需要我们对拿到的加密字符还原到明文状态。
> 所以出现了公钥加密这种算法; 而`Node.js`本身给我们提供了4种与公钥加密相关的类`Cipher/Decipher、Sign、Verify`这里只讲前面2个以及它们衍生出来的`Cipheriv/Decipheriv`; > 所以出现了公钥加密这种算法; 而`Node.js`本身给我们提供了4种与公钥加密相关的类`Cipher/Decipher、Sign、Verify`这里只讲前面2个以及它们衍生出来的`Cipheriv/Decipheriv`;
>> Nodejs v10.0之后该方法为Deprecated, 推荐使用 cipheriv()
#### cipher(mode, data[, key, inEncode, outEncode]) #### cipher(mode, data[, key, inEncode, outEncode])
- mode `<String>` - mode `<String>`
- data `<String>` | `<Buffer>` - data `<String>` | `<Buffer>`
- key `<String>` 可选, 默认为 `<Buffer d7 2c 87 d0 f0 77 c7 76 6f 29 85 df ab 30 e8 95>`, 即 `crypto.scryptSync('', '', 16)` 的结果 - key `<String>` 可选, 默认为 `<Buffer 0 0 0 ... 0>`, 即 `Buffer.alloc(16)` 的结果
- inEncode '<String>' 可选 - inEncode '<String>' 可选
- outEncode '<String>' 可选,默认base64 - outEncode '<String>' 可选,默认返回Buffer对象
> `crypto.js v3.x`开始, `cipher()`内部改成调用 `cipheriv()`, 如果有特别原因, 仍然要调用的话, 请使用 `2.x版本` > `crypto.js v3.x`开始, `cipher()`内部改成调用 `cipheriv()`, 如果有特别原因, 仍然要调用的话, 请使用 `2.x版本`
> `mode`为算法类型,常见的有`aes-128-cbc、aes-128-gcm`等等地,很多,具体有哪些可以通过 `this.crypto.getCiphers()` 来查看。 > `mode`为算法类型,常见的有`aes-128-cbc、aes-128-gcm`等等地,很多,具体有哪些可以通过 `this.crypto.getCiphers()` 来查看。
> 其他的参数与上面的HMAC算法相似; `inEncode`即声明要加密的数据是什么编码的,默认根据要加密的数据进行判断。 > 其他的参数与上面的HMAC算法相似; `inEncode`即声明要加密的数据是什么编码的,默认根据要加密的数据进行判断。
>> 需要注意的是, 算法类型为`aes-***-gcm`时, 返回的不是一个字符串, 而是一个对象{ enStr, authTag }, 解密时, 需要提供这个 authTag方可解密
```javascript ```javascript
// 这里给出一个AES-128-CBC的加密例子 // 这里给出一个AES-128-CBC的加密例子
@ -255,16 +271,12 @@ crypto.cipher('aes-128-cbc', '123456', 'abcdefg')
crypto.cipher('aes-128-cbc', '123456', 'abcdefg', 'utf8', 'hex') crypto.cipher('aes-128-cbc', '123456', 'abcdefg', 'utf8', 'hex')
// 9aa03d64f87d555f9fc0a95fa6270656 // 9aa03d64f87d555f9fc0a95fa6270656
// 要注意gcm算法的结果
crypto.cipher('aes-128-gcm', '123456', 'abcdefg')
// { enStr: 'qmo1a4Jz',
// authTag: <Buffer c4 a0 3e ab e5 34 a0 ea 25 02 f0 91 06 f7 3b dd>
// }
// v3.x 之后, decipher()同理 // v3.x 之后, decipher()同理
crypto.cipher('aes-128-cbc', '123456', {key}) crypto.cipher('aes-128-cbc', '123456', {key})
// 等价于 // 等价于
crypto.cipheriv('aes-128-cbc', '123456', {key}, EMPTY_IV) // 其中 EMPTY_IV = crypto.scryptSync('', '', 16) crypto.cipheriv('aes-128-cbc', '123456', {key}, EMPTY_IV) // 其中 EMPTY_IV = Buffer.alloc(16)
``` ```
@ -279,6 +291,8 @@ crypto.cipheriv('aes-128-cbc', '123456', {key}, EMPTY_IV) // 其中 EMPTY_IV = c
> 这是与上面的`cipher`对应的解密方法; > 这是与上面的`cipher`对应的解密方法;
>> Nodejs v10.0之后该方法为Deprecated, 推荐使用 decipheriv()
```javascript ```javascript
// 这里不用指定编码默认即为base64 // 这里不用指定编码默认即为base64
crypto.decipher('aes-128-cbc', 'mqA9ZPh9VV+fwKlfpicGVg==', 'abcdefg') crypto.decipher('aes-128-cbc', 'mqA9ZPh9VV+fwKlfpicGVg==', 'abcdefg')
@ -290,14 +304,8 @@ crypto.decipher('aes-128-cbc', '9aa03d64f87d555f9fc0a95fa6270656', 'abcdefg', 'h
// 要注意gcm算法的结果
// authTag: <Buffer c4 a0 3e ab e5 34 a0 ea 25 02 f0 91 06 f7 3b dd>
crypto.decipher('aes-128-gcm', 'qmo1a4Jz', 'abcdefg', authTag)
// 123456
``` ```
> 至于另外的`cipheriv/decipheriv`这2个方法这里就不细讲了和上面的这2个是同样的用法只是要多1个参数`向量(iv)` > 至于另外的`cipheriv/decipheriv`这2个方法这里就不细讲了和上面的这2个是同样的用法只是要多1个参数`向量(iv)`
>> **`特别要注意的一点是选择128位的加密算法那key的长度就必须是16位256则是32位依此类推; 算法类型为gcm时,返回的是对象,解密时需要提供authTag `,具体的请看相关文档** >> **`特别要注意的一点是选择128位的加密算法那key的长度就必须是16位256则是32位依此类推`,具体的请看相关文档**

View File

@ -7,7 +7,7 @@
const Es = require('esbuild') const Es = require('esbuild')
Es.build({ Es.build({
entryPoints: ['src/index.mjs'], entryPoints: ['src/index.js'],
outfile: 'dist/index.mjs', outfile: 'dist/index.mjs',
platform: 'node', platform: 'node',
bundle: true, bundle: true,
@ -15,7 +15,7 @@ Es.build({
format: 'esm' format: 'esm'
}) })
Es.build({ Es.build({
entryPoints: ['src/index.mjs'], entryPoints: ['src/index.js'],
outfile: 'dist/index.js', outfile: 'dist/index.js',
platform: 'node', platform: 'node',
bundle: true, bundle: true,

View File

@ -1,14 +1,14 @@
{ {
"name": "crypto.js", "name": "crypto.js",
"version": "3.1.2", "version": "3.2.2",
"description": "原生crypto加密模块的二次封装,简化常用加密函数的使用", "description": "原生crypto加密模块的二次封装,简化常用加密函数的使用",
"keywords": [ "keywords": [
"md5", "md5",
"sha1", "sha1",
"sha256", "sha256",
"hmac", "hmac",
"aes",
"base64", "base64",
"fivejs",
"crypto", "crypto",
"crypto-js", "crypto-js",
"crypto.js" "crypto.js"
@ -16,10 +16,8 @@
"author": "yutent <yutent.io@gmail.com>", "author": "yutent <yutent.io@gmail.com>",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/bytedo/crypto.js.git" "url": "https://git.wkit.fun/bytedo/crypto.js.git"
}, },
"dependencies": {},
"devDependencies": {},
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [
"dist/*" "dist/*"

View File

@ -12,15 +12,15 @@ const AUTH_MODE = [
'aes-256-ocb' 'aes-256-ocb'
] ]
const VERSION = +process.versions.node.split('.').slice(0, 2).join('.') const VERSION = +process.versions.node.split('.').slice(0, 2).join('.')
const KEY_16 = Buffer.alloc(16)
function format(buff, encode) {
if (encode === void 0 || encode === 'buffer') {
return buff
}
return buff.toString(encode)
}
// <Buffer d7 2c 87 d0 f0 77 c7 76 6f 29 85 df ab 30 e8 95>
const EMPTY_KEY = crypto.scryptSync
? crypto.scryptSync('', '', 16)
: Buffer.from(
'0xd7 0x2c 0x87 0xd0 0xf0 0x77 0xc7 0x76 0x6f 0x29 0x85 0xdf 0xab 0x30 0xe8 0x95'.split(
' '
)
)
// //
if (!crypto.randomUUID) { if (!crypto.randomUUID) {
crypto.randomUUID = function () { crypto.randomUUID = function () {
@ -49,13 +49,13 @@ if (!crypto.randomInt) {
} }
} }
export const origin = crypto export { crypto }
export const hash = function (mode, data, outEncode) { export const hash = function (mode, data, outEncode) {
let sum = crypto.createHash(mode) let sum = crypto.createHash(mode)
let isBuffer = Buffer.isBuffer(data) let isBuffer = Buffer.isBuffer(data)
sum.update(data, isBuffer ? 'binary' : 'utf8') sum.update(data, isBuffer ? 'buffer' : 'utf8')
return sum.digest(outEncode || 'hex') return sum.digest(outEncode || 'hex')
} }
@ -64,101 +64,111 @@ export const hmac = function (mode, data, key, outEncode) {
let sum = crypto.createHmac(mode, key) let sum = crypto.createHmac(mode, key)
let isBuffer = Buffer.isBuffer(data) let isBuffer = Buffer.isBuffer(data)
sum.update(data, isBuffer ? 'binary' : 'utf8') sum.update(data, isBuffer ? 'buffer' : 'utf8')
return sum.digest(outEncode || 'hex') return sum.digest(outEncode || 'hex')
} }
export const cipher = function ( export const cipher = function (
mode, mode,
data, data,
key = EMPTY_KEY, key = KEY_16,
inEncode, inEncode = 'utf8',
outEncode outEncode
) { ) {
// 10.0.0之后, createCipher方法不推荐使用了 // 10.0.0之后, createCipher方法不推荐使用了
if (VERSION >= 10.5) { if (VERSION >= 10.5) {
return cipheriv(mode, data, key, EMPTY_KEY, inEncode, outEncode) return cipheriv(mode, data, key, KEY_16, inEncode, outEncode)
} }
let isBuffer = Buffer.isBuffer(data) let isBuffer = Buffer.isBuffer(data)
inEncode = isBuffer ? 'binary' : inEncode || 'utf8' inEncode = isBuffer ? 'buffer' : inEncode
outEncode = outEncode || 'base64'
let _cipher = crypto.createCipher(mode, key)
let buff = _cipher.update(data, inEncode)
buff = Buffer.concat([buff, _cipher.final()])
let cipher = crypto.createCipher(mode, key)
let enStr = cipher.update(data, inEncode, outEncode)
enStr += cipher.final(outEncode)
if (AUTH_MODE.indexOf(mode) > -1) { if (AUTH_MODE.indexOf(mode) > -1) {
let authTag = cipher.getAuthTag() buff = Buffer.concat([buff, _cipher.getAuthTag()])
return { enStr, authTag }
} }
return enStr return format(buff, outEncode)
} }
export const decipher = function ( export const decipher = function (
mode, mode,
data, data,
key = EMPTY_KEY, key = KEY_16,
tag, inEncode = 'base64',
inEncode, outEncode = 'utf8'
outEncode
) { ) {
// 10.0.0之后, createCipher方法不推荐使用了 // 10.0.0之后, createCipher方法不推荐使用了
if (VERSION >= 10.5) { if (VERSION >= 10.5) {
return decipheriv(mode, data, key, EMPTY_KEY, tag, inEncode, outEncode) return decipheriv(mode, data, key, KEY_16, inEncode, outEncode)
} }
let isBuffer = Buffer.isBuffer(data) let isBuffer = Buffer.isBuffer(data)
inEncode = isBuffer ? 'binary' : inEncode || 'base64' if (!isBuffer) {
outEncode = outEncode || 'utf8' data = Buffer.from(data, inEncode)
let cd = crypto.createDecipher(mode, key)
if (AUTH_MODE.indexOf(mode) > -1) {
cd.setAuthTag(tag)
} }
let deStr = cd.update(data, inEncode, outEncode) inEncode = 'buffer'
deStr += cd.final(outEncode)
return deStr let _decipher = crypto.createDecipher(mode, key)
if (AUTH_MODE.indexOf(mode) > -1) {
let tag = data.slice(-16)
data = data.slice(0, -16)
_decipher.setAuthTag(tag)
}
let buff = _decipher.update(data, inEncode)
buff = Buffer.concat([buff, _decipher.final()])
return format(buff, outEncode)
} }
export const cipheriv = function ( export const cipheriv = function (
mode, mode,
data, data,
key = EMPTY_KEY, key = KEY_16,
iv = EMPTY_KEY, iv = KEY_16,
inEncode, inEncode = 'utf8',
outEncode outEncode
) { ) {
let isBuffer = Buffer.isBuffer(data) let isBuffer = Buffer.isBuffer(data)
inEncode = isBuffer ? 'binary' : inEncode || 'utf8' inEncode = isBuffer ? 'buffer' : inEncode
outEncode = outEncode || 'base64'
let _cipher = crypto.createCipheriv(mode, key, iv)
let buff = _cipher.update(data, inEncode)
buff = Buffer.concat([buff, _cipher.final()])
let cciv = crypto.createCipheriv(mode, key, iv)
let enStr = cciv.update(data, inEncode, outEncode)
enStr += cciv.final(outEncode)
if (AUTH_MODE.indexOf(mode) > -1) { if (AUTH_MODE.indexOf(mode) > -1) {
let authTag = cciv.getAuthTag() buff = Buffer.concat([buff, _cipher.getAuthTag()])
return { enStr, authTag }
} }
return enStr return format(buff, outEncode)
} }
export const decipheriv = function ( export const decipheriv = function (
mode, mode,
data, data,
key = EMPTY_KEY, key = KEY_16,
iv = EMPTY_KEY, iv = KEY_16,
tag, inEncode = 'base64',
inEncode, outEncode = 'utf8'
outEncode
) { ) {
let isBuffer = Buffer.isBuffer(data) let isBuffer = Buffer.isBuffer(data)
inEncode = isBuffer ? 'binary' : inEncode || 'base64'
outEncode = outEncode || 'utf8'
let dcpiv = crypto.createDecipheriv(mode, key, iv) if (!isBuffer) {
if (AUTH_MODE.indexOf(mode) > -1) { data = Buffer.from(data, inEncode)
dcpiv.setAuthTag(tag)
} }
let deStr = dcpiv.update(data, inEncode, outEncode) inEncode = 'buffer'
deStr += dcpiv.final(outEncode)
return deStr let _decipher = crypto.createDecipheriv(mode, key, iv)
if (AUTH_MODE.indexOf(mode) > -1) {
let tag = data.slice(-16)
data = data.slice(0, -16)
_decipher.setAuthTag(tag)
}
let buff = _decipher.update(data, inEncode)
buff = Buffer.concat([buff, _decipher.final()])
return format(buff, outEncode)
} }

View File

@ -7,14 +7,14 @@
import os from 'os' import os from 'os'
import fs from 'fs' import fs from 'fs'
import { import {
origin, crypto,
hash, hash,
hmac, hmac,
cipher, cipher,
decipher, decipher,
cipheriv, cipheriv,
decipheriv decipheriv
} from './helper.mjs' } from './helper.js'
const MAC = (function (ns) { const MAC = (function (ns) {
for (let k in ns) { for (let k in ns) {
@ -27,15 +27,15 @@ const MAC = (function (ns) {
return Math.random().toString(16).slice(-4) return Math.random().toString(16).slice(-4)
})(os.networkInterfaces()) })(os.networkInterfaces())
var __inc__ = 4096 let __inc__ = 4096
/** /**
* [base64encode base64编码] * [base64encode base64编码]
* @param {Str/Num/Buffer} str [要编码的字符串] * @param {Str/Num/Buffer} str [要编码的字符串]
* @param {bool} urlFriendly [是否对URL友好默认否是则会把+转成-/转成_] * @param {bool} urlFriendly [是否对URL友好, 默认否, 是则会把+转成-, /_]
*/ */
export function base64encode(str, urlFriendly) { export function base64encode(str, urlFriendly) {
var buf, str64 let buf, str64
if (Buffer.isBuffer(str)) { if (Buffer.isBuffer(str)) {
buf = str buf = str
@ -79,15 +79,15 @@ export function rand(len, forceNum) {
let max = str.length let max = str.length
let tmp = '' let tmp = ''
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
tmp += str[origin.randomInt(max)] tmp += str[crypto.randomInt(max)]
} }
return tmp return tmp
} }
// 返回一个如下格式的 xxxxxxxx-xxxx-xxxx-xxxxxxxx 的唯一ID // 返回一个如下格式的 xxxxxxxx-xxxx-xxxx-xxxxxxxx 的唯一ID
export function uuid(pipe = '-') { export function uuid(pipe = '-') {
var str = origin.randomUUID() let str = crypto.randomUUID()
var now = (~~(Date.now() / 1000)).toString(16) let now = (~~(Date.now() / 1000)).toString(16)
if (__inc__ > 65535) { if (__inc__ > 65535) {
__inc__ = 4096 __inc__ = 4096
@ -121,11 +121,12 @@ export function md5(str, encode) {
* @param {Str} file [文件路径] * @param {Str} file [文件路径]
*/ */
export function md5Sign(file) { export function md5Sign(file) {
if (fs.accessSync(file, fs.constants.R_OK)) { try {
var buf = fs.readFileSync(file) let buf = fs.readFileSync(file)
return hash('md5', buf) return hash('md5', buf)
} } catch (e) {
return null return null
}
} }
/** /**
@ -149,11 +150,12 @@ export function sha1(str, encode) {
* @param {Str} file [文件路径] * @param {Str} file [文件路径]
*/ */
export function sha1Sign(file) { export function sha1Sign(file) {
if (fs.accessSync(file, fs.constants.R_OK)) { try {
var buf = fs.readFileSync(file) let buf = fs.readFileSync(file)
return hash('sha1', buf) return hash('sha1', buf)
} } catch (e) {
return null return null
}
} }
/** /**
@ -177,14 +179,24 @@ export function sha256(str, encoding) {
* @param {Str} file [文件路径] * @param {Str} file [文件路径]
*/ */
export function sha256Sign(file) { export function sha256Sign(file) {
if (fs.accessSync(file, fs.constants.R_OK)) { try {
var buf = fs.readFileSync(file) let buf = fs.readFileSync(file)
return hash('sha256', buf) return hash('sha256', buf)
} } catch (e) {
return null return null
}
} }
export { origin, hash, hmac, cipher, decipher, cipheriv, decipheriv } export {
crypto,
crypto as origin,
hash,
hmac,
cipher,
decipher,
cipheriv,
decipheriv
}
export default { export default {
base64encode, base64encode,
@ -197,7 +209,8 @@ export default {
sha1Sign, sha1Sign,
sha256, sha256,
sha256Sign, sha256Sign,
origin, crypto,
origin: crypto,
hash, hash,
hmac, hmac,
cipher, cipher,

20
test/test.js Normal file
View File

@ -0,0 +1,20 @@
import { crypto, cipher, cipheriv, decipher, decipheriv } from '../src/index.js'
let algorithm = 'aes-128-cbc'
let data = 'abcd'
let key = Buffer.alloc(16)
let key2 = Buffer.alloc(32)
let iv = Buffer.alloc(16)
let encode = 'base64'
// console.log(crypto.getCiphers())
let output1 = cipher(algorithm, data, key, 'utf8', encode)
let output2 = cipheriv(algorithm, data, key, iv)
console.log(output1)
console.log(output2.toString(encode))
console.log(decipher(algorithm, output1, key))
console.log(decipheriv(algorithm, output2, key, iv))