保证http请求传输过程防篡改:RSA算法的签名与验签

前记

在前后端分离开发方式普遍流行的今天;有些信息很重要(如 密码、密钥、金额资产等);有些要求在传输过程严格防止第三方中间人攻击,所以要加密,有些信息要防止篡改,所以要传输方签名,接收方验签。虽然这些手段不一定能完全做到百分百安全,但也是系统安全堡垒不可缺少的一砖一瓦。下面我就介绍一下RSA算法的签名与验签

jsrsasign签名和验签

前端需要用js加密库 jsrsasign;
1.安装

npm install jsrsasign -S

2.封装签名、验签函数 rsa.js

import {KJUR, KEYUTIL, hex2b64, b64tohex} from 'jsrsasign'

const ALGORITHM = 'MD5withRSA'

/**
 * 私钥签名
 * rsa 用 MD5withRSA 算法签名
 * @param privateKey 私钥
 * @param src 明文
 * @return {*}
 * @constructor
 */
const RSA_SIGN = (privateKey, src) => {
  const signature = new KJUR.crypto.Signature({'alg': ALGORITHM})
  const priKey = KEYUTIL.getKey(privateKey) // 因为后端提供的是pck#8的密钥对,所以这里使用 KEYUTIL.getKey来解析密钥
  signature.init(priKey) // 初始化实例
  signature.updateString(src) // 传入待签明文
  const a = signature.sign() // 签名, 得到16进制字符结果
  return hex2b64(a) // 转换成base64
}

/**
 * 公钥验签
 * @param publicKey 公钥
 * @param src 明文
 * @param data 经过私钥签名并且转换成base64的结果
 * @return {Boolean} 是否验签成功
 * @constructor
 */
const RSA_VERIFY_SIGN = (publicKey, src, data) => {
  const signature = new KJUR.crypto.Signature({'alg': ALGORITHM, 'prvkeypem': publicKey})
  signature.updateString(src) // 传入待签明文
  return signature.verify(b64tohex(data))
}

export {
  RSA_SIGN,
  RSA_VERIFY_SIGN
}

实验一下:

import {RSA_SIGN, RSA_VERIFY_SIGN} from './js/rsa'

const src = '123456'

      const publicKey = '-----BEGIN PUBLIC KEY-----\n' +
        'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJRGV7eyd9peLPOIqFg3oionWq\n' +
        'pmrjVik2wyJzWqv8it3yAvo/o4OR40ybrZPHq526k6ngvqHOCNJvhrN7wXNUEIT+\n' +
        'PXyLuwfWP04I4EDBS3Bn3LcTMAnGVoIka0f5O6lo3I0YtPWwnyhcQhrHWuTietGC\n' +
        '0CNwueI11Juq8NV2nwIDAQAB\n' +
        '-----END PUBLIC KEY-----'

      const privateKey = '-----BEGIN PRIVATE KEY-----\n' +
        'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMlEZXt7J32l4s84\n' +
        'ioWDeiKidaqmauNWKTbDInNaq/yK3fIC+j+jg5HjTJutk8ernbqTqeC+oc4I0m+G\n' +
        's3vBc1QQhP49fIu7B9Y/TgjgQMFLcGfctxMwCcZWgiRrR/k7qWjcjRi09bCfKFxC\n' +
        'Gsda5OJ60YLQI3C54jXUm6rw1XafAgMBAAECgYAii9PjcwsfPQcGTI0yR5QCN+J8\n' +
        'jR4RsWtXk/zo0eptaaSY8rvjinx94Qb4Pb386s8jBE+HXRFG3SrJq9RI7LaPrGjU\n' +
        '3qbURTExr9qRo9//eR9VahCKyftryRkeXGqBcOreDgbiTb6wYzUL9OdgSV4to4hz\n' +
        '7oIBmnal3+oy5grpIQJBAOgQwoMgAQfjfDSeBcXRklLestWvHRxLu3mpgcvcqHWm\n' +
        'eH6HdSxBidJlu0U14QkruvxOZAeW0Y4iu20LY0JKZY8CQQDeBneXmEJr1Pnd/GAU\n' +
        'o61i9xpKJOmGmFaiM78DE+JYFdnim+wdye1z/u7GPuD6HmcQC3kb7zpSRVSdOWsn\n' +
        'xvXxAkEAhJBWXMsia5wybmg6ifcebAJVDCW9LlXAoU4IHClPfe17dWPxtjc2AJ8m\n' +
        'a/HMPA3kAY7SK1enG1eR00enCs4u1wJBAJitY9H4Xzyd0VGIul2XDKVwfUCdT4VB\n' +
        '/tk9sk2gf9bI9/Mv+9ekQ0iv92yWUslM3NyYtyixgq6OhJg1ou1QkVECQB3Vu4Kv\n' +
        'KafP5ejMPe3XplyDI20HJbHlAWH5NGZ67oRWLsVnKAIyLxZRhF4LPXew3gC9BVFC\n' +
        'w8zj1geO42oOAso=\n' +
        '-----END PRIVATE KEY-----'

      console.log('明文:', src)
      const data = RSA_SIGN(privateKey, src)
      console.log('签名后的结果:', data)
      console.log('--------------下面开始验签---------------')
      const res = RSA_VERIFY_SIGN(publicKey, src, data)
      console.log('验签结果:', res)

结果:


res.PNG

这里是演示了一下签名与验签的流程,前端借助 jsrsasign这个库;如果你后端是nodejs的话,可以用这个库来验签;后端是java或者其他后端语言也问题不大,都有一些相关的库;

接下来说一下我遇到的一些注意点:

1.怎么生成 公私钥,你可以百度一下 在线生成rsa 公私钥;

比如点击这个网址http://web.chacuo.net/netrsakeypair

2.PNG

生成密钥位数可选 1024位 / 2048位,因为目前最大破解位数好像是768位就不要选 512位的了,不够安全;密钥格式选择 pkcs#8 ; 证书密码 可填可不填,点击生成密钥对就行了,下面两个输入框就是新生成的公钥和私钥,然后复制好备份,私钥给前端,公钥给服务端同学;然后前端用私钥签名,后端用公钥验签。

明文:最好不要写死如'123456' 是一个唯一的字符串,每次签名的明文都不一样这样得到的签名结果就不一样。

2.签名算法:

const ALGORITHM = 'MD5withRSA'

上面写道 'MD5withRSA',当然不止这一种, 还有其他的 如 SHA1withRSA、
SHA1withDSA 、SHA1withECDSA等 可以参考文档https://kjur.github.io/jsrsasign/api/symbols/KJUR.crypto.Signature.html
注意签名和验签时的算法要一致

3.签名结果如何在get请求中传输?

我的建议是:
当你以get请求的时候,参数会格式化为key=value;而签名结果里面刚好有+、/、=字符串,这时候就需要encodeURIComponent一下,后端接收时decodeURIComponent一下再验签;

4.公钥签名时记得加上开头 '-----BEGIN PUBLIC KEY-----' 与 结尾 '-----END PUBLIC KEY-----',这个不能少,在联调的过程中,可能会出现验签失败的情况,这时候前端和后端都可能觉得自己没有写错,怀疑是对方的错。这时候首先是前后端都要基于自己的封装好的签名和验签方法在同一个公钥签名,同一个私钥验签的情况下做对比,这样就能知道是谁签名不正确或者谁没有正确的验签了。

如何保证防篡改?

经过上面的例子,我们知道签名需要 两个参数 (明文、私钥)
验签需要三个参数(公钥、明文、签名结果)

在传输过程中, 假如明文被篡改了,那么服务端在接收后验签肯定不对,这时候就不必理会这次请求了,甚至可以做一下异常请求日志

总结

以上就是一些rsa的签名与验签使用经验,当然还有加密和解密的用法,那就不是本文章要说的了,如有疑惑或者不对请指出来,不胜感激,谢谢。

参考文章:https://www.jianshu.com/p/b32fc387d8ad

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 一、准备知识 在开始介绍前,需要首先了解一下消息摘要、数字签名、数字证书的知识 1、消息摘要 - Message ...
    浪够_阅读 2,650评论 1 2
  • 前言 文中首先解释加密解密的一些基础知识和概念,然后通过一个加密通信过程的例子说明了加密算法的作用,以及数字证书的...
    sunny冲哥阅读 2,874评论 0 2
  • 1 基础 1.1 对称算法 描述:对称加密是指加密过程和解密过程使用相同的密码。主要分:分组加密、序列加密。 原理...
    御浅永夜阅读 2,215评论 1 4
  • 公钥密码系统及RSA公钥算法 本文简单介绍了公开密钥密码系统的思想和特点,并具体介绍了RSA算法的理论基础,工作原...
    火狼o阅读 4,156评论 2 15
  • 转:http://caisenchen.blog.163.com/blog/static/552865502008...
    right_33cb阅读 3,988评论 0 4