RSA签名和数字证书

由上一篇文章 RSA非对称加密原理 可知公钥加密后只能有私钥解密, 用来发送密文.

假设 Tony 给 Banner 发送一条加密消息, 用 Banner 的公钥加密. 如果密文被截获也无妨, 因为私钥只有Banner有.

但是存在另外一个问题, 如果另外一个人冒充 Tony, 并用公钥把加密后的信息发送给 Banner, Banner该如何鉴别?

这时就需要用到签名

签名(Signing messages) 就是为了验证信息的”发送者”的确是真的发送者, 内容不可伪造

RSA加密时, 公钥加密后只能有私钥解密. 重要的是反过来也同样成立, 由私钥加密的内容只能由公钥进行解密

但为了避免混淆, 私钥的加密会称作签名.

用公钥进行解密, 称作验证签名

签名/验签

1. 签名

签名用的是私钥

1
2
3
echo -n hello > file1
openssl rsautl -sign -inkey key.pem -in file1 -out file1.sign
base64 file1.sign

内容为

1
sWAg0Hb2sng9Xupkc12FeQ==

2. 验签

1
openssl rsautl -verify -pubin -inkey pub_key.pem -in file1.sign

打印hello

注:

一般情况下, 签名不会如上述例子所示, 对原文件进行签名, 而是先计算原文件的散列
以 Tony 给 Banner 发送文件为例, Tony 可用自己的私钥对消息的散列值$h=hash(m)$进行签名得到: $s=sign(h)$

然后将$(m, s)$用Banner的公钥加密后发送

Banner 收到消息后, 先用自己的私钥解密, 得到$(m, s)$, 然后用 Tony 的公钥解密签名, 得到散列值 $h$, 重新对$m$进行散列, 如果$h==hash(m)$

则说明文件没有被篡改, 并且发送者就是Tony

因为 Banner 拿的是 Tony 的公钥, 只能解开 Tony 签名过的消息

3. 用python代码验签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import base64

n = 282522173461889495699110463826178747657
e = 65537
d = 226881639216003847549763572915136397913

sign = base64.b64decode('sWAg0Hb2sng9Xupkc12FeQ==')


c = int.from_bytes(sign, byteorder='big')
print(c) # 235772481305732042486557949216182601081

# 公钥解密
m = pow(c, e, n)
print(m) # 10384593717069655256779966059932783

mBytes = int.to_bytes(m, length=16, byteorder='big')

print(mBytes)
# b'\x00\x01\xff\xff\xff\xff\xff\xff\xff\xff\x00hello'

由代码可见 签名/验签 算法的过程与rsa加密解密完全一样, 只不过将公私钥调换

私钥签名时, 填充的格式为: 0x0001开头, 中间填充0xff(加密是填充的是非零随机数), 最后一位是0xff, 填充部分最少也是11个字节

之后跟上具体的消息. 最大长度不能超过key的位数

总结:

假设公钥为 $(n, e)$, 私钥为 $(n, d)$

  • 加密(秘): $c= m^e \; mod \; n$
  • 解密(公): $m= c^d \; mod \; n$
  • 签名(公): $s= m^d \; mod \; n$
  • 签名(秘): $c= s^e \; mod \; n$

签名的用途总结:

信息传输过程中,单纯采用加密来保证数据的保密性,实际上还存在缺陷,假如发送方在发送某个信息后突然反悔,声明这个信息不是其发送,进行抵赖,虽然数据传输过程中是保密的,但无法证明这个信息的发送方身份,这样不利于通信的管理.

现实中,一般采用签名的方式,使信息不可抵赖,例如,合同谈判,银行取款等,都采用了用户签名的形式,证明这个信息确实发生过,那么,在网络通信中,通常使用数字签名实现信息的不可否认性.

数字签名的签名过程,就是发送者根据待发送的信息和用自身私钥加密的数字摘要组合成数字签名.用户采用自己的私钥对信息加以处理,由于密钥仅为本个所有,这样就产生了别人无法生成的文件,也就形成了数字签名,采用数字签名,能够确认以下两点.

  1. 保证信息是由签名者自己签名发送的,签名者不能否认或难以否认.
  2. 接收方可以验证信息自签发后到收到为止未曾做过任何修改,签发的文件是真实文件.

数字证书

对于 签名/验证签名 而言, 确定确认 Banner 电脑上的公钥的确就是 Tony 的公钥至关重要

数字证书就是为了完成这件事情

证书中心(certificate authority, CA), 将 Tony 的公钥和相关信息一起用 CA 的私钥进行签名, 生成数字证书(Digital Certificate)

CA的公钥是公开的, 在每个人的电脑上已经预装. Banner 用CA公钥解密 Tony 的数字证书, 可得到 Tony 真正的公钥和相关信息

证书中心(certificate authority, CA), 是证书权威机构, 其根证书被预先安装在用户的操作系统中.

x.509 数字证书

X.509 证书己应用在包括TLS/SSL在内的众多 Intenet协议里.同时它也用在很多非在线应用场景里,比如电子签名服务

X.509是ITU-T标准化部门基于他们之前的ASN.1定义的一套证书标准。

本文为了演示, 首先创建一个自建的CA, 当然这个测试的CA是不被相信的.

1. 生成 1024 私钥 (RSA PRIVATE KEY)

1
openssl genrsa 1024 > key.pem

2. 生成根证书 (CERTIFICATE)

格式为x.509, 自签名的证书, 所谓自签名, 指的是用自己的私钥来签名.

1
openssl req -x509 -new -days 365 -key key.pem  > crt.pem

输入信息

1
2
3
4
5
6
7
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:ShangHai
Locality Name (eg, city) []:ShangHai, PuDong
Organization Name (eg, company) [Internet Widgits Pty Ltd]:tswblog
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:TangShiWei
Email Address []:dztxd@126.com

查看证书内容

1
openssl x509 -text -noout -in crt.pem

打印输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
fe:1a:f9:72:29:39:d3:e4
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=CN, ST=ShangHai, L=ShangHai, PuDong, O=tswblog, CN=TangShiWei/emailAddress=dztxd@126.com
Validity
Not Before: Mar 10 03:08:52 2019 GMT
Not After : Mar 9 03:08:52 2020 GMT
Subject: C=CN, ST=ShangHai, L=ShangHai, PuDong, O=tswblog, CN=TangShiWei/emailAddress=dztxd@126.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:96:b8:ea:75:29:9c:24:b7:e8:ac:94:ff:e8:4f:
32:9b:3b:2f:33:14:a0:3f:20:9b:ae:5e:b7:45:e1:
1f:8e:1b:68:f3:bf:0f:a7:0d:41:1f:b0:1f:11:d6:
3d:5e:3b:2e:6a:8b:e1:e5:55:e9:e1:68:6f:65:10:
df:2c:a7:70:5e:d0:46:d9:47:3f:a5:f4:49:97:4f:
8f:7b:88:f3:c5:1e:2d:90:94:01:27:e5:88:8d:67:
14:bb:6a:ba:55:49:9c:20:42:f3:d3:79:d6:ec:26:
37:68:8a:97:48:ac:76:fa:25:c8:19:17:4b:6c:34:
94:2b:47:0d:82:5f:ca:ce:9f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
DB:3C:71:AF:D3:76:05:1A:73:34:56:E1:E2:A0:5F:0A:09:7A:03:D8
X509v3 Authority Key Identifier:
keyid:DB:3C:71:AF:D3:76:05:1A:73:34:56:E1:E2:A0:5F:0A:09:7A:03:D8
DirName:/C=CN/ST=ShangHai/L=ShangHai, PuDong/O=tswblog/CN=TangShiWei/emailAddress=dztxd@126.com
serial:FE:1A:F9:72:29:39:D3:E4

X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
5a:12:e9:44:8d:7d:8c:06:84:f3:16:81:6b:d7:32:cd:e8:ff:
7a:84:2f:b9:9d:23:a0:19:8a:f3:f0:05:52:64:49:13:96:7b:
0f:0b:f3:47:a8:c0:48:a9:1e:91:3b:4f:e8:b8:0a:6f:ae:c2:
69:0e:3c:3f:f7:bc:03:5d:17:eb:19:ce:9e:3e:62:8c:97:ec:
4c:39:dd:6a:89:26:30:3a:75:2a:f7:37:01:8b:ab:3a:a9:b3:
86:6d:79:5a:53:42:10:36:06:33:4a:21:e5:16:77:b4:b3:8f:
6a:e4:34:66:b5:6b:79:d1:95:d0:97:e0:b7:ef:bd:87:4d:dd:
50:3a

证书的存储也是使用了ANS.1标准, 包含数据签名两部分,

数据部分包含了主体的公钥, 主体的身份信息CA的身份信息

签名是CA用自己的私钥对数据部分hash后进行签名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
数据
版本号
证书序列号
签名算法标识符
颁发者信息
有效日期
起始
结束
主体信息
C Country Name 证书持有者所在国家 要求填写国家代码,用2个字母表示
ST State or Province Name 证书持有者所在州或省份 选填
L Locality Name 证书持有者所在城市 选填
O Organization Name 证书持有者所属组织或公司 选填
OU Organizational Unit Name 证书持有者所属部门 选填
CN Common Name 证书持有者的通用名 必填 (对于https来讲是域名)
主体公钥信息
算法类型-rsa
模数
指数
颁发机构的密钥标识
主体密钥标识符
签名算法

3. 证书请求 (CERTIFICATE REQUEST)

证书请求不是证书. 是主体将自己的信息和公钥封装在一个文件里, 然后用这个文件向CA请求证书.

1
openssl req -new -key app_key.pem > app_csr.pem
1
2
3
4
5
6
7
8
9
10
11
12
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:ShangHai
Locality Name (eg, city) []:ShangHai, PuDong
Organization Name (eg, company) [Internet Widgits Pty Ltd]:tswblog
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:custapp.com
Email Address []:test@126.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

4. 签发证书

CA会从csr中获取主体的信息和公钥等信息, 并附带一些其他的信息(例如有效期, 证书颁发机构信息), 然后用CA的私钥进行签名
签名 + 数据 = 证书

编辑openssl.cnf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[ ca ] 
default_ca= CA_default # The default ca section

[ CA_default ]

dir= ./certs # Where everything is kept
certs= $dir # Where the issued certs are kept
crl_dir= $dir/crl # Where the issued crl are kept
database= $dir/index.txt # database index file
new_certs_dir= $dir/new_certs # default place for new certs
certificate= $dir/CA/OrbixCA # The CA certificate
serial= $dir/serial # The current serial number
crl= $dir/crl.pem # The current CRL
private_key= $dir/CA/OrbixCA.pk # The private key
RANDFILE= $dir/.rand # private random number file
default_days= 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md= sha256 # which message digest to use
preserve= no # keep passed DN ordering

# A few different ways of specifying how closely the request should
# conform to the details of the CA

policy= policy_anything # For the CA policy

[ policy_anything ]
countryName = optional
stateOrProvinceName= optional
localityName= optional
organizationName = optional
organizationalUnitName = optional
commonName= supplied
emailAddress= optional

创建必要文件

1
2
3
mkdir -p certs/new_certs
touch certs/index.txt
echo 01 >certs/serial

执行命令

1
openssl ca -keyfile key.pem -cert crt.pem -in app_csr.pem -days 10 -config openssl.cnf -out app_crt.pem

查看证书内容

1
openssl x509 -text -noout -in app_crt.pem

可见颁发者(Issuer)和主体(Subject)已经是不同的内容了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 1 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=ShangHai, L=ShangHai, PuDong, O=tswblog, CN=TangShiWei/emailAddress=dztxd@126.com
Validity
Not Before: Mar 10 04:47:15 2019 GMT
Not After : Mar 20 04:47:15 2019 GMT
Subject: C=CN, ST=ShangHai, L=ShangHai, PuDong, O=custapp, CN=custapp.com/emailAddress=test@126.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:bc:44:c8:84:2d:78:e0:a8:e3:31:56:e3:b4:1c:
d0:57:01:06:a7:75:c8:fd:c5:af:2d:6f:b9:05:de:
5e:c8:9b:db:8f:a0:fa:50:54:89:33:81:18:18:3c:
16:a0:6e:1a:9c:97:69:39:74:a2:5f:8b:bb:a0:0b:
5d:70:f2:6f:2d:6a:a5:a4:71:73:3d:ac:d6:24:2a:
02:3b:82:27:27:01:ae:2d:b3:19:ed:f4:7e:72:1b:
e1:2b:e4:03:8c:8b:15:44:87:aa:9f:9a:b9:7b:36:
b4:89:0a:fb:a9:44:26:44:af:2c:00:16:11:39:db:
59:ce:80:ca:07:b4:98:17:71
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
12:89:10:3b:69:3d:55:a3:97:ea:f1:72:26:da:3a:45:03:ab:
a6:9e:59:52:e6:29:53:00:d5:ae:b2:e0:35:75:f1:15:2b:a5:
98:a2:08:23:ac:31:58:e0:af:b2:97:76:71:a8:61:31:fa:77:
f0:3d:55:b0:30:21:6c:e7:5b:23:68:4c:fa:21:7e:8a:ee:d7:
8e:32:1d:35:8a:29:ed:a5:b8:27:0f:60:85:08:24:e6:07:8f:
bf:37:54:b6:eb:e1:d7:6b:f3:85:48:2a:b9:29:34:89:e4:a1:
3d:8e:c5:be:ba:01:d6:49:75:cf:15:8e:01:b7:9a:28:32:d5:
71:fb

6. 验证

用来验证某个证书是不是ca颁发的
crt.pem 是 ca 的证书

1
openssl verify -CAfile crt.pem app_crt.pem

7. 颁发中级证书

CA还可以办法中级证书, 中级证书用于子CA, 可以继续颁发下级证书. 这样就可以构成证书链
本文演示的是普通的应用证书, 不具有继续颁发下级证书的权限.

参考

X.509
what_is_a_digital_signature
signature
rsa_sign_vs_dec
how-to-build-a-https-server
detail-about-ca-and-certs
利用OpenSSL自签证书和CA颁发证书
使用OpenSSL工具制作X.509证书的方法及其注意事项总结

0%