RSA概述
1978年出现了著名的RSA算法,它通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。
RSA允许你选择公钥的大小。512位的密钥被视为不安全的;768位的密钥不用担心受到除了国家安全管理(NSA)外的其他事物的危害;1024位的密钥几乎是安全的。RSA在一些主要产品内部都有嵌入,像 Windows、网景 Navigator、 Quicken和 Lotus Notes
vue RSA使用jsrsasign
vue RSA使用的库是jsrsasign
jsrsasign(RSA-Sign JavaScript库)是一个免费的开源加密库,支持RSA / RSAPSS / ECDSA / DSA签名/验证,ASN.1,PKCS#1/5/8私钥/公钥,X.509证书,纯JavaScript中的CRL,OCSP,CMS SignedData,TimeStamp,CAdES JSON Web签名/令牌/密钥。
官网给出的 每月600万次的下载
very popular crypto library with 0.6M+ npm downloads/month
可见其相当受欢迎,但直接百度的话国内相关做说明这个的还是比较少的,还好官网描述的比较细致。
官网描述
http://kjur.github.io/jsrsasign/
秘钥格式化 KEYUTIL
类字段说明:
专门用来格式化 PKCS5PKEY 的类
方法说明:
主要会用到三个方法:
KEYUTIL.generateKeypair 生成key
KEYUTIL.getKey 获得RSA 的key
KEYUTIL.getPEM 获得DES 的key
支持的方法:
秘钥加载示例
秘钥生成
var rsaKeypair = KEYUTIL.generateKeypair("RSA", 1024);
var ecKeypair = KEYUTIL.generateKeypair("EC", "secp256r1");
秘钥加载
// 1. loading PEM private key
var key = KEYUTIL.getKey(pemPKCS1PrivateKey);
var key = KEYUTIL.getKey(pemPKCS5EncryptedPrivateKey, "passcode");
var key = KEYUTIL.getKey(pemPKCS5PlainRsaDssEcPrivateKey);
var key = KEYUTIL.getKey(pemPKC85PlainPrivateKey);
var key = KEYUTIL.getKey(pemPKC85EncryptedPrivateKey, "passcode");
// 2. loading PEM public key
var key = KEYUTIL.getKey(pemPKCS8PublicKey);
var key = KEYUTIL.getKey(pemX509Certificate);
// 3. exporting private key
var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS1PRV");
var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS5PRV", "passcode"); // DES-EDE3-CBC by default
var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS5PRV", "passcode", "DES-CBC");
var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS8PRV");
var pem = KEYUTIL.getPEM(privateKeyObj, "PKCS8PRV", "passcode");
// 4. exporting public key
var pem = KEYUTIL.getPEM(publicKeyObj);
签名 Signature
类字段说明:
Signature class which is very similar to java.security.Signature class
As for params of constructor's argument, it can be specify following attributes:
翻译:
加签的类和java.security.Signature 类非常相似,至于构造函数参数的params,可以指定以下属性:
alg-签名算法名称
此签名对象的当前状态是“ SIGN”,“ VERIFY”还是null
支持的算法:
这里的算法参数填写格式是
alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}with{RSA,ECDSA,DSA})
散列算法名+with+公开秘钥算法名
方法说明:
方法主要有
init 初始化
sign 加签
verify 验签
加签验签示例:
// RSA signature generation
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
sig.init(prvKeyPEM);
sig.updateString('aaa');
var hSigVal = sig.sign();
// DSA signature validation
var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"});
sig2.init(certPEM);
sig.updateString('aaa');
var isValid = sig2.verify(hSigVal);
// ECDSA signing
var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
sig.init(prvKeyPEM);
sig.updateString('aaa');
var sigValueHex = sig.sign();
// ECDSA verifying
var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
sig.init(certPEM);
sig.updateString('aaa');
var isValid = sig.verify(sigValueHex);
加密 Cipher
类说明
加密和解密数据的密码类,这个类与java的javax.crypto.Cipher 类 类似,方法也比较简单
支持的算法:
这里支持规范化的密码算法名称及其标准名称:
RSA-RSA / ECB / PKCS1Padding(RSAKey的默认设置)
RSAOAEP-RSA / ECB / OAEPWithSHA-1AndMGF1Padding
RSAOAEP224-RSA / ECB / OAEPWithSHA-224AndMGF1Padding(*)
RSAOAEP256-RSA / ECB / OAEPWithSHA-256AndMGF1Padding
RSAOAEP384-RSA / ECB / OAEPWithSHA-384AndMGF1Padding(*)
RSAOAEP512-RSA / ECB / OAEPWithSHA-512AndMGF1Padding(*)
方法说明:
方法主要有:
decrypt 解密
encrypt 加密
getAlgByKeyAndName 根据秘钥获取加密算法
加密解密示例:
加密
KJUR.crypto.Cipher.encrypt("aaa", pubRSAKeyObj) → "1abc2d..."
KJUR.crypto.Cipher.encrypt("aaa", pubRSAKeyObj, "RSAOAEP") → "23ab02..."
解密
KJUR.crypto.Cipher.decrypt("aaa", prvRSAKeyObj) → "1abc2d..."
KJUR.crypto.Cipher.decrypt("aaa", prvRSAKeyObj, "RSAOAEP) → "23ab02..."
获取算法
KJUR.crypto.Cipher.getAlgByKeyAndName(objRSAKey) → "RSA"
KJUR.crypto.Cipher.getAlgByKeyAndName(objRSAKey, "RSAOAEP") → "RSAOAEP"
方法封装
私钥加签
// 私钥加签
export function signature(signData) {
// console.log("jsutil:"+jsrsasignUtil.readFileHexByBin("./pri.key"));
// 创建秘钥实例
var key = jsrsasign.KEYUTIL.getKey(priK);
// 指定签名算法 sha1对原文哈希
let signature = new jsrsasign.KJUR.crypto.Signature({ alg: "SHA1withRSA" });
// 传入秘钥实例, 初始化
signature.init(key);
// 传入待签明文
signature.updateString(signData);
// 签名, 得到16进制字符结果
let signResult = signature.sign();
// 签名hex转base64
let signBase64 = jsrsasign.hextob64(signResult);
// console.log(signBase64);
return signBase64;
}
公钥验签
// 验签
export function verify(signData, data) {
// signData: 加签的数据
// data: 加签之后得到的签文
try {
// 验签
let signatureVf = new jsrsasign.KJUR.crypto.Signature({ alg: "SHA1withRSA", prvkeypem: pubk });
signatureVf.updateString(data);
let result = signatureVf.verify(jsrsasign.b64tohex(signData));
console.log("jsrsasign verify: " + result);
return result;
} catch (e) {
console.error(e);
}
}
公钥加密
// 加密
export function encrypt(encryptData) {
// 读取解析pem格式的秘钥, 生成秘钥实例 (RSAKey)
var pub = jsrsasign.KEYUTIL.getKey(pubk);
var enc = jsrsasign.KJUR.crypto.Cipher.encrypt(encryptData, pub);
console.log("jsrsasign decrypt: " + enc);
console.log("jsrsasign hextob64: " + jsrsasign.hextob64(enc));
return jsrsasign.hextob64(enc);
}
私钥解密
// 解密
export function decrypt(decryptData) {
var prv = jsrsasign.KEYUTIL.getKey(priK);
var dec = jsrsasign.KJUR.crypto.Cipher.decrypt(jsrsasign.b64utohex(decryptData), prv);
console.log("jsrsasign decrypt: " + dec);
console.log("jsrsasign b64utohex: " + jsrsasign.b64utohex(dec));
return dec;
}
方法使用
登录时引入加密解密
import { encrypt, decrypt } from '@/utils/crypt/jsrsacrypt'
加密密码
Cookies.set("password", encrypt(this.ruleForm.password), { expires: 30 });
解密密码
password: password === undefined ? this.ruleForm.password : decrypt(password),
与DES相结合
DES生成的秘钥用RSA加密,报文拼装完后整个使用RSA进行加签
扩展RSA相关
API http://kjur.github.io/jsrsasign/api/index.html
简书大佬 https://www.jianshu.com/p/b32fc387d8ad