RSA原理和数学基础不再赘述,网上资料比较多,本文重点分析,RSA信息如何在证书等相关领域的应用。

RSA密钥生成过程大概是这样的,

  1. p、q: 随机找两个大素数p、q,
  2. n:把它们的乘积结果记为n
  3. φ(n):计算n的欧拉函数φ(n) = (p-1)(q-1)
  4. e:随机选择一个整数e,条件是1< e < φ(n),且e与φ(n) 互质。(实际应用中,常常选择65537。)
  5. d:d满足 ed ≡ 1 (mod φ(n))
  6. 将n和e封装成公钥,n和d封装成私钥。

证书信息

以思否网站的证书为例,我们看到使用的非对称加密是RSA
image.png

公钥信息RSA(2048Bits)说明,公钥长度是2048个比特,也就是n这个十进制大整数转换为二进制的bit个数。根据RSA密钥生成过程,公钥是又n和e组成,e一般用65537。那么,在证书的公钥信息里,n和e在哪里?但是数下面的30 82 01 0a...的所有字节,加强远超过2048bit。

到这,不得不提ASN.1编码,人们为了方便存储、传输、交换信息而制定的编码方式,这种编码方式是独立于任何系统和设备的,以达到跨系统,跨领域传输通用性。我们知道,RSA生成公钥,就是n和e,n和e,通过ASN.1的编码规范进行编码,这样,任何人,任何设备,只要按照规范去解码,肯定能够获取n和e,其实就是ASN.1编码统一通信语言。好了,到这里,我们知道,证书的公钥信息是ASN.1编码的,那就按照编码规范,解析出n和e即可,其实很简单,n和e就嵌在公钥信息里,直接提取就行。

公钥ASN.1格式编码信息
30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01
01 05 00 03 82 01 0f 00 30 82 01 0a 02 82 01 01
00 ba 3c 0b 9f a4 6a 8c 70 37 c2 eb 69 b7 07 f6
c0 b9 3d 83 28 8b a2 db e9 96 88 23 fc ca 43 1c
2b 68 1c 63 12 67 94 0e 20 61 8f b0 28 96 7a e5
42 e6 61 e2 35 32 5b b4 0d 7d 6b 65 5b c4 7d 3e
91 4a c8 af 81 fb c7 aa 02 dd 69 e7 5b 31 68 79
ff 41 65 5e 32 e3 f1 6a 81 20 c9 c2 ff 4b e1 ab
14 a2 ce b0 39 15 86 35 7a d9 25 b1 5a 32 a4 cc
3a fe 35 7c 05 5e 41 9a 9a 88 6f f9 5f 28 18 7b
6c 3d fc b1 04 7a 29 4f 34 00 01 b0 97 f9 4e bc
e8 ad e7 5d 98 8e ed 3b 3b d0 01 87 8b 63 4e c3
8d e5 1f bf 80 39 e5 80 c8 06 4f 35 40 c9 de 3b
42 50 2c 73 fe 51 8a 8a ea dd 38 77 8b 6f 34 99
41 bb f1 3f 9e 09 29 53 ff ec f6 92 04 bf 77 f7
b6 48 11 05 39 22 86 1b 72 fe 4d 94 a3 7d 48 c8
1c f9 eb 93 87 06 e0 d5 69 61 e2 9e 2c 38 d8 8d
63 38 ab 32 7d 7c a5 50 bf 8b 83 0c 5e 7e 76 ca
65 02 03 01 00 01 

从上述的编码序列中,公钥n的值(16进制):
00 ba 3c 0b 9f a4 6a 8c 70 37 c2 eb 69 b7 07 f6
c0 b9 3d 83 28 8b a2 db e9 96 88 23 fc ca 43 1c
2b 68 1c 63 12 67 94 0e 20 61 8f b0 28 96 7a e5
42 e6 61 e2 35 32 5b b4 0d 7d 6b 65 5b c4 7d 3e
91 4a c8 af 81 fb c7 aa 02 dd 69 e7 5b 31 68 79
ff 41 65 5e 32 e3 f1 6a 81 20 c9 c2 ff 4b e1 ab
14 a2 ce b0 39 15 86 35 7a d9 25 b1 5a 32 a4 cc
3a fe 35 7c 05 5e 41 9a 9a 88 6f f9 5f 28 18 7b
6c 3d fc b1 04 7a 29 4f 34 00 01 b0 97 f9 4e bc
e8 ad e7 5d 98 8e ed 3b 3b d0 01 87 8b 63 4e c3
8d e5 1f bf 80 39 e5 80 c8 06 4f 35 40 c9 de 3b
42 50 2c 73 fe 51 8a 8a ea dd 38 77 8b 6f 34 99
41 bb f1 3f 9e 09 29 53 ff ec f6 92 04 bf 77 f7
b6 48 11 05 39 22 86 1b 72 fe 4d 94 a3 7d 48 c8
1c f9 eb 93 87 06 e0 d5 69 61 e2 9e 2c 38 d8 8d
63 38 ab 32 7d 7c a5 50 bf 8b 83 0c 5e 7e 76 ca
65 

公钥e(16进制)的值
01 00 01 

打印公钥信息的代码

    private static void printCert() {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            FileInputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\sf.crt.cer");
            Certificate certificate = cf.generateCertificate(inputStream);
            RSAPublicKey publicKey = (RSAPublicKey) certificate.getPublicKey();
            System.out.println(HexUtils.dumpString(publicKey.getEncoded(), 16));

            System.out.println();
            System.out.println(HexUtils.dumpString(publicKey.getPublicExponent().toByteArray(), 16));
            System.out.println();
            System.out.println(HexUtils.dumpString(publicKey.getModulus().toByteArray(), 16));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

RSA 加解密原理

首先,数学推导,可以得如下结论,

  1. 用公钥加密,用私钥解密。

明文m,用公钥(n, e)经过如下公式计算,得到模值c,c就是密文
\(  m^e ≡ c (mod n)\)
解密过程,对密文c, 用私钥(n, d)经过如下公式计算,得到模值m,还原明文
\( c^d ≡ m (mod n)\)

  1. 用私钥加密,用公钥解密。
  2. 加密的明文,大小要满足0<=m < n,其实,很容易理解,加入m大于n,那么m mod n的结果将不再是m,结果有歧义,所以有这个约束。
有的读者可能有疑问,上面加解密算来算去,都是整数之间进行计算,
那么计算机要加密的信息,大多是字符串,那如何应用到字符串呢?

如果对计算机底层原理了解,这个问题就很容易理解。就说,无论我们看到什么样类型
的字符,在计算存储的实际上都是01字节序列,也就是二进制序列,二进制可以转换成
10进制,这样就可以转换成一个10进制的大整数,就可以套用上述公式进行加解密了。

当然实际应用,要考虑很多因素,如防攻击,就有一些列规范,比如加密填充,
RSA/ECB/PKCS1Padding,可以看看RFC文档,参考资料下面有链接,RFC文档详细
介绍,如何加解密,如何签名和验签。

应用

  • 公钥解密私钥解密:可以用于TLS通信初始化时交换对称密钥,即客户端用服务器的公钥对对称密钥进行加密,服务器用自己的私钥进行解密。然后双方用约定的对称密钥进行加密通信。
  • 私钥加密,公钥解密:应用于数字签名,具体是证书颁发机构用自己的私钥,对证书信息的消息摘要和摘要算法组成的数据进行加密。浏览器或操作系统验证证书是否是权威机构颁发的,通过预置的证书机构证书公钥进行解密,获取消息摘要和摘要算法,用摘要算法对证书信息计算得到摘要,比较计算出来的摘要和解密出来的摘要信息是否一致,一致就认为证书确实是证书机构颁发的证书。

参考资料

http://www.ruanyifeng.com/blo...
https://blog.csdn.net/wzj_whu...
https://github.com/wzjwhut/rs...
https://datatracker.ietf.org/...


ThinkFault
16 声望2 粉丝