Compare commits

...

34 Commits

Author SHA1 Message Date
yutent 6313b9c0a8 添加MIT开源协议 2025-01-03 18:51:24 +08:00
yutent fae1ce2f15 修复声明 2025-01-03 18:46:51 +08:00
yutent a740ad2f73 优化index.d.ts 2025-01-03 18:25:00 +08:00
yutent b25b04efbc 优化`.d.ts`参数声明 2024-12-13 12:07:11 +08:00
yutent 1794ab0470 增加 `.d.ts`, 默认为esm加载 2024-12-12 16:05:44 +08:00
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
yutent 52af19e58e 优化`uuid()`, 增加有序性 2023-10-18 19:20:15 +08:00
yutent 20639ab038 优化uuid, 增加有序特性 2023-06-02 18:53:02 +08:00
yutent 5281159c21 优化引入方式,及uuid算法 2023-02-13 17:19:05 +08:00
yutent 3cc8c53a72 cipher()内部判断Node.js版本, 大于10.5时,改为调用cipheriv() 2022-01-08 16:43:29 +08:00
yutent 4617514a7c update 2022-01-08 16:02:24 +08:00
yutent 83d3f04b44 更新readme 2022-01-08 16:00:36 +08:00
yutent 7bbec9afbf 改成esbuild打包;公钥加密增加版本判断, 10.0之后, 不再使用createCipher 2022-01-07 19:45:59 +08:00
宇天 f0240827db 优化uuid 2021-06-24 17:55:47 +08:00
宇天 9abf208084 fixed 2021-06-24 14:04:32 +08:00
宇天 24d5287baf 优化uuid 2021-06-23 17:25:04 +08:00
宇天 c21a72a9a2 修复base64传buffer的bug;优化各方法的类型判断 2020-09-24 18:02:13 +08:00
宇天 a938cfcbab update repo 2020-09-18 15:55:47 +08:00
宇天 a8d98697b8 fixed import 2020-09-17 16:58:56 +08:00
宇天 c9824a10e0 2.0.0 2020-09-17 16:30:45 +08:00
宇天 95f5b85bb6 增加esm模块 2020-09-16 20:01:35 +08:00
宇天 00026e9b8b 优化 2019-06-17 17:18:41 +08:00
宇天 704a806e49 增加sha256Sign方法;uuid增加配置 2019-06-17 17:11:53 +08:00
宇天 9f5580edfa 优化base64解码 2019-03-08 19:04:42 +08:00
宇天 1f1fe657f8 修复对gcm算法的支持 2019-01-15 18:05:09 +08:00
宇天 5c8ec8e024 fixed fs bug 2018-12-23 17:21:58 +08:00
宇天 5af78262e7 优化md5/sha1/sha256,支持对buffer对象求值 2018-10-08 12:22:48 +08:00
宇天 15ebc01f93 优化base64的编码和解码 2018-08-31 14:12:50 +08:00
11 changed files with 787 additions and 273 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
.Spotlight-V100
.Trashes
.DS_Store
.AppleDouble
.LSOverride
._*
.idea
.vscode
dist/

12
.npmignore Normal file
View File

@ -0,0 +1,12 @@
.Spotlight-V100
.Trashes
.DS_Store
.AppleDouble
.LSOverride
._*
.idea
.vscode
src/
build.js

21
LICENSE copy Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

189
Readme.md
View File

@ -1,48 +1,129 @@
# 加密工具(Crypto)
> 本模块是对原生的`crypto`模块二次封装的,在使用上更加简单方便。
## 更新日志
+ v3.3.4
- 添加MIT开源协议
+ v3.3.3
- 优化`.d.ts`参数声明
+ v3.3.1
- 优化`.d.ts`参数声明
+ v3.3.0
- 增加 `.d.ts`, 默认为esm加载
+ v3.2.0
- 调整`cipher,decipher,cipheriv,decipheriv`的传参和返回结果, `aes-gcm`等算法,`tag`会拼接在密文后面。
- 增加`crypto`属性返回, 该属性为`原生crypto对象`
- 原`origin`属性标识为`Deprecated`,v4.0之后会直接移除。
- `cipher,cipheriv`, 默认的密钥和向量均为`Buffer.alloc(16)`
+ v3.1.2
- 优化`uuid()`, 增加有序性
+ v3.1.0
- 优化`uuid(),rand()`
- 优化库引用方式
+ v3.0.0
- Node.js 10.0.0之后不再推荐使用`crypto.createCipher()`, 所以 本库的`cipher()`方法, 内部改为调用`cipheriv()` (Node.js大于10.5.0时, 旧版本的不变)
+ v2.1.0
- 优化`cipher()`等公钥加密方法的`key`和`iv`的默认值为`crypto.scryptSync('', '', 16)`
- 使用ESBuild进行打包。
+ v2.0.5
- 优化`uuid()`的实现。
## 安装
- 使用npm安装
```bash
npm install crypto.js
```
- 从github获取
```bash
git clone https://github.com/yutent/crypto.js.git
## 说明
> 本模块内置2种不同的引入方式。
```js
// 1、 传统的 commonJS引入, 所有的方法都在上面
var {
origin, // 原生crypto对象
crypto, // 原生crypto对象
uuid,
rand,
md5,
md5Sign,
sha1,
sha1Sign,
sha256,
sha256Sign,
sha512,
sha512Sign,
base64encode,
base64decode
} = require('crypto.js')
// 2、 全新的 ESM 方式
import crypto from 'crypto.js'
import crypto, {
origin, // 原生crypto对象
crypto, // 原生crypto对象
uuid,
rand,
md5,
md5Sign,
sha1,
sha1Sign,
sha256,
sha256Sign,
sha512,
sha512Sign,
base64encode,
base64decode,
} from 'crypto.js'
```
## 属性
> 其实就一个属性,即 `origin`,即为原生的`crypto`对象,方便在封装的方法中无法满足需求时,可以自行调用原生的`crypto`实现。
### `origin` (Deprecated)
> 即为原生的`crypto`对象,方便在封装的方法中无法满足需求时,可以自行调用原生的`crypto`实现。
### `crypto` (v3.2.0新增)
> 即为原生的`crypto`对象,方便在封装的方法中无法满足需求时,可以自行调用原生的`crypto`实现。
## 常用API方法
> 对使用频率非常高的几种加密/编码进行更加简便的封装。
### rand(len[, forceNum])
- len `<Number>`
- forceNum `<Boolean>` 可选
- len `<Number>` 需要的字符长度
- forceNum `<Boolean>` 返回纯数字字符串 [可选]
> 该方法用于生成指定长度的随机字符串`[a-z-A-z0-9]`,参数`len`即为要生成的字符串长度了; 而`forceNum` 顾名思义,就是是否强制返回纯数字字符串。
> 该方法用于生成指定长度的随机字符串`[a-z-A-z0-9]`
```javascript
let crypto = require('crypto.js')
crypto.rand(6) // ddjF7d
crypto.rand(16) // 4sf7dJH6tGHDjhdf
crypto.rand(6, true) // 439875
crypto.rand(10, true) // 3458765234
let { rand } = require('crypto.js')
rand(6) // ddjF7d
rand(16) // 4sf7dJH6tGHDjhdf
rand(6, true) // 439875
rand(10, true) // 3458765234
```
### uuid()
> 返回一个如下格式的 xxxxxxxx-xxxx-xxxx-xxxxxxxx 的唯一ID
>> 1、加入机器码, 减小不同机器生成的uuid相同的机率
>> 2、每秒可生成20万个ID(测试机器: Intel i5-8500B@3.00GHz 16G内存)
```javascript
let crypto = require('crypto.js')
crypto.uuid() // 076d029f-4927-ec5f-5b06e35e
let { uuid } = require('crypto.js')
uuid() // 076d029f-4927-ec5f-5b06e35e
```
@ -55,20 +136,20 @@ crypto.uuid() // 076d029f-4927-ec5f-5b06e35e
> 这方法,应该没有人不知道是做什么的了,`encode`是要返回的字符串编码,默认为`hex` 可选`base64` 不过有这需求的人可能也许大概...很少吧。
```javascript
crypto.md5(123456) // e10adc3949ba59abbe56e057f20f883e
crypto.md5('123456') // e10adc3949ba59abbe56e057f20f883e
crypto.md5('hello world') // 5eb63bbbe01eeed093cb22bb8f5acdc3
crypto.md5('hello world', 'base64') // XrY7u+Ae7tCTyyK7j1rNww==
md5(123456) // e10adc3949ba59abbe56e057f20f883e
md5('123456') // e10adc3949ba59abbe56e057f20f883e
md5('hello world') // 5eb63bbbe01eeed093cb22bb8f5acdc3
md5('hello world', 'base64') // XrY7u+Ae7tCTyyK7j1rNww==
```
### md5Sign(file)
- file `<String>`
> 该方法用于计算文件的md5签名`file`即为文件的绝对路径。
> 该方法用于计算文件的md5签名`file`即为文件的路径。
```javascript
crypto.md5Sign('xx.jpg')
md5Sign('xx.jpg')
```
@ -79,20 +160,20 @@ crypto.md5Sign('xx.jpg')
> 这方法也应该没有人不知道是做什么的了,`encode`是要返回的字符串编码,默认为`hex` 可选`base64` 不过有这需求的人可能也许大概...很少吧。
```javascript
crypto.sha1(123456) // 7c4a8d09ca3762af61e59520943dc26494f8941b
crypto.sha1('123456') // 7c4a8d09ca3762af61e59520943dc26494f8941b
crypto.sha1('hello world') // 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
crypto.sha1('hello world', 'base64') // Kq5sNclPz7QV2+lfQIuc6R7oRu0=
sha1(123456) // 7c4a8d09ca3762af61e59520943dc26494f8941b
sha1('123456') // 7c4a8d09ca3762af61e59520943dc26494f8941b
sha1('hello world') // 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
sha1('hello world', 'base64') // Kq5sNclPz7QV2+lfQIuc6R7oRu0=
```
### sha1Sign(file)
- file `<String>`
> 该方法用于计算文件的sha1签名`file`即为文件的绝对路径。
> 该方法用于计算文件的sha1签名`file`即为文件的路径。
```javascript
crypto.sha1Sign('xx.jpg')
sha1Sign('xx.jpg')
```
@ -103,6 +184,13 @@ crypto.sha1Sign('xx.jpg')
> 自然这方法,也没啥好说的了。
### sha256Sign(file)
- file `<String>`
> 都懂的。
### base64encode(str[, urlFriendly])
- str `<Number>` | `<String>` | `<Buffer>`
@ -111,7 +199,7 @@ crypto.sha1Sign('xx.jpg')
> 这是用来进行base64编码的本身没啥好说。主要是第2个参数是指编码的结果是否对URL友好默认为否; 如果为true则会把+转成-/转成_ (遵循RFC4648标准)。
```javascript
crypto.base64encode('hello world') //aGVsbG8gd29ybGQ=
base64encode('hello world') //aGVsbG8gd29ybGQ=
```
@ -121,10 +209,10 @@ crypto.base64encode('hello world') //aGVsbG8gd29ybGQ=
- str `<String>`
- urlFriendly `<Boolean>` 可选
> 与之对应的便是这个base解码了。同样`urlFriendly`是指要解码的字符串之前是否采用了URL友好处理默认否。
> base64解码, 返回Buffer对象。同样`urlFriendly`是指要解码的字符串之前是否采用了URL友好处理默认否。
```javascript
crypto.base64decode('aGVsbG8gd29ybGQ=') //hello world
base64decode('aGVsbG8gd29ybGQ=')// .toString('utf-8') === hello world
```
@ -147,6 +235,8 @@ crypto.base64decode('aGVsbG8gd29ybGQ=') //hello world
```javascript
crypto.hash('md5', '123456') //e10adc3949ba59abbe56e057f20f883e
// 等价于
md5('123456')
```
@ -172,38 +262,52 @@ crypto.hmac('md5', '123456', 'sdfvkjfhd')
> 在上面的2种算法中加密都是不可逆的也就是说加密后的字符我们是没办法再还原回去了但是有很多场景需要我们对拿到的加密字符还原到明文状态。
> 所以出现了公钥加密这种算法; 而`Node.js`本身给我们提供了4种与公钥加密相关的类`Cipher/Decipher、Sign、Verify`这里只讲前面2个以及它们衍生出来的`Cipheriv/Decipheriv`;
#### cipher(mode, data[, key][, inEncode][, outEncode])
>> Nodejs v10.0之后该方法为Deprecated, 推荐使用 cipheriv()
#### cipher(mode, data[, key, inEncode, outEncode])
- mode `<String>`
- data `<String>` | `<Buffer>`
- key `<String>` 可选
- key `<String>` 可选, 默认为 `<Buffer 0 0 0 ... 0>`, 即 `Buffer.alloc(16)` 的结果
- inEncode '<String>' 可选
- outEncode '<String>' 可选默认base64
- outEncode '<String>' 可选默认返回Buffer对象
> `crypto.js v3.x`开始, `cipher()`内部改成调用 `cipheriv()`, 如果有特别原因, 仍然要调用的话, 请使用 `2.x版本`
> `mode`为算法类型,常见的有`aes-128-cbc、aes-128-gcm`等等地,很多,具体有哪些可以通过 `this.crypto.getCiphers()` 来查看。
> 其他的参数与上面的HMAC算法相似; `inEncode`即声明要加密的数据是什么编码的,默认根据要加密的数据进行判断。
```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
// v3.x 之后, decipher()同理
crypto.cipher('aes-128-cbc', '123456', {key})
// 等价于
crypto.cipheriv('aes-128-cbc', '123456', {key}, EMPTY_IV) // 其中 EMPTY_IV = Buffer.alloc(16)
```
#### decipher(mode, data[, key][, inEncode][, outEncode])
#### decipher(mode, data[, key, tag, inEncode, outEncode])
- mode `<String>`
- data `<String>` | `<Buffer>`
- key `<String>` 可选
- tag `<Buffer>` 可选(mode为gcm算法时必填)
- inEncode '<String>' 可选, 默认是base64
- outEncode '<String>' 可选默认utf8
> 这是与上面的`cipher`对应的解密方法;
>> Nodejs v10.0之后该方法为Deprecated, 推荐使用 decipheriv()
```javascript
// 这里不用指定编码默认即为base64
crypto.decipher('aes-128-cbc', 'mqA9ZPh9VV+fwKlfpicGVg==', 'abcdefg')
@ -211,9 +315,12 @@ crypto.decipher('aes-128-cbc', 'mqA9ZPh9VV+fwKlfpicGVg==', 'abcdefg')
// 这里一定要指定因为之前加密的时候指定输出为hex所以这里也要指定输入的是hex编码
crypto.decipher('aes-128-cbc', '9aa03d64f87d555f9fc0a95fa6270656', 'abcdefg', 'hex')
//123456
// 123456
```
> 至于另外的`cipheriv/decipheriv`这2个方法这里就不细讲了和上面的这2个是同样的用法只是要多1个参数`向量(iv)`, **`特别要注意的一点是选择128位的加密算法那key的长度就必须是16位256则是32位依此类推; 向量iv是16位`,具体的请看相关文档**
> 至于另外的`cipheriv/decipheriv`这2个方法这里就不细讲了和上面的这2个是同样的用法只是要多1个参数`向量(iv)`
>> **`特别要注意的一点是选择128位的加密算法那key的长度就必须是16位256则是32位依此类推`,具体的请看相关文档**

26
build.js Normal file
View File

@ -0,0 +1,26 @@
/**
* {build}
* @author yutent<yutent.io@gmail.com>
* @date 2021/08/09 11:59:41
*/
import Es from 'esbuild'
import fs from 'iofs'
Es.build({
entryPoints: ['src/index.js'],
outfile: 'dist/index.mjs',
platform: 'node',
bundle: true,
minify: true,
format: 'esm'
})
Es.build({
entryPoints: ['src/index.js'],
outfile: 'dist/index.js',
platform: 'node',
bundle: true,
minify: true
})
fs.cp('src/index.d.ts', 'dist/index.d.ts')

224
index.js
View File

@ -1,224 +0,0 @@
/**
* 加密类 md5/sha1/base64
* @authors yutent (yutent@doui.cc)
* @date 2015-09-10 13:56:18
*/
'use strict'
const CRYPTO = require('crypto')
const FS = require('fs')
module.exports = {
origin: CRYPTO,
__stamp__: '',
__inc__: 0,
hash(mode, data, outEncode) {
let sum = CRYPTO.createHash(mode)
let isBuffer = Buffer.isBuffer(data)
sum.update(data, isBuffer ? 'binary' : 'utf8')
return sum.digest(outEncode || 'hex')
},
hmac(mode, data, key, outEncode) {
key = key || ''
let sum = CRYPTO.createHmac(mode, key)
let isBuffer = Buffer.isBuffer(data)
sum.update(data, isBuffer ? 'binary' : 'utf8')
return sum.digest(outEncode || 'hex')
},
cipher(mode, data, key, inEncode, outEncode) {
key = key || ''
let isBuffer = Buffer.isBuffer(data)
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)
},
decipher(mode, data, key, 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)
},
cipheriv(mode, data, key, iv, inEncode, outEncode) {
key = key || '0000000000000000'
iv = iv || ''
let isBuffer = Buffer.isBuffer(data)
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)
},
decipheriv(mode, data, key, iv, 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)
},
/**
* [rand 生成指定长度的随机字符串]
* @param {[type]} len [要得到的字符串长度]
* @param {[type]} forceNum [是否强制返回纯数字]
*/
rand(len, forceNum) {
let str = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789'
if (forceNum) {
str = '0123456789'
}
let max = str.length
let tmp = ''
for (let i = 0; i < len; i++) {
let r = Math.floor(Math.random() * max)
tmp += str[r]
}
return tmp
},
// 返回一个如下格式的 xxxxxxxx-xxxx-xxxx-xxxxxxxx 的唯一ID
uuid() {
let rand = CRYPTO.randomBytes(8).toString('hex')
let now = (Date.now() / 1000).toString(16).slice(0, 8)
if (this.__stamp__ === now) {
this.__inc__++
} else {
this.__stamp__ = now
this.__inc__ = 0
}
rand = this.__inc__.toString(16) + rand
rand = rand.slice(0, 4) + '-' + rand.slice(4, 8) + '-' + rand.slice(8, 16)
return this.__stamp__ + '-' + rand
},
/**
* [md5 md5加密]
* @param {Str/Num} str [要加密的字符串]
* @param {Str} encode [hex/base64]
*/
md5(str, encode) {
if (typeof str !== 'string' && typeof str !== 'number') {
return str
}
return this.hash('md5', str + '', encode)
},
/**
* [md5Sign 获取文件的md5签名]
* @param {Str} file [文件路径]
*/
md5Sign(file) {
if (!fs.existsSync(file)) {
return null
}
let fileStream = fs.readFileSync(file)
return this.hash('md5', fileStream)
},
/**
* [sha1 sha1加密]
* @param {Str/Num} str [要加密的字符串]
* @param {Str} encode [hex/base64]
*/
sha1(str, encode) {
if (typeof str !== 'string' && typeof str !== 'number') {
return str
}
return this.hash('sha1', str + '', encode)
},
/**
* [sha1Sign 获取文件的sha1签名]
* @param {Str} file [文件路径]
*/
sha1Sign(file) {
if (!fs.existsSync(file)) {
return null
}
let fileStream = fs.readFileSync(file)
return this.hash('sha1', fileStream)
},
/**
* [sha256 sha256加密]
* @param {Str/Num} str [要加密的字符串]
* @param {Str} encoding [hex/base64]
*/
sha256(str, encoding) {
if (typeof str !== 'string' && typeof str !== 'number') {
return str
}
return this.hash('sha256', str + '', encoding)
},
/**
* [base64encode base64加密]
* @param {Str/Num/Buffer} str [要加密的字符串]
* @param {bool} urlFriendly [是否对URL友好默认否是则会把+转成-/转成_]
*/
base64encode(str, urlFriendly) {
if (!Buffer.isBuffer(str)) {
str = Buffer.from(str + '')
}
let encode = str.toString('base64')
if (urlFriendly) {
encode = encode
.replace(/[+\/]/g, m => {
return m === '+' ? '-' : '_'
})
.replace(/=/g, '')
}
return encode
},
/**
* [base64decode base64解密]
* @param {Str} str [要解密的字符串]
* @param {bool} urlFriendly [之前是否对结果采用了URL友好处理]
* @param {Str/Buffer} encoding [编码默认utf-8]
*/
base64decode(str, urlFriendly, encoding) {
if (urlFriendly) {
str = str
.replace(/[-_]/g, m => {
return m === '-' ? '+' : '/'
})
.replace(/[^A-Za-z0-9\+\/]/g, '')
}
let buff = Buffer.from(str, 'base64')
if (encoding === 'buffer') {
return buff
}
return buff.toString(encoding || 'ascii')
}
}

View File

@ -1,17 +1,36 @@
{
"name": "crypto.js",
"version": "1.1.3",
"type": "module",
"version": "3.3.4",
"description": "原生crypto加密模块的二次封装,简化常用加密函数的使用",
"keywords": [
"md5",
"sha1",
"sha256",
"hmac",
"aes",
"base64",
"fivejs",
"crypto"
"crypto",
"crypto-js",
"crypto.js"
],
"author": "yutent <yutent@doui.cc>",
"repository": { "type": "git", "url": "https://github.com/yutent/crypto.js.git" },
"dependencies": {},
"devDependencies": {},
"main": "index.js"
"author": "yutent <yutent.io@gmail.com>",
"repository": {
"type": "git",
"url": "https://git.wkit.fun/bytedo/crypto.js.git"
},
"license": "MIT",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist/*"
],
"scripts": {
"start": "node ./build.js"
},
"exports": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
}
}

174
src/helper.js Normal file
View File

@ -0,0 +1,174 @@
import crypto from 'crypto'
const AUTH_MODE = [
'aes-128-gcm',
'aes-192-gcm',
'aes-256-gcm',
'aes-128-ccm',
'aes-192-ccm',
'aes-256-ccm',
'aes-128-ocb',
'aes-192-ocb',
'aes-256-ocb'
]
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)
}
//
if (!crypto.randomUUID) {
crypto.randomUUID = function () {
let str = crypto.randomBytes(16).toString('hex')
return (
str.slice(0, 8) +
'-' +
str.slice(8, 12) +
'-' +
str.slice(12, 16) +
'-' +
str.slice(16, 20) +
'-' +
str.slice(-12)
)
}
}
if (!crypto.randomInt) {
crypto.randomInt = function (max) {
if (max === void 0) {
throw new TypeError(
'[ERR_INVALID_ARG_TYPE]: The "max" argument must be a safe integer. Received undefined'
)
}
return ~~(Math.random() * max)
}
}
export { crypto }
export const hash = function (mode, data, outEncode) {
let sum = crypto.createHash(mode)
let isBuffer = Buffer.isBuffer(data)
sum.update(data, isBuffer ? 'buffer' : 'utf8')
return sum.digest(outEncode || 'hex')
}
export const hmac = function (mode, data, key, outEncode) {
key = key || ''
let sum = crypto.createHmac(mode, key)
let isBuffer = Buffer.isBuffer(data)
sum.update(data, isBuffer ? 'buffer' : 'utf8')
return sum.digest(outEncode || 'hex')
}
export const cipher = function (
mode,
data,
key = KEY_16,
inEncode = 'utf8',
outEncode
) {
// 10.0.0之后, createCipher方法不推荐使用了
if (VERSION >= 10.5) {
return cipheriv(mode, data, key, KEY_16, inEncode, outEncode)
}
let isBuffer = Buffer.isBuffer(data)
inEncode = isBuffer ? 'buffer' : inEncode
let _cipher = crypto.createCipher(mode, key)
let buff = _cipher.update(data, inEncode)
buff = Buffer.concat([buff, _cipher.final()])
if (AUTH_MODE.indexOf(mode) > -1) {
buff = Buffer.concat([buff, _cipher.getAuthTag()])
}
return format(buff, outEncode)
}
export const decipher = function (
mode,
data,
key = KEY_16,
inEncode = 'base64',
outEncode = 'utf8'
) {
// 10.0.0之后, createCipher方法不推荐使用了
if (VERSION >= 10.5) {
return decipheriv(mode, data, key, KEY_16, inEncode, outEncode)
}
let isBuffer = Buffer.isBuffer(data)
if (!isBuffer) {
data = Buffer.from(data, inEncode)
}
inEncode = 'buffer'
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 (
mode,
data,
key = KEY_16,
iv = KEY_16,
inEncode = 'utf8',
outEncode
) {
let isBuffer = Buffer.isBuffer(data)
inEncode = isBuffer ? 'buffer' : inEncode
let _cipher = crypto.createCipheriv(mode, key, iv)
let buff = _cipher.update(data, inEncode)
buff = Buffer.concat([buff, _cipher.final()])
if (AUTH_MODE.indexOf(mode) > -1) {
buff = Buffer.concat([buff, _cipher.getAuthTag()])
}
return format(buff, outEncode)
}
export const decipheriv = function (
mode,
data,
key = KEY_16,
iv = KEY_16,
inEncode = 'base64',
outEncode = 'utf8'
) {
let isBuffer = Buffer.isBuffer(data)
if (!isBuffer) {
data = Buffer.from(data, inEncode)
}
inEncode = 'buffer'
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)
}

96
src/index.d.ts vendored Normal file
View File

@ -0,0 +1,96 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2024/12/12 15:41:25
*/
declare module 'crypto.js' {
import crypto from 'node:crypto'
// 原生 crypto 模块
export { crypto }
/**
* @deprecated Use `crypto` instead.
*/
export const origin: typeof crypto
// 随机数生成
export function rand(len: number, forceNum?: boolean): string
// 生成唯一 uuid
export function uuid(pipe?: string): string
export function base64encode(str: string, urlFriendly?: boolean): string
export function base64decode(str: string, urlFriendly?: boolean): string
export function md5(data: string, encode?: string): string | Buffer
export function md5Sign(path: string, encode?: string): string | Buffer
export function sha1(data: string, encode?: string): string | Buffer
export function sha1Sign(path: string, encode?: string): string | Buffer
export function sha256(data: string, encode?: string): string | Buffer
export function sha256Sign(path: string, encode?: string): string | Buffer
export function sha512(data: string, encode?: string): string | Buffer
export function sha512Sign(path: string, encode?: string): string | Buffer
//
export function hash(
mode: string,
data: string | Buffer,
outEncode?: string
): string | Buffer
//
export function hmac(
mode: string,
data: string | Buffer,
key: string | Buffer,
outEncode?: string
): string | Buffer
//
export function cipher(
mode: string,
data: string | Buffer,
key: string | Buffer,
inEncode?: string,
outEncode?: string
): string | Buffer
//
export function decipher(
mode: string,
data: string | Buffer,
key: string | Buffer,
inEncode?: string,
outEncode?: string
): string | Buffer
//
export function cipheriv(
mode: string,
data: string | Buffer,
key: string | Buffer,
iv: string | Buffer,
inEncode?: string,
outEncode?: string
): string | Buffer
//
export function decipheriv(
mode: string,
data: string | Buffer,
key: string | Buffer,
iv: string | Buffer,
inEncode?: string,
outEncode?: string
): string | Buffer
}

252
src/index.js Normal file
View File

@ -0,0 +1,252 @@
/**
* 加密类 md5/sha1/base64
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/16 18:11:51
*/
import os from 'os'
import fs from 'fs'
import {
crypto,
hash,
hmac,
cipher,
decipher,
cipheriv,
decipheriv
} from './helper.js'
const MAC = (function (ns) {
for (let k in ns) {
if (k === 'lo') {
continue
}
let _ = ns[k].pop()
return _.mac.replace(/:/g, '').slice(-4)
}
return Math.random().toString(16).slice(-4)
})(os.networkInterfaces())
let __inc__ = 4096
/**
* [base64encode base64编码]
* @param {Str/Num/Buffer} str [要编码的字符串]
* @param {bool} urlFriendly [是否对URL友好, 默认否, 是则会把+转成-, /_]
*/
export function base64encode(str, urlFriendly) {
let buf, str64
if (Buffer.isBuffer(str)) {
buf = str
} else {
buf = Buffer.from(str + '')
}
str64 = buf.toString('base64')
if (urlFriendly) {
return str64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
}
return str64
}
/**
* [base64decode base64解码, 返回Buffer对象]
* @param {Str} str [要解码的字符串]
* @param {bool} urlFriendly [之前是否对结果采用了URL友好处理]
*/
export function base64decode(str, urlFriendly) {
if (urlFriendly) {
str = str
.replace(/-/g, '+')
.replace(/_/g, '/')
.replace(/[^A-Za-z0-9\+\/]/g, '')
}
return Buffer.from(str, 'base64')
}
/**
* [rand 生成指定长度的随机字符串]
* @param {[type]} len [要得到的字符串长度]
* @param {[type]} forceNum [是否强制返回纯数字]
*/
export function rand(len = 0, forceNum = false) {
let str = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789'
if (forceNum) {
str = '0123456789'
}
let max = str.length
let tmp = ''
for (let i = 0; i < len; i++) {
tmp += str[crypto.randomInt(max)]
}
return tmp
}
// 返回一个如下格式的 xxxxxxxx-xxxx-xxxx-xxxxxxxx 的唯一ID
export function uuid(pipe = '-') {
let str = crypto.randomUUID()
let now = (~~(Date.now() / 1000)).toString(16)
if (__inc__ > 65535) {
__inc__ = 4096
}
str = __inc__.toString(16) + str
__inc__++
return now + pipe + MAC + pipe + str.slice(0, 4) + pipe + str.slice(-8)
}
/**
* [md5 md5加密]
* @param {Str/Num} str [要加密的字符串]
* @param {Str} encode [hex/base64]
*/
export function md5(str, encode) {
if (typeof str === 'number') {
str += ''
}
if (typeof str === 'string' || Buffer.isBuffer(str)) {
return hash('md5', str, encode)
}
return str
}
/**
* [md5Sign 获取文件的md5签名]
* @param {Str} file [文件路径]
* @param {Str} encode [hex/base64]
*/
export function md5Sign(file, encode) {
try {
let buf = fs.readFileSync(file)
return hash('md5', buf, encode)
} catch (e) {
return null
}
}
/**
* [sha1 sha1加密]
* @param {Str/Num} str [要加密的字符串]
* @param {Str} encode [hex/base64]
*/
export function sha1(str, encode) {
if (typeof str === 'number') {
str += ''
}
if (typeof str === 'string' || Buffer.isBuffer(str)) {
return hash('sha1', str, encode)
}
return str
}
/**
* [sha1Sign 获取文件的sha1签名]
* @param {Str} file [文件路径]
*/
export function sha1Sign(file, encode) {
try {
let buf = fs.readFileSync(file)
return hash('sha1', buf, encode)
} catch (e) {
return null
}
}
/**
* [sha256 sha256加密]
* @param {Str/Num} str [要加密的字符串]
* @param {Str} encode [hex/base64]
*/
export function sha256(str, encode) {
if (typeof str === 'number') {
str += ''
}
if (typeof str === 'string' || Buffer.isBuffer(str)) {
return hash('sha256', str, encode)
}
return str
}
/**
* [sha256Sign 获取文件的sha256签名]
* @param {Str} file [文件路径]
*/
export function sha256Sign(file, encode) {
try {
let buf = fs.readFileSync(file)
return hash('sha256', buf, encode)
} catch (e) {
return null
}
}
/**
* [sha512 sha512加密]
* @param {Str/Num} str [要加密的字符串]
* @param {Str} encode [hex/base64]
*/
export function sha512(str, encode) {
if (typeof str === 'number') {
str += ''
}
if (typeof str === 'string' || Buffer.isBuffer(str)) {
return hash('sha512', str, encode)
}
return str
}
/**
* [sha512Sign 获取文件的sha512签名]
* @param {Str} file [文件路径]
*/
export function sha512Sign(file, encode) {
try {
let buf = fs.readFileSync(file)
return hash('sha512', buf, encode)
} catch (e) {
return null
}
}
export {
crypto,
crypto as origin,
hash,
hmac,
cipher,
decipher,
cipheriv,
decipheriv
}
export default {
base64encode,
base64decode,
rand,
uuid,
md5,
md5Sign,
sha1,
sha1Sign,
sha256,
sha256Sign,
sha512,
sha512Sign,
crypto,
origin: crypto,
hash,
hmac,
cipher,
decipher,
cipheriv,
decipheriv
}

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))