RSA私钥签名时要基于某个HASH算法,比如MD5或者SHA1等。之前我一直认为签名的过程是:先对明文做HASH计算,然后用私钥直接对HASH值加密。最近才发现不是那么简单,需要对HASH后的数据进行BER编码再加密。

先看一个例子。

公钥模:89 54 E6 61 C1 52 DB ED 07 57 50 04 AD B3 D2 A7 A9 8F E8 D8 20 5B 01 B2 E5 E4 7A 7B EE 80 E3 C0 13 11 D2 F9 AD C3 CC 5F 1D 96 AC B2 AB BE 9C 14 9E 76 31 06 B2 E6 FA 01 52 A7 2E 53 C2 1D 3B 7B 9B 68 05 D2 5E 35 31 98 0E 02 93 E0 D9 0C 38 2D 3D EE 10 E6 87 53 79 DF B2 1E 12 D9 9E EF 89 6D 01 59 0D 13 94 DB 05 B7 09 34 D3 5B AB ED 7C FE 0E BE 87 EE E8 DD 01 39 3A CA 3A A7 17 B8 AA E3

公钥指数:01 00 01

私钥指数:01 FE B1 BA 09 CC E2 54 F7 1E 55 93 3B D2 B8 E4 A6 99 E8 8F FB 28 57 45 FA 00 EF A6 8D 38 62 16 90 30 5A 18 36 65 F9 BA 07 FC 00 56 38 18 74 BB F7 F1 4F 95 01 54 49 9D 6B 4D F2 66 55 13 87 A1 A6 95 74 72 6A D8 3A EA 34 A8 F8 40 5F 27 11 30 4F 96 3A 2E 7B E6 B6 47 3C 3B 4D 24 E8 FA 51 19 59 FB 52 E0 9B D2 24 B3 B5 8A 36 BF 34 20 E9 2A AB 5D 55 9B 60 01 D5 04 81 E8 E7 EC B2 5F 81 41

私钥P:BF 36 08 66 63 74 6A 79 D0 77 64 21 73 6D 1A B9 13 BB 35 13 BE A6 73 84 C8 7D 83 67 BE C2 F5 0C 3A 7F 5F EF 6E 73 E2 BC 31 D2 0C 78 06 D7 38 85 7E F5 06 40 62 A6 1D 53 CC 97 34 30 58 EE E2 05

私钥Q:B7 DD 46 99 58 B2 52 4B 87 FB E1 F1 09 44 AB 9A AD D1 93 90 9C 40 E0 2F 36 63 F4 7F 49 CB 36 E3 2C DA 85 5C 6E CE 41 AC CB 09 6C 27 B6 44 2B D8 26 5F D5 63 DF 2A C8 60 57 3B 23 13 2B 5F 65 C7

私钥DP:A6 EF C4 9B A7 9E DE CA E5 2F 27 33 71 33 C3 0D EC 65 18 2C D9 D9 36 A7 A9 E6 B2 CF E3 A3 10 10 12 0E 5C B2 8C 2B 0E BC 21 7E F2 35 E4 3B 08 74 BC 67 AD 82 8E DD DA 62 EC 0E E2 98 87 3C 60 05

私钥DQ:B6 A0 8B A7 75 7A 6A 53 AB D6 7D 2E 35 CE 87 C5 34 31 9F 29 5C 8A F4 22 F1 1B 87 97 87 6C DA 2F FC 35 71 91 C6 5E 08 CD E1 3E 92 B7 3F 4B A7 61 23 7C BD 30 5E 52 D8 85 19 20 1C 4E C6 1E 13 B1

私钥InvQ:B4 12 D6 05 1C 2C 2B 6F B5 73 99 F3 B7 A7 08 6F A3 E8 2D 6F 33 A6 AE E5 BE 7B 89 86 7F 48 3B DD BC 4A 07 BF A4 A1 BB 96 BD 0E 46 F1 43 FA FB DE A0 1B AB 38 7D 49 59 45 EE 8C F9 3D 89 CF EB AC

明文:11 22 33 44 55

通过调用.NET的RSA签名接口,产生基于MD5的签名后数据:56 E1 5E 29 84 D6 BC FB 87 7F 55 93 B4 E1 F3 75 2C 64 A5 BC 04 3A D7 0A DB 84 AD 8B 9C 4D D8 E6 8A 56 85 7B 2C 5E 50 E5 81 EB DC 40 D8 9A 29 64 54 19 5B F0 2B 77 D3 DB CF A2 17 BF 33 3F 19 19 B0 FF 36 53 D3 C2 36 1D 90 43 27 2C 0F 54 34 54 F7 E8 D2 09 75 E4 F1 A0 8B F5 38 EA 66 D6 53 14 E4 C5 B6 5A C7 74 52 6E 0A 16 C6 9B B7 81 0B 06 61 8A E7 41 BB 97 E6 EE 3E 6A 1C 7A E6 32 18 60

用公钥对上面的数据解密后得到:30 20 30 0C 06 08 2A 86 48 86 F7 0D 02 05 05 00 04 10 28 3D 4F EA 5D DE D5 9C F8 37 D3 04 73 28 F5 AF

这是一段TLV格式的数据,解析后

TAG

名称

长度

30

Sequence组合类型

20

 
 

30

Sequence组合类型

0C

 
   

06

对象标识ObjectID

08

2A 86 48 86 F7 0D 02 05

   

05

空类型

00

 
 

04

字符串类型

10

28 3D 4F EA 5D DE D5 9C F8 37 D3 04 73 28 F5 AF

可以看到28 3D 4F EA 5D DE D5 9C F8 37 D3 04 73 28 F5 AF正好就是明文数据11 22 33 44 55的MD5值。

那么上面这段数据的其它内容表示什么意思呢?

这里使用的编码方法是BER(Basic Encoding Rule),BER的数据都是TLV格式的,每种TAG的定义如下:

0x01:BOOL

0x02:INT,整型

0x04:OCTSTR,字符串类型

0x05:NULL,空类型

0x06:OBJID,对象标识ObjectID(在这里就是对应的HASH算法的OID编码)

0x0A:ENUM

0x30:SEQ,Sequence组合类型

0x31:SETOF

0x40:IPADDR

0x41:COUNTER

0x42:GAUGE

0x43:TIMETICKS

0x44:OPAQUE

也就是说,每次基于不同的HASH算法对不同的数据进行签名时,构造的这一段BER数据的基本格式是固定不变的,只是HASH算法的OID和哈希值会变而已。

下面讲一下HASH算法的OID是怎么编码的。

每个算法的OID都是固定的一串十进制数据,是国际权威组织定的。比如MD5的OID 是 1.2.840.113549.2.5   ,表示为"iso(1) member-body (2) US (840) rsadsi(113549) digestAlgorithm (2) md5 (5)", 所以当解码程序看到这个OID时,就知道是MD5散列.

对OID的编码规则如下:前两部分如果定义为x.y, 那么它们将合成一个字40*x + y, 其余部分单独作为一个字节进行编码。每个字首先被分割为最少数量的没有头零数字的7位数字.这些数字以big-endian格式进行组织,并且一个接一个地组合成字节. 除了编码的最后一个字节外,其他所有字节的最高位(位8)都为1。举例: 30331 = 1 * 128^2 + 108 * 128 + 123   分割成7位数字(0x80)后为{1,108,123}设置最高位后变成{129,236,123}.如果该字只有一个7位数字,那么最高为0。

规则不太好懂,还是以MD5举例

一、将1.2.840.113549.2.5转换成字数组 {42, 840, 113549, 2, 5}(因为前两部分定义为1.2,那么合成一个字40*1+2=42)

二、将每个字分割为带有最高位的7位数字。

42=42,只有一个7位数字,那么最高为0,结果为{0x2A}

840= 6*128^1+72,除最后一个字节外,其他字节的BIT8都置1,结果为{0x86,0x48}

113549=6*128^2+119*128^1+13,除最后一个字节外,其他字节的BIT8都置1,结果为{0x86,0xF7,0x0D}

2=2, 只有一个7位数字,那么最高为0,结果为{0x02}

5=5, 只有一个7位数字,那么最高为0,结果为{0x05}

最终结果为{{0x2A},{0x86,0x48},{0x86,0xF7,0x0D},{0x02},{0x05}}

三、加上TAG和LEN,得到OID编码为 0x06 08 2A 86 48 86 F7 0D 02 05

RSA验签时的步骤:先用公钥解密,解析TLV数据从中得到HASH算法的OID和HASH值,根据OID选择相应的HASH算法对明文进行计算,最后比对HASH值。

常见的HASH算法在用于RSA签名时的BER数据编码格式为:

MD2

1.2.840.113549.2.2

30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10 || H.

MD4

1.2.840.113549.2.4

30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 04 05 00 04 10 || H.

MD5

1.2.840.113549.2.5

30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04 10 || H

SHA1

1.3.14.3.2.26

30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H

SHA224

2.16.840.1.101.3.4.2.4

不确定是否这个OID

30 2D 30 0d 06 09 60 86 48 01 65 03 04 02 04 05 00 04 1C || H

SHA256

2.16.840.1.101.3.4.2.1

30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H

SHA384

2.16.840.1.101.3.4.2.2

30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H

SHA512

2.16.840.1.101.3.4.2.3

30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H

SM3

1.2.156.197.1.504

不确定是否这个OID

30 30 30 0c 06 08 2a 81 1C 81 45 01 83 78 05 00 04 20 || H.

RSA签名验签学习笔记的更多相关文章

  1. RSA签名验签

    import android.util.Base64; import java.security.KeyFactory; import java.security.PrivateKey; import ...

  2. .net core AES加密解密及RSA 签名验签

    引用 using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System; using Sy ...

  3. js rsa sign使用笔记(加密,解密,签名,验签)

    你将会收获: js如何加密, 解密 js如何签名, 验签 js和Java交互如何相互解密, 验签(重点) 通过谷歌, 发现jsrsasign库使用者较多. 查看api发现这个库功能很健全. 本文使用方 ...

  4. RSA加解密&RSA加验签详解

    RSA 加密算法是目前最有影响力的 公钥加密算法,并且被普遍认为是目前 最优秀的公钥方案 之一.RSA 是第一个能同时用于 加密 和 数字签名 的算法,它能够 抵抗 到目前为止已知的 所有密码攻击,已 ...

  5. 利用SHA-1算法和RSA秘钥进行签名验签(带注释)

    背景介绍 1.SHA 安全散列算法SHA (Secure Hash Algorithm)是美国国家标准和技术局发布的国家标准FIPS PUB 180-1,一般称为SHA-1.其对长度不超过264二进制 ...

  6. RSA密钥生成、加密解密、签名验签

    RSA 非对称加密公钥加密,私钥解密 私钥签名,公钥验签 下面是生成随机密钥对: //随机生成密钥对 KeyPairGenerator keyPairGen = null; try { keyPair ...

  7. 数据安全管理:RSA加密算法,签名验签流程详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.RSA算法简介 1.加密解密 RSA加密是一种非对称加密,在公开密钥加密和电子商业中RSA被广泛使用.可以在不直接传递密钥的情况下,完成加 ...

  8. [Python3] RSA的加解密和签名/验签实现 -- 使用pycrytodome

    Crypto 包介绍: pycrypto,pycrytodome 和 crypto 是一个东西,crypto 在 python 上面的名字是 pycrypto 它是一个第三方库,但是已经停止更新,所以 ...

  9. RSA公钥验签

    1.业务场景,公司做理财业务,但是可能有第三方合作.与第三方合作获得更多客户流量.别人可以在第三方进行购买理财产品.那么怎么保证交易信息的安全性那,我们这里给出rsa加密实现原理. 2.工具类rsa: ...

随机推荐

  1. spring的定时任务配置

    本文来源于:http://myspace1916.iteye.com/blog/1570707 也可参考:http://www.oschina.net/question/8676_9032 (个人只是 ...

  2. 从刚刚「简书」平台的短暂异常,谈Nginx An error occurred报错~

    09.26简书平台的短暂异常 An error occurred. Sorry, the page you are looking for is currently unavailable. Plea ...

  3. SQL指令中一些特别值得注意的地方

    SQL基本指令要频繁使用,要是理解错了,将来工作一定会出现很大的麻烦.今天再重新梳理一下基本的SQL语法 SQL指令 in: 这个指令,我曾经发生过把它和python中的in搞混的错误.python中 ...

  4. json字符串的拼接,并转换为json对象

    <html> <head> <script> var qianzhui = "cc"; var test1=""; func ...

  5. iOS 实现Tabbarcontroller中间自定义样式 最简单的方法

    先上图: 如果我们要实现中间按钮自定义样式,方法应该蛮多,这里介绍一种最简单的. 1.创建类继承:UITabBarController,如下代码都是写在该类的 .m文件里 2.定义最中间的自定义样式, ...

  6. iOS 判断内容是否是中文,两种实现

    用category实现 新建类别文件,代码 .h文件 #import <Foundation/Foundation.h> @interface NSString (Valid) - (BO ...

  7. linux 源码安装mysql 5.5

         今天在ubuntu和CentOS下,用源码反复安装了许多次mysql,趁还没忘记,赶紧记下来...      在ubuntu和CentOS下安装过程倒是没什么差别.      0.下载源码, ...

  8. nodeJS Express 删除 x-powered-by

    在使用Express4 Header头部会输出,在晚上搜索几种方案也没有产生效果,就看了一下官方文档 Property Type               Value Default     x-p ...

  9. 关于Leetcode上二叉树的算法总结

    二叉树,结构很简单,只是比单链表复杂了那么一丢丢而已.我们先来看看它们结点上的差异: /* 单链表的结构 */ struct SingleList{ int element; struct Singl ...

  10. XSS quiz练习题做题过程及感悟

    XSS quiz 最近刚学XSS.所以新手理解如有错误不当,欢迎批评指正. 第1题 一开始做,使用了Chrome浏览器.第一题怎么都做不出来.突然想起来使用IE,打开IE11,才成功了. <sc ...