|
|
|
const {KJUR, hextob64} = require('jsrsasign')
|
|
|
|
|
|
|
|
const HashMap = {
|
|
|
|
SHA256withRSA: 'SHA256withRSA',
|
|
|
|
SHA1withRSA: 'SHA1withRSA'
|
|
|
|
}
|
|
|
|
|
|
|
|
const PEM_BEGIN = '-----BEGIN PRIVATE KEY-----\n'
|
|
|
|
const PEM_END = '\n-----END PRIVATE KEY-----'
|
|
|
|
|
|
|
|
/**
|
|
|
|
* rsa签名参考:https://www.jianshu.com/p/145eab95322c
|
|
|
|
*/
|
|
|
|
exports.SignUtil = {
|
|
|
|
/**
|
|
|
|
* 创建签名
|
|
|
|
* @param params 请求参数
|
|
|
|
* @param privateKey 私钥,PKCS8
|
|
|
|
* @param signType 签名类型,RSA,RSA2
|
|
|
|
* @returns 返回签名内容
|
|
|
|
*/
|
|
|
|
createSign(params, privateKey, signType) {
|
|
|
|
const content = this.getSignContent(params)
|
|
|
|
return this.sign(content, privateKey, signType)
|
|
|
|
},
|
|
|
|
sign: function (content, privateKey, signType) {
|
|
|
|
if (signType.toUpperCase() === 'RSA') {
|
|
|
|
return this.rsaSign(content, privateKey, HashMap.SHA1withRSA)
|
|
|
|
} else if (signType.toUpperCase() === 'RSA2') {
|
|
|
|
return this.rsaSign(content, privateKey, HashMap.SHA256withRSA)
|
|
|
|
} else {
|
|
|
|
throw 'signType错误'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* rsa签名
|
|
|
|
* @param content 签名内容
|
|
|
|
* @param privateKey 私钥
|
|
|
|
* @param hash hash算法,SHA256withRSA,SHA1withRSA
|
|
|
|
* @returns 返回签名字符串,base64
|
|
|
|
*/
|
|
|
|
rsaSign: function (content, privateKey, hash) {
|
|
|
|
privateKey = this._formatKey(privateKey)
|
|
|
|
// 创建 Signature 对象
|
|
|
|
const signature = new KJUR.crypto.Signature({
|
|
|
|
alg: hash,
|
|
|
|
//!这里指定 私钥 pem!
|
|
|
|
prvkeypem: privateKey
|
|
|
|
})
|
|
|
|
signature.updateString(content)
|
|
|
|
const signData = signature.sign()
|
|
|
|
// 将内容转成base64
|
|
|
|
return hextob64(signData)
|
|
|
|
},
|
|
|
|
_formatKey: function (key) {
|
|
|
|
if (!key.startsWith(PEM_BEGIN)) {
|
|
|
|
key = PEM_BEGIN + key
|
|
|
|
}
|
|
|
|
if (!key.endsWith(PEM_END)) {
|
|
|
|
key = key + PEM_END
|
|
|
|
}
|
|
|
|
return key
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* 获取签名内容
|
|
|
|
* @param params 请求参数
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
getSignContent: function (params) {
|
|
|
|
const paramNames = []
|
|
|
|
// 获取对象中的Key
|
|
|
|
paramNames.push(...Object.keys(params || {})
|
|
|
|
// 过滤无效的KeyValue
|
|
|
|
.filter(paramName => {
|
|
|
|
// 参数名不为undefined且参数值不为undefined
|
|
|
|
return !(typeof paramName === undefined || typeof params[paramName] === undefined)
|
|
|
|
}))
|
|
|
|
|
|
|
|
paramNames.sort()
|
|
|
|
|
|
|
|
// 合成签名字符串
|
|
|
|
const paramNameValue = paramNames.map(paramName => {
|
|
|
|
const val = params[paramName];
|
|
|
|
return `${paramName}=${val}`
|
|
|
|
})
|
|
|
|
|
|
|
|
return paramNameValue.join('&')
|
|
|
|
}
|
|
|
|
}
|