最近因项目需求,需要配合 JAVA 后端返回的签名,在 H5 网页中做验签功能。网上搜了一下发现了 jsrsasign 满足需求,所以顺便研究了一下 jsrsasign 。
首先去官网下载压缩包,解压后只需要引用其中的 jsrsasign-all-min.js 文件即可。
<!--引入jsrsasign.js-->
<script src="./jsrsasign-all-min.js"></script>
初始化一下公钥和私钥(实际可以根据业务需求只使用公钥或者私钥)
// 公钥
let pk="-----BEGIN PUBLIC KEY-----\n" +
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMF4B4aDnV6j+yXiiXBYJjHM8sEgRicQ\n" +
"TsRndPKocf4PyNTcd9D1046wRMdtV5cijT3oVzBXQYupN+VXmMiM7MMCAwEAAQ==\n" +
"-----END PUBLIC KEY-----";
// 私钥
let priK = "-----BEGIN PRIVATE KEY-----\n" +
"MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAwXgHhoOdXqP7JeKJ\n" +
"cFgmMczywSBGJxBOxGd08qhx/g/I1Nx30PXTjrBEx21XlyKNPehXMFdBi6k35VeY\n" +
"yIzswwIDAQABAkA+Zcj/kFlkGb05pcuwCS4gZ7pvoUoe9TqCS9/DF6LUTpFgsDlj\n" +
"6AiXRng6BzlWqdn7//E/+BIInuh7Wn0q/j0hAiEA4xrWytU7EFCfilvy63oXzem2\n" +
"um9fSqa4fksezyXtERECIQDaFZ0nIDdcACabh5JD7dEseqw85IMKUyfFNtLKaqog\n" +
"kwIgKvg5C8eslTmr9hHPtJ41QtClskDAVu+UmNC905PpdwECIQCv4u60N49ua9C3\n" +
"b0fP8WXacbWoBsSI9zgEHoszJYPAcQIhAIdENiYBXqHxVQByKZoRS4uG0UrRskxI\n" +
"zMnAPlDWNOap\n" +
"-----END PRIVATE KEY-----\n";
假设原文内容为如下:
// 原文
let src = "{我是测试明文}";
加密、解密套餐 ( 公钥加密,私钥解密 ):
// 加密
let pub = KEYUTIL.getKey(pk);
let enc = KJUR.crypto.Cipher.encrypt(src, pub);
console.log(`公钥加密结果:${enc}`);
// console.log(hextob64(enc));
// 解密
let prv = KEYUTIL.getKey(priK);
let dec = KJUR.crypto.Cipher.decrypt(enc, prv);
console.log(`私钥解密结果:${dec}`);
签名、验签套餐 ( 私钥签名,公钥验签 ):
// 签名
let signature=new KJUR.crypto.Signature({alg:"SHA1withRSA",prvkeypem:priK});
signature.updateString(src);
// 签名返回结果是16进制字符串,注意转码
let a = signature.sign();
let sign = hextob64(a);
console.log(`私钥签名:${sign}`);
// 验签
let signatureVf = new KJUR.crypto.Signature({alg:"SHA1withRSA",prvkeypem:pk});
signatureVf.updateString(src);
// 验签入参是16进制字符串,注意转码
let b = signatureVf.verify(b64tohex(sign));
console.log(`公钥验签:${b}`);
输出结果如图:
最后总结一下,在与 Java 联调的时候要注意算法类型是什么,我们这次匹配的算法就不是 SHA1withRSA 而是 MD5withRSA。另外在签名的时候字符串是不能太长的,不然会报错,所以需要先做一次哈希。我们后端开发是用 sha1 对原文进行哈希,然后再用 Sha1withRSA 签名,前端开发使用 sha1 对原文哈希,在用 Sha1withRSA 验签。另外如果 Java 用 fastjson 输出 toJsonString 会出现转义符,小数类型默认返回是 0.0 ,JSON.Stringify 小数默认返回 0,要注意保持前端和后端的原文绝对一致!
附录:
使用 jsrsasign 进行 sha1 操作
let sha1 = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
sha1.updateString('需要sha1处理的明文字符串')
let sha1Str = sha1.digest()
console.log(`src: ${src}`)
console.log(`sha1: ${sha1Str}`)
Tutorial for MessageDigest class
Getting Started
Here is a basic example for 'SHA1' hash calculation.
// initialize
var md = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
// update data
md.updateString('aaa')
// SHA1 hash result of string aaa which will be 7e240de74fb1ed08fa08d38063f6a6a91462a815
var hashValueHex = md.digest()
for hexadecimal input
You can also update a hexadecimal string as hash input.
var md = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
md.updateHex('5f6de0');
var hashValueHex = md.digest();
progressive hashing
The 'updateHex' and 'updateString' method can be called one or more times.
var md = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
md.updateHex('9a3bcd345793173');
md.updateHex('5f6de0');
md.updateString('abcdefg');
md.updateHex('01341571fg56ab');
md.updateString('apple');
var hashValueHex = md.digest();
in short
To update and digest in a one method you can use 'digestHex' or 'digestString' method.
var md = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
var hashValueHex = md.digestHex('1afcdd');
var md = new KJUR.crypto.MessageDigest({"alg": "sha1", "prov": "cryptojs"});
var hashValueHex = md.digestString('orange');
supported hash algorithms and cryptographic providers
MessageDigest class supports combinations of following providers and hash algorithms.
- cryptojs - md5
- cryptojs - sha1
- cryptojs - sha224
- cryptojs - sha256
- cryptojs - sha384
- cryptojs - sha512
- cryptojs - ripemd160
- sjcl - sha256 (NEW since crypto 1.0.4, sjcl only supports sha256)
Tutorial for Signature class
Getting Started
Here is a basic example for 'SHA1withRSA' signature calculation.
// initialize
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
// initialize for signature generation
sig.init(rsaPrivateKey); // rsaPrivateKey of RSAKey object
// update data
sig.updateString('aaa')
// calculate signature
var sigValueHex = sig.sign()
Here is a example for signature validation.
// initialize
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
// initialize for signature validation
sig.init("-----BEGIN CERTIFICATE-----(snip)"); // signer's certificate
// update data
sig.updateString('aaa')
// verify signature
var isValid = sig.verify(sigValueHex)
for hexadecimal input
You can also update a hexadecimal string as hash input.
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
sig.init(rsaPrivateKey);
sig.updateHex('5f6de0');
var sigValueHex = sig.sign()
progressive signing
The 'updateHex' and 'updateString' method can be called one or more times.
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
sig.init(rsaPrivateKey);
sig.updateHex('5f6de0');
sig.updateHex('9a3bcd345793173');
sig.updateHex('5f6de0');
sig.updateString('abcdefg');
sig.updateHex('01341571fg56ab');
sig.updateString('apple');
var sigValueHex = sig.sign()
in short
To update and digest in a one method you can use 'signHex' or 'signString' method.
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
sig.init(rsaPrivateKey);
var sigValueHex = sig.signString('aaa')
var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
sig.init(rsaPrivateKey);
var sigValueHex = sig.signHex('1bdeff')
supported cryptographic providers and signature algorithms
Here is a list of supported cryptographic providers and signature algorithms.
- cryptojs/jsrsa - MD5withRSA
- cryptojs/jsrsa - SHA1withRSA
- cryptojs/jsrsa - SHA224withRSA
- cryptojs/jsrsa - SHA256withRSA
- cryptojs/jsrsa - SHA384withRSA
- cryptojs/jsrsa - SHA512withRSA
- cryptojs/jsrsa - RIPEMD160withRSA
required JavaScript sources
To use Signature class following codes will be required.
<script src="http://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js"></script>
来源:oschina
链接:https://my.oschina.net/u/943746/blog/3053812