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. 组内Linq培训记录

    注: 由于该培训是在组内分享,先写成了Word,而word中的代码都以截图方式呈现了,而在博客园不能很方便的粘贴截图进来,所以我用插入代码的方式加进来,如果文中说“如下图”或“如下图代码”,那么就直接 ...

  2. yii2 如何在页面底部加载css和js

    作者:白狼 出处:www.manks.top/article/yii2_load_js_css_in_end 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接 ...

  3. Spring AOP 动态代理 缓存

    Spring AOP应用:xml配置及注解实现. 动态代理:jdk.cglib.javassist 缓存应用:高速缓存提供程序ehcache,页面缓存,session缓存 项目地址:https://g ...

  4. web会话管理

    http协议是无状态的协议,也就是说服务器不知道这个http连接是那个浏览器发过来的. 要标识会话的唯一,有两种方法:1 Cookie  2 会话级cookie(开关浏览器算一次会话) 和 持久化的c ...

  5. Kafka三款监控工具比较(转)

    在之前的博客中,介绍了Kafka Web Console这 个监控工具,在生产环境中使用,运行一段时间后,发现该工具会和Kafka生产者.消费者.ZooKeeper建立大量连接,从而导致网络阻塞.并且 ...

  6. 初识Hadoop入门介绍

    初识hadoop入门介绍 Hadoop一直是我想学习的技术,正巧最近项目组要做电子商城,我就开始研究Hadoop,虽然最后鉴定Hadoop不适用我们的项目,但是我会继续研究下去,技多不压身. < ...

  7. 用VC6开发嵌入式LINUX程序

    黄山松 (Tom Huang) 发表于博客园http://www.cnblogs.com/tomview/ 首先说明一下,VC6自然不能直接开发LINUX程序,主要使用的是它的编辑环境而已,但是作为一 ...

  8. contiki在keil下的stm32平台移植

    参考博客: http://www.aiuxian.com/article/p-705047.html http://blog.csdn.net/u013232419/article/details/4 ...

  9. addrinfo 结构

    typedef struct addrinfo {int             ai_flags;int            ai_family;int             ai_sockty ...

  10. 在JazzyViewPager中调用其它layout布局xml并使用

    开源地址:https://github.com/jfeinstein10/JazzyViewPager 发现网上的例子使用的是直接创建的一个TextView来做的.但是实际上使用,不可能只有这一个控件 ...