最近公司进行vue项目用到RSA签名,研究了一下网上的一些技术博客,发现都是千篇一律,而且实现原理示例代码都存在或多或少的问题所以自己写下这篇文章记录总结一下RSA加签、验签的方法,让像我这种开发小白少走弯路。
一、RSA签名的原理
RSA签名需要公钥和私钥,具体实现原理是:
1、A保留生成的私钥,将公钥留给B;
2、A用私钥将数据加签生成密文,传给B;
3、B接到数据用公钥将数据加签,生成密文与A传过来的密文进行对比,如果对比的结果一致,证明消息是A回复的。
二、vue项目中RSA加签、验签具体实现步骤
1、密钥的生成
密钥的生成有很多方法最简单的方法是直接在网上搜索 “RSA密钥生成”就可以找到专门生成RSA密钥的网站。而我这里介绍的是使用 支付宝 rsa 密钥生成工具 生成密钥 。如图:
2、签名规则
为了保证数据的严谨性需要对数据进行一下处理,比如排序,或者在数据后面加上一些你与后端约定的一些代码。如图:3、在VUE中使用jsrsasign进行签名
1、安装jsrsasign
jsrsasign官网
npm install jsrsasign --save
2、引入jsrsasign
因为我将加签、验签封装在了统一的jsrsasign.js文件中所以要在js文件中引用如下代码
import Vue from 'vue'
import jsrsasign, { KJUR, hextob64, b64utohex } from 'jsrsasign'
Vue.prototype.$jsrsasign = jsrsasign
3、加签
/**
* RSA加签
* @param {加签参数} signData
*/
export const RSAEncrypt = (signData) => {
let prk = '' //私钥
let signPrivateKey = '-----BEGIN PRIVATE KEY-----' + prk + '-----END PRIVATE KEY-----';
let data = signData
//ASCII排序 生成 bar=2&foo=1这种结构
function sortAsc (o) {
var n = [];
for (var k in o) n.push(k);
n.sort();
for (var i = 0, str = ''; i < n.length; i++) {
var v = o[n[i]];
if (v) {
if ({}.toString.call(v) == '[object Object]')
v = sortAsc(v);
else if ({}.toString.call(v) == '[object Array]')
v = JSON.stringify(v).replace(/:/g, '=');
}
str += '&' + n[i] + '=' + v;
}
return str.slice(1);
}
// 参数
let data1 = sortAsc(data) + 'zaq1' // sortAsc(data) 'zaq1'为与后端约定好的参数值
let sig = new KJUR.crypto.Signature({ "alg": "SHA1withRSA" });//创建sig对象并指定算法名称(SHA1withRSA)算法要与后端约定好
sig.init(signPrivateKey);//初始化实例
sig.updateString(data1)//更新签名数据
let sign = jsrsasign.hextob64(sig.sign())//签名得到十六进制密文
return sign
}
4、验签
/**
* RSA验签
* @param {加签的数据} signData
* @param {加签之后得到的签文} data
*/
export const RSADecrypt = (signData, data) => {
//ASCII排序 生成 bar=2&foo=1这种结构
function sortAsc (o) {
var n = [];
for (var k in o) n.push(k);
n.sort();
for (var i = 0, str = ''; i < n.length; i++) {
var v = o[n[i]];
if (v) {
if ({}.toString.call(v) == '[object Object]')
v = sortAsc(v);
else if ({}.toString.call(v) == '[object Array]')
v = JSON.stringify(v).replace(/:/g, '=');
}
str += '&' + n[i] + '=' + v;
}
return str.slice(1);
}
let newSign1 = sortAsc(signData) + 'zaq1'// 'zaq1'为与后端约定好的参数值
try {
let pk = ''//公钥
let signPublicKey = '-----BEGIN PUBLIC KEY-----' + pk + '-----END PUBLIC KEY-----';
let sig2 = new KJUR.crypto.Signature({ "alg": "SHA1withRSA" });//创建sig2对象并指定算法名称(SHA1withRSA)
sig2.init(signPublicKey);//初始化实例
sig2.updateString(newSign1);//更新签名数据
let result = sig2.verify(b64utohex(data));//进行十六进制字符串的验签
return result;
} catch (e) {
console.error(e);
}
}
以上便是我对RSA加签验签的小结,希望可以帮助到需要的人。