2018-05-25 00:09:29 +08:00
|
|
|
|
/**
|
|
|
|
|
* 加密类 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')
|
2019-01-15 18:05:09 +08:00
|
|
|
|
const GCM_MODE = ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm']
|
2018-05-25 00:09:29 +08:00
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
origin: CRYPTO,
|
2018-07-02 01:53:02 +08:00
|
|
|
|
__stamp__: '',
|
|
|
|
|
__inc__: 0,
|
2018-05-25 00:09:29 +08:00
|
|
|
|
|
|
|
|
|
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'
|
|
|
|
|
|
2019-01-15 18:05:09 +08:00
|
|
|
|
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
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
2019-01-15 18:05:09 +08:00
|
|
|
|
decipher(mode, data, key, tag, inEncode, outEncode) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
key = key || ''
|
|
|
|
|
let isBuffer = Buffer.isBuffer(data)
|
|
|
|
|
inEncode = isBuffer ? 'binary' : inEncode || 'base64'
|
|
|
|
|
outEncode = outEncode || 'utf8'
|
|
|
|
|
|
2019-01-15 18:05:09 +08:00
|
|
|
|
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
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
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'
|
|
|
|
|
|
2019-01-15 18:05:09 +08:00
|
|
|
|
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
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
2019-01-15 18:05:09 +08:00
|
|
|
|
decipheriv(mode, data, key, iv, tag, inEncode, outEncode) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
key = key || '0000000000000000'
|
|
|
|
|
iv = iv || ''
|
|
|
|
|
let isBuffer = Buffer.isBuffer(data)
|
|
|
|
|
inEncode = isBuffer ? 'binary' : inEncode || 'base64'
|
|
|
|
|
outEncode = outEncode || 'utf8'
|
|
|
|
|
|
2019-01-15 18:05:09 +08:00
|
|
|
|
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
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* [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
|
2019-06-17 17:11:53 +08:00
|
|
|
|
uuid(line = true) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
let rand = CRYPTO.randomBytes(8).toString('hex')
|
2018-07-02 01:53:02 +08:00
|
|
|
|
let now = (Date.now() / 1000).toString(16).slice(0, 8)
|
2019-06-17 17:11:53 +08:00
|
|
|
|
|
|
|
|
|
let pipe = line ? '-' : ''
|
2018-07-02 01:53:02 +08:00
|
|
|
|
if (this.__stamp__ === now) {
|
|
|
|
|
this.__inc__++
|
|
|
|
|
} else {
|
|
|
|
|
this.__stamp__ = now
|
|
|
|
|
this.__inc__ = 0
|
|
|
|
|
}
|
|
|
|
|
rand = this.__inc__.toString(16) + rand
|
2018-05-25 00:09:29 +08:00
|
|
|
|
|
2019-06-17 17:11:53 +08:00
|
|
|
|
return (
|
|
|
|
|
this.__stamp__ +
|
|
|
|
|
pipe +
|
|
|
|
|
rand.slice(0, 4) +
|
|
|
|
|
pipe +
|
|
|
|
|
rand.slice(4, 8) +
|
|
|
|
|
pipe +
|
|
|
|
|
rand.slice(8, 16)
|
|
|
|
|
)
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* [md5 md5加密]
|
|
|
|
|
* @param {Str/Num} str [要加密的字符串]
|
|
|
|
|
* @param {Str} encode [hex/base64]
|
|
|
|
|
*/
|
|
|
|
|
md5(str, encode) {
|
2018-10-08 12:22:48 +08:00
|
|
|
|
if (typeof str === 'number') {
|
|
|
|
|
str += ''
|
|
|
|
|
}
|
|
|
|
|
if (typeof str !== 'string' && !Buffer.isBuffer(str)) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 12:22:48 +08:00
|
|
|
|
return this.hash('md5', str, encode)
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* [md5Sign 获取文件的md5签名]
|
|
|
|
|
* @param {Str} file [文件路径]
|
|
|
|
|
*/
|
|
|
|
|
md5Sign(file) {
|
2018-12-23 17:21:58 +08:00
|
|
|
|
if (!FS.existsSync(file)) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-23 17:21:58 +08:00
|
|
|
|
let fileStream = FS.readFileSync(file)
|
2018-05-25 00:09:29 +08:00
|
|
|
|
return this.hash('md5', fileStream)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* [sha1 sha1加密]
|
|
|
|
|
* @param {Str/Num} str [要加密的字符串]
|
|
|
|
|
* @param {Str} encode [hex/base64]
|
|
|
|
|
*/
|
|
|
|
|
sha1(str, encode) {
|
2018-10-08 12:22:48 +08:00
|
|
|
|
if (typeof str === 'number') {
|
|
|
|
|
str += ''
|
|
|
|
|
}
|
|
|
|
|
if (typeof str !== 'string' && !Buffer.isBuffer(str)) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 12:22:48 +08:00
|
|
|
|
return this.hash('sha1', str, encode)
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* [sha1Sign 获取文件的sha1签名]
|
|
|
|
|
* @param {Str} file [文件路径]
|
|
|
|
|
*/
|
|
|
|
|
sha1Sign(file) {
|
2018-12-23 17:21:58 +08:00
|
|
|
|
if (!FS.existsSync(file)) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-23 17:21:58 +08:00
|
|
|
|
let fileStream = FS.readFileSync(file)
|
2018-05-25 00:09:29 +08:00
|
|
|
|
return this.hash('sha1', fileStream)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* [sha256 sha256加密]
|
|
|
|
|
* @param {Str/Num} str [要加密的字符串]
|
|
|
|
|
* @param {Str} encoding [hex/base64]
|
|
|
|
|
*/
|
|
|
|
|
sha256(str, encoding) {
|
2018-10-08 12:22:48 +08:00
|
|
|
|
if (typeof str === 'number') {
|
|
|
|
|
str += ''
|
|
|
|
|
}
|
|
|
|
|
if (typeof str !== 'string' && !Buffer.isBuffer(str)) {
|
2018-05-25 00:09:29 +08:00
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 12:22:48 +08:00
|
|
|
|
return this.hash('sha256', str, encoding)
|
2018-05-25 00:09:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
2019-06-17 17:11:53 +08:00
|
|
|
|
/**
|
|
|
|
|
* [sha256Sign 获取文件的sha256签名]
|
|
|
|
|
* @param {Str} file [文件路径]
|
|
|
|
|
*/
|
|
|
|
|
sha256Sign(file) {
|
|
|
|
|
if (!FS.existsSync(file)) {
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let fileStream = FS.readFileSync(file)
|
|
|
|
|
return this.hash('sha256', fileStream)
|
|
|
|
|
},
|
|
|
|
|
|
2018-05-25 00:09:29 +08:00
|
|
|
|
/**
|
|
|
|
|
* [base64encode base64加密]
|
|
|
|
|
* @param {Str/Num/Buffer} str [要加密的字符串]
|
|
|
|
|
* @param {bool} urlFriendly [是否对URL友好,默认否,是则会把+转成-,/转成_]
|
|
|
|
|
*/
|
|
|
|
|
base64encode(str, urlFriendly) {
|
2019-03-08 19:04:42 +08:00
|
|
|
|
let buf
|
2018-05-25 00:09:29 +08:00
|
|
|
|
if (!Buffer.isBuffer(str)) {
|
2019-03-08 19:04:42 +08:00
|
|
|
|
buf = Buffer.from(str + '')
|
2018-05-25 00:09:29 +08:00
|
|
|
|
}
|
2019-03-08 19:04:42 +08:00
|
|
|
|
let encode = buf.toString('base64')
|
2018-05-25 00:09:29 +08:00
|
|
|
|
if (urlFriendly) {
|
2018-08-31 14:12:50 +08:00
|
|
|
|
return encode
|
|
|
|
|
.replace(/\+/g, '-')
|
|
|
|
|
.replace(/\//g, '_')
|
2018-05-25 00:09:29 +08:00
|
|
|
|
.replace(/=/g, '')
|
|
|
|
|
}
|
|
|
|
|
return encode
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
2019-03-08 19:04:42 +08:00
|
|
|
|
* [base64decode base64解密, 返回Buffer对象]
|
2018-05-25 00:09:29 +08:00
|
|
|
|
* @param {Str} str [要解密的字符串]
|
|
|
|
|
* @param {bool} urlFriendly [之前是否对结果采用了URL友好处理]
|
|
|
|
|
*/
|
|
|
|
|
base64decode(str, urlFriendly, encoding) {
|
|
|
|
|
if (urlFriendly) {
|
|
|
|
|
str = str
|
2018-08-31 14:12:50 +08:00
|
|
|
|
.replace(/-/g, '+')
|
|
|
|
|
.replace(/_/g, '/')
|
2018-05-25 00:09:29 +08:00
|
|
|
|
.replace(/[^A-Za-z0-9\+\/]/g, '')
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-08 19:04:42 +08:00
|
|
|
|
return Buffer.from(str, 'base64')
|
2018-05-25 00:09:29 +08:00
|
|
|
|
}
|
|
|
|
|
}
|