你将会收获:

js如何加密, 解密

js如何签名, 验签

js和Java交互如何相互解密, 验签(重点)

通过谷歌, 发现jsrsasign库使用者较多. 查看api发现这个库功能很健全. 本文使用方法, 是结合网上千篇一律的博文, 加上我自己查看源码总结出来的.

公用代码:

// 公钥

let pk="-----BEGIN PUBLIC KEY-----\n" +

"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3XSdz1MnzazBEN5KOfTx0IyVJ\n" +

"Z5wb57isrCuHDhnYXwtmdhQalgII0fozeeFpMpAvlnmHC1kpW7XVGvZnLx3bWbCE\n" +

"bf+pMSW4kmQuI+5cxRUJbCl7sdaODBrINgERHPICVC18AJLThEVMHyjuR6Jn4zQm\n" +

"yYNbReSktY/BrFTvMQIDAQAB\n" +

"-----END PUBLIC KEY-----";

// 私钥

let priK = "-----BEGIN PRIVATE KEY-----\n" +

"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPddJ3PUyfNrMEQ3\n" +

"ko59PHQjJUlnnBvnuKysK4cOGdhfC2Z2FBqWAgjR+jN54WkykC+WeYcLWSlbtdUa\n" +

"9mcvHdtZsIRt/6kxJbiSZC4j7lzFFQlsKXux1o4MGsg2AREc8gJULXwAktOERUwf\n" +

"KO5HomfjNCbJg1tF5KS1j8GsVO8xAgMBAAECgYEA6eG1JMrj63jEmStmMb1txG1a\n" +

"mu4Q5z2QGgtr2HVXsIIlGEq6tWxyHf7TL4qkuz9onuYKn8n2Eqm44fZtVaBx+5ES\n" +

"zRpIvlTvaxmVu0HZ1hYAzUw1XyRnXNMKpL5tT4GCjm8+QGPzlGxgXI1sNg8r9Jaw\n" +

"9zRUYeA6LQR9RIMkHWUCQQD8QojjVoGjtiunoh/N8iplhUszZIavAEvmDIE+kVy+\n" +

"pA7hvlukLw6JMc7cfTcnHyxDo9iHVIzrWlTuKRq9KWVLAkEA+wgJS2sgtldnCVn6\n" +

"tJKFVwsHrWhMIU29msPPbNuWUD23BcKE/vehIyFu1ahNA/TiM40PEnzprQ5JfPxU\n" +

"16S78wJANTfMLTnYy7Lo7sqTLx2BuD0wqjzw9QZ4/KVytsJv8IAn65P/PVn4FRV+\n" +

"8KEx+3zmF7b/PT2nJRe/hycAzxtmlQJBAMrFwQxEqpXfoAEzx4lY2ZBn/nmaR/SW\n" +

"4VNEXCbocVC7qT1j1R5HVMgV13uKiTtq8dUGWmhqsi7x3XayNK5ECPUCQQDZaAN6\n" +

"tvIHApz9OLsXSw0jZirQ6KEYdharXbIVDy1W1sVE3lzLbqLdFp1bxAHQIvsYS5PM\n" +

"A9veSJh372RLJKkj\n" +

"-----END PRIVATE KEY-----";

// 原文

var src = "好厉害";

jsrsasign加密和解密

加密

传入pem标准格式的秘钥字符串, 解析生成秘钥实例: RSAKey. 标准的pem格式秘钥含有开始标记和结束标记, 如本文使用的秘钥: -----BEGIN xxx-----, -----END xxx-----. 至于xxx的具体内容不是太重要, 代码里自动通过正则清洗掉头和尾标记, 所以真的写成-----BEGIN xxx-----也没有关系.

调用encrypt方法, 传入明文和公钥实例, 加密后的返回值是16进制字符串.

所以, 需要将其转为常用的Base64编码. 如果为了方便放在URL上, 建议使用使用hextob64u(enc), 它会将+替换成-,/替换成_,去掉尾部补全的=. 不建议使用encodeURIComponent, 这种编码方式会更大程度上扩大原数据的体积(Base64只会增加1/3, 而url采用的16进制方式, 会增加1倍, 具体原因可另外谷歌).

解密

基本类似加密流程.

// 加密

// 读取解析pem格式的秘钥, 生成秘钥实例 (RSAKey)

var pub = KEYUTIL.getKey(pk);

var enc = KJUR.crypto.Cipher.encrypt(src,pub);

// console.log(enc);

// console.log(hextob64(enc));

// 解密

var prv = KEYUTIL.getKey(priK);

var dec = KJUR.crypto.Cipher.decrypt(enc,prv);

console.log("jsrsasign decrypt: "+dec);

jsrsasign签名和验签

通用流程

RSA签名验签基本流程如下, 当然, 都会被封装成两个方法搞定: 签名和验签.

签名:

指定一款摘要算法, 如sha1对原文哈希.

上述哈希前面填补上摘要算法标识, 便于验签时识别用的什么算法.

用rsa私钥对上述哈希加密.

完成签名.

验签:

用rsa公钥对签名解密, 得到摘要.

原文取摘要.

对比两个摘要, 一样则验签通过, 否则验签不通过.

使用jsrsasign签名验签

签名

网上资料很多比较雷同, 在签名时代码开起来比较麻烦.

这里先给出大家通常步骤, 最后给出我自己看源码总结简化调用方式.

方式1: 创建秘钥实例 -> 构建Signature实例 -> 传入秘钥实例, 初始化 -> 签名

// 方式1: 先建立 key 对象, 构建 signature 实例, 传入 key 初始化 -> 签名

var key = KEYUTIL.getKey(priK);

console.log(key);

// 创建 Signature 对象

let signature=new KJUR.crypto.Signature({alg:"SHA1withRSA"});

// 传入key实例, 初始化signature实例

signature.init(key);

// 传入待签明文

signature.updateString(src);

// 签名, 得到16进制字符结果

let a = signature.sign();

let sign = hextob64(a);

console.log(sign);

方式2: 我的简化方式: 方式1的基础上, 去掉显示读取私钥, 去掉初始化步骤(init(..))

// 创建 Signature 对象

let signature=new KJUR.crypto.Signature({alg:"SHA1withRSA",prvkeypem:priK}); //!这里指定 私钥 pem!

signature.updateString(src);

let a = signature.sign();

let sign = hextob64(a);

console.log(sign);

验签

注意点看注释.

// 验签

// !要重新new 一个Signature, 否则, 取摘要和签名时取得摘要不一样, 导致验签误报失败(原因不明)!

let signatureVf = new KJUR.crypto.Signature({alg:"SHA1withRSA",prvkeypem:pk});

signatureVf.updateString(src);

// !接受的参数是16进制字符串!

let b = signatureVf.verify(b64tohex(sign));

console.log("jsrsasign verify: "+b);

jsrsasign和Java交互

这是很关键的, 任何js插件在好用, 如果和Java不能兼容, 也是白搭. 之前就是过jsencrypt.js库, 但是发现Java在签名验签时貌似不兼容.

// 解密Java的密文

var prv = KEYUTIL.getKey(priK);

// Java加密的密文(Base64Url)

let encJava = "8S2KlcygY8eUvq_Dzro81IQd6oA5fxW9l9hsy8iOvtByMMJI1wKedO5sR_pJmJFYEZl6wfD4BQ-FzvSYftnO5xO8kJaHNtnrFE7R0mqpLIkf6aN02K4F9zWLad3emFTN8Ze_GqooVaa0oX6XHqpDFBQJF3kUB6cfS9mDJNq_boE";

// 解密 / Base64Url -> 16进制 / 私钥实例

var dec4Java = KJUR.crypto.Cipher.decrypt(b64utohex(encJava), prv);

console.log("jsrsasign decrypt 4 java: "+dec4Java);

// 验证Java的签名

// 构建Signature实例

// 这里 prvkeypem 放公钥pem看起来有点怪, 但是这是可行的, 内部还是使用的上文经常出现的 KEYUTIL.getKey(pk) 来生成公钥实例的

var sign4Java = new KJUR.crypto.Signature({alg:"SHA1withRSA",prvkeypem:pk});

sign4Java.updateString(src);

// Java生成签名

var signByJava = "O6uEQFPPEmRfEiZcLQjMB7yYLpO2ohmCJvn95Izu8LveUWqFtoYJbvWRYwKCCV-Z3iurjpEw5nExvHQghwoYIxpB7p97G29WXWhfiaA0AUNlxDM2cOus-CIAq-Kyqee7vDsewp6ixaHThu0CxoPFGpBTpo5kuOFlPFR6CRS3Q9M";

var b2 = sign4Java.verify(b64utohex(signByJava));

console.log("jsrsasign verify 4 java: " + b2);

本文测试代码的运行结果:

jsrsasign signing: O6uEQFPPEmRfEiZcLQjMB7yYLpO2ohmCJvn95Izu8LveUWqFtoYJbvWRYwKCCV+Z3iurjpEw5nExvHQghwoYIxpB7p97G29WXWhfiaA0AUNlxDM2cOus+CIAq+Kyqee7vDsewp6ixaHThu0CxoPFGpBTpo5kuOFlPFR6CRS3Q9M=

jsrsasign verify: true

jsrsasign decrypt: 好厉害

jsrsasign decrypt 4 java: 好厉害

jsrsasign verify 4 java: true

附录: jsrsasign部分方法源码

本来想讲测试用的源文件附上来, 但是这里貌似不支持附件, 所以部分主要的方法代码. 通过阅读, 加上了部分注释, 所以api看起来更容易理解. 另外, 本文调用方式是在页面引入js方式使用的, 若使用其他框架, 可能调用方式略有区别, 但是核心api是不变的.

/**

*

* @param l RSAKey / ECDSA / DSA / 标准的pem格式秘钥Base64字符

* @param k

* @param n

* @returns {*}

*/

KEYUTIL.getKey = function (l, k, n) {

var G = ASN1HEX, L = G.getChildIdx, v = G.getV, d = G.getVbyList, c = KJUR.crypto, i = c.ECDSA, C = c.DSA,

w = RSAKey, M = pemtohex, F = KEYUTIL;

...

// 这里通过判断pem结束标记来判断传入的是什么类型的秘钥字符

if (l.indexOf("-END PUBLIC KEY-") != -1) {

var O = pemtohex(l, "PUBLIC KEY");

return F._getKeyFromPublicPKCS8Hex(O)

}

if (l.indexOf("-END RSA PRIVATE KEY-") != -1 && l.indexOf("4,ENCRYPTED") == -1) {

var m = M(l, "RSA PRIVATE KEY");

return F.getKey(m, null, "pkcs5prv")

}

...

/**

*

* @param {String} e 明文

* @param {RSAKey} f 公钥

* @param {String} d 算法名称, 大写, 如 RSA, 缺省 RSA

* @returns {String} 16进制字符串

*/

KJUR.crypto.Cipher.encrypt = function (e, f, d) {

if (f instanceof RSAKey && f.isPublic) {

var c = KJUR.crypto.Cipher.getAlgByKeyAndName(f, d);

if (c === "RSA") {

return f.encrypt(e)

}

if (c === "RSAOAEP") {

return f.encryptOAEP(e, "sha1")

}

var b = c.match(/^RSAOAEP(\d+)$/);

if (b !== null) {

return f.encryptOAEP(e, "sha" + b[1])

}

throw"Cipher.encrypt: unsupported algorithm for RSAKey: " + d

} else {

throw"Cipher.encrypt: unsupported key or algorithm"

}

};

/**

*

* @param {String} e 16进制密文字符串

* @param {RSAKey} f 私钥

* @param {String} d 算法名称, 大写, 如 RSA, 缺省 RSA

* @returns {String} 明文

*/

KJUR.crypto.Cipher.decrypt = function (e, f, d) {

if (f instanceof RSAKey && f.isPrivate) {

var c = KJUR.crypto.Cipher.getAlgByKeyAndName(f, d);

if (c === "RSA") {

return f.decrypt(e)

}

if (c === "RSAOAEP") {

return f.decryptOAEP(e, "sha1")

}

var b = c.match(/^RSAOAEP(\d+)$/);

if (b !== null) {

return f.decryptOAEP(e, "sha" + b[1])

}

throw"Cipher.decrypt: unsupported algorithm for RSAKey: " + d

} else {

throw"Cipher.decrypt: unsupported key or algorithm"

}

};

/**

*

* @param {Object}o o.alg:算法名称; o.prov:支持的js文件标识; o.prvkeypem:pem格式秘钥(base64);

* @constructor

*/

KJUR.crypto.Signature = function (o) {

var q = null;

...

/**签名方法*/

this.sign = function () {

...

} else {

if (this.prvKey instanceof RSAKey && this.pubkeyAlgName === "rsa") {

this.hSign = this.prvKey.signWithMessageHash(this.sHashHex, this.mdAlgName)

...

js rsa验签_js rsa sign使用笔记(加密,解密,签名,验签)相关推荐

  1. RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密

    RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密 原文:RSACryptoServiceProvider加密解密签名验签和DES ...

  2. RSA 加密解密签名验签

    api package v1// get请求 import "github.com/gogf/gf/v2/frame/g"type GetKeyReq struct {g.Meta ...

  3. C# RSACryptoServiceProvider加密解密签名验签和DESCryptoServic

    C#在using System.Security.Cryptography下有 DESCryptoServiceProvider RSACryptoServiceProvider  DESCrypto ...

  4. golang RSA base64 加解密 签名验签

    1.秘钥.加密/签名字符串加密的格式 目前主要见到有hex及base64 (1)hex 针对hex的加解密 import ("encoding/hex" ) hex.DecodeS ...

  5. java rsa加密 加签_RSA加密解密与加签验签

    RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年7月首次在美国公布 ...

  6. java rsa签名_Java使用RSA加密解密签名及校验

    由于项目要用到非对称加密解密签名校验什么的,于是参考<Java加密解密的艺术>写一个RSA进行加密解密签名及校验的Demo,代码很简单,特此分享! 一.项目截图 代码下载后,导入到ecli ...

  7. iOS使用Security.framework进行RSA 加密解密签名和验证签名

    iOS 上 Security.framework为我们提供了安全方面相关的api: Security框架提供的RSA在iOS上使用的一些小结 支持的RSA keySize 大小有:512,768,10 ...

  8. .NET Core 使用RSA算法 加密/解密/签名/验证签名

    前言 前不久移植了支付宝官方的SDK,以适用ASP.NET Core使用支付宝支付,但是最近有好几位用户反应在Linux下使用会出错,调试发现是RSA加密的错误,下面具体讲一讲. RSA在.NET C ...

  9. asp版 vbscript RSA公钥加密 / 私钥解密 / 私钥签名 / 公钥验签(支持中文)分段加密解密

    最近有空在把自己的asp站点后端函数全部整理了下,在弄RSA的时候遇到了坑了,然后找到下面这位兄弟刚好发布的文章: https://blog.csdn.net/todaygods/article/de ...

最新文章

  1. 洪小文: 今天的AI只是一个黑盒,仍需与HI密切配合
  2. 关于RMAN几个容易混淆的参数
  3. 美团全链路压测自动化实践
  4. SpringBoot解决cors跨域问题
  5. 链表经典题:K个一组翻转链表
  6. Ubuntu 18.10安装MySql8.0.13
  7. 什么是m叉树_国考临近考试了,感觉已经没有进步空间了,最后关头还有没有什么提成成绩的好方法?...
  8. 含有运算符的STRING得到计算结果,类似JS的EVAL
  9. 【正睿2021寒假省选第二轮集训 day 1】令牌生成 (组合数+二分)
  10. CSS块级元素与行内元素的区别和联系
  11. oracle9i目录不停增长,丢失所有文件、拥有全备份,缺少后增加的文件
  12. 点聚-weboffice 6.0 (一)
  13. Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)) | nuget管理器所引发的的错误
  14. 第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV 标签: SFM3D重建 2015-01-15
  15. 压缩ppt文件大小的方法
  16. 修心三不:不生气不计较不抱怨
  17. 群星灵能界所有事件_张丹峰出轨经纪人实锤!愿所有原配都能活得像小三一样...
  18. Redis 提示“Couldn‘t determine DBSIZE!”
  19. Kotlin-Android世界的一股清流
  20. Linux下批量ping ip地址

热门文章

  1. linux 常用查看网络连接方法及脚本
  2. 自动打开WINDWOS远程控制的注册表文件
  3. 企业级分布式事务设计实践解决方案
  4. Java LinkedList指南
  5. Rabbitmq消息发送事务与确认机制
  6. vuex重置所有state(可定制)
  7. [TPYBoard - Micropython之会python就能做硬件 2] 利用micropython控制NOKIA 5110屏
  8. NSOperation的使用细节 [1]
  9. 使用python 的paramiko制作堡垒机
  10. 使用FluentValidation来进行数据有效性验证