RSA

1 Introduction

本文覆盖面较广的、简单介绍RSA

RSA是一种非对称密码算法,RSA代表了3个发明人名字的首字母

RSA背后依靠了两个大质数乘积进行质因数分解特别困难的原理,更多了解参看wiki

RSA公钥、私钥本质就是大数构成,公钥和私钥数学地位上是等价的,一个可以公开,一个不能公开。私钥由(n,d)2个数构成,公钥由(n,e)2个数构成。关于n和e:

  • n: 我们所说的1024/2048 bits的RSA密钥对,其中的1024/2048就是指n的位数
  • e: e一般固定取10001(十进制65537),是折衷的选择,即e不会太小,够保证安全性,又能够保证加密/验证签名时的效率

2 PKCS#1 和 PKCS#8

两者之间的区别可以简单理解为,PKCS#1是Public-Key Cryptography Standards标准中只关于RSA的标准,而PKCS#8是对前者的扩充,毕竟非对称密码算法也不只有RSA一个

PKCS#1包含了RSA的属性、操作(加解密,签名验签)等

我们常常看见如下开头表示的私钥文件:

-----BEGIN PRIVATE KEY-----

-----BEGIN RSA PRIVATE KEY-----

第一个代表PKCS#1和第二个代表PKCS#8,怎么记忆呢?

第一个没有RSA就说明key的类型(OID 1.2.840.113549.1.1.1)包含在了数据里面,所以理论上可以不是RSA,所以是PKCS#8,而第二个限定了是RSA,所以是PKCS#1

下图可以直观感受到:

如果是相同的公钥即n和e值相同,PKCS#1和PKCS#8简单理解为封装格式不一样

工具网址:https://lapo.it/asn1js/

3 DER 和 PEM

首先介绍一下ASN.1,是一种syntax representations,广泛应用在了通讯和密码学领域,我们常见的私钥Key,证书请求文件CSR,证书CER,证书撤销列表CRL,无一例外全部使用了ASN.1表示

下面就是PKCS#8 RSA公钥的ASN.1表示:

对应着的16进制数如下,SEQUENCE对应着30 81 9F,对应着的过程就是DER编码(encoding)的过程,如上也说明了ASN.1本身很轻便

但是DER encoding有个问题,因为是二进制表达,就是会出现乱码,PEM就是用于解决上面这个问题

PEM本质就是对DER编码的二进制数据进行base64编码,让其可以显示不再乱码,方便复制粘贴,邮件发送给别人等

上图中-----BEGIN PUBLIC KEY----------END PUBLIC KEY-----之间的数据,实质就是对DER编码数据30 81 9F xxxxxx 01 00 01进行base64编码而产生的,我们可以通过下面的Python代码再一次验证

import base64

temp = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXKm469Q1THhkO8Q+YYCNmJ/wp\nNZnxiO3kYRlrtl5hFRLxbt/DMo5+VSj/g4HWZNdkHM7V5RVHWyrHg4aK39Qjcw2z\nzG74Hk6r053n3fQV6NdBc0zOYI2te7KLsyNZ0k6l8cvq4d44W30zg/qCNlZLgvj0\nRIWeZkrw4UuEqdwf5wIDAQAB'

print(base64.b64decode(temp.encode('utf-8')).hex())

输入如下:
30819f300d06092a864886f70d010101050003818d0030818902818100972a6e3af50d531e190ef10f9860236627fc293599f188ede461196bb65e611512f16edfc3328e7e5528ff8381d664d7641cced5e515475b2ac783868adfd423730db3cc6ef81e4eabd39de7ddf415e8d741734cce608dad7bb28bb32359d24ea5f1cbeae1de385b7d3383fa8236564b82f8f444859e664af0e14b84a9dc1fe70203010001

PEM编码的文件,都会以第一行形如-----BEGIN PUBLIC KEY-----开始,以最后一行行如-----END PUBLIC KEY-----结束,原因是标识了第一行和最后一行之后,可以标识剩余的中间数据了,所有剩余中间数据就是base64编码的DER编码信息了

4 填充方式

细心的你可能在平常学习工作会发现,对同样一串密文使用RSA公钥加密,得出来的密文有时保持不变,有时却会变,这是什么原因呢?这个主要是填充在起作用

填充为什么存在,主要存在的意义是加入了随机属性,提高RSA算法的安全性,即让其拥有不确定性,确保对同样的消息加密多次,每次产生的密文都不同。同时RSA算法不是block密码算法,RSA是对数操作(消息要转成数),所以这里的填充和CBC填充的意义不太相同,CBC的填充只是为了满足块的大小要求,告诉你这个块又多少填充

首先,加解密和签名验签在PKCS#1中是分别有标准的,因为二者的安全级别要求不同,我们这里将说明下加密时常用到的三种填充:

  • RSA_PKCS1_PADDING: PCKS#1 1.5版本引入的填充方式,需要占用11个字节,所以分组后的每组数据大小不能超过n/8 - 11
  • RSA_PKCS1_OAEP_PADDING: PKCS#2 2版本引入的填充方式,分组后的每组数据大小不能超过n/8 - 2 - 2 * hLen,安全性更高
  • RSA_NO_PADDING: 补0填充,没有引入随机的特征

由加密公示Encrypted = Message ^ e Mod N可得,明文Message长度是要和N保持一致的(N和Message是具有可比较性的数,长度要求要一致),密文长度始终为N的长度

同时应为性能问题,不建议使用RSA直接对数据进行加解密

5 References

https://en.wikipedia.org/wiki/RSA_(cryptosystem) https://stackoverflow.com/questions/20065304/differences-between-begin-rsa-private-key-and-begin-private-key https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem https://blog.cnbluebox.com/blog/2014/03/19/rsajia-mi/ https://crypto.stackexchange.com/questions/42097/what-is-the-maximum-size-of-the-plaintext-message-for-rsa-oaep/42100 https://crypto.stackexchange.com/questions/3608/why-is-padding-used-for-rsa-encryption-given-that-it-is-not-a-block-cipher

Tags:

Categories:

Updated: