*
本文只讨论一个问题,在非对称加密算法RSA中,什么是公钥什么是私钥
非对称加密算法
非对称加密算法有很多,例如RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。
在在这些算法中,RSA最为常用,因此,在没有特殊说明的情况下,常说的公钥、私钥都指的的RAS的公钥、私钥。
这里也是以RSA算法为例,来讨论非对称加密中的公钥和私钥 。
RSA加密算法
要想了解公钥和私钥的区别,就要从它们的产生开始。
这里我默认读者已经了解了RSA算法。如果还不了解,请先去看这两篇文章。
RSA算法原理(一)
RSA算法原理(二)
特别是 RSA算法原理(二)一定要仔细看一遍,不然下面的内容你将看不懂。
RSA加密算法中的公钥和私钥
看过上面两篇文章的人应该已经知道了,在RSA加密算法中有6个非常关键数字,他们是算法的核心。
这6个数字分别是
- 大质数p
- 另一个大质数q
- p和q的乘积n
- n的欧拉函数φ(n) 注:φ(n) = (p-1)(q-1)
- 一个随机整数e,1< e < φ(n),且e与φ(n) 互质
- e对于φ(n)的模反元素d 注:所谓"模反元素"就是指有一个整数d,可以使得ed被φ(n)除的余数为1。
其中(n,e)在一起组成了公钥,(n,d)在一起组成了私钥。
现在让我们来回答最开始提出是问题,什么是公钥,什么是私钥。
答:公钥为(n,e) 私钥为(n,d)
文章到此结束,谢谢大家的阅读!
番外1
其实我们仔细想想就会发现,(n,e) 和 (n,d) 根本没什么区别。为什么一个叫公钥一个叫私钥呢?反过来行不行?
答案是可以的,根据算法原理我们知道,只有 (n,e) 是算不出 (n,d) 的,反过来只有 (n,d) 也是算不出 (n,e) 的。所以反过来也是安全的。
那我们就不经思考了,既然反过来也可以,那公钥私钥还有什么区别,为什么一个叫公钥,一个叫私钥呢。
我想了很久,最终想到了一个合理的解释,被公开的秘钥就叫公钥,没有被公开的秘钥就叫私钥。网上多数的回答也证实了我的想法。
原来 公钥和私钥并不是根据 (n,e) 和 (n,d) 区分的,而是根据使用上的不同来区分的
番外2
让我们再思考一个问题。
在工作中,我们经常会用到各种生成秘钥的工具。这些工具一般会为我们生成两个文件。一个公钥文件,假设叫public.key。一个私钥文件,假设叫private.key。
根据上文的结论,我们是否能将private.key当做公钥公开,将public.key当做私钥,保留呢?
答案是 不可以!!!大家千万别去这么做!
为什么,按照上文的结论 “被公开的秘钥就叫公钥,未被公开的秘钥就叫私钥”,不应该是可以吗?为什么不可以?
除非,上面的结论是错的!!!
是的,上面的结论是错的,公钥和私钥并不是根据使用上的不同来区分的,也不是根据(n,e) 和 (n,d) 来区分的。
那公钥和私钥是通过什么来区分的,到底有没有区别。
别着急,让我们先来看一个有趣的现象
根据私钥推导出公钥
在一些秘钥生成工具中,有一个功能叫做 根据私钥推导出公钥 ,这个功能可以根据私钥文件,推导出公钥文件来。 比如蚂蚁金服的秘钥生成工具
学习了RSA算法原理的人肯定想说,这不可能,不管私钥是(n,d)还是(n,e) ,只有 (n,e) 是算不出 (n,d) 的,只有 (n,d) 也是算不出 (n,e) 的。
难道是阿里的人太nb了,可以算出来吗?
当然不是!要真是这样,这种加密算法就不安全了。
那这个功能是怎么实现的了!
答案是私钥中包含了公钥信息!!!
私钥中包含公钥信息
让我们做个实验,随便用什么秘钥生成工具,生成一对秘钥,然后以文本的方式打开,你会发现,私钥的内容总是比公钥的多! 再仔细观察你会发现 公钥中的部分内容在私钥中也存在!
这里最好用文本对比工具,这样看的比较清楚,我知道你们懒得去动手,所以我帮你们做好了!
左边是公钥的内容,右边是私钥的内容,可以看到中间有一行内容是一样的!为什么会这样, 公钥难道不是(n,e) 私钥难道不是(n,d) 吗!
按照RSA算法的定义,公钥确实是(n,e) 私钥也确实的(n,d)。
但是,实际应用中,人们发现,这样做的话,公钥和私钥的重要性和地位就一样了,但其实我们最关心的是私钥,私钥才是最重要的。
于是
在pkcs标准中,pkcs#1规定,私钥包含(n,e,d,p,q),公钥包含(n,e)
在pkcs标准中,pkcs#1规定,私钥包含(n,e,d,p,q),公钥包含(n,e)
在pkcs标准中,pkcs#1规定,私钥包含(n,e,d,p,q),公钥包含(n,e)
重要的话说三遍
(pkcs全称Public-Key Cryptography Standards (公开秘钥加密标准),旗下包含十几个子标准,每个子标准负责一个领域。)
这样做有两个好处
- 公钥和私钥的重要性和地位不再一样,私钥的重要性和地位远高于公钥,这有利于私钥的持有者。
- 拥有了私钥,就相当于拥有了公钥,使用起来特别方便,就算公钥弄丢了,还可以通过私钥生成出来。
(从上文我们了解到,理论和实现还是有区别的,理论跟偏向原理,而实现更偏向使用,所以实际中的私钥会比理论中的私钥多几个参数。)
现在我们可以回答最开始提出的问题了,在非对称加密算法RSA中,什么是公钥什么是私钥。
- 公钥首先是一种秘钥,它包含(n,e),可以被公开,不能推导出私钥
- 私钥首先也是一种秘钥,他有两种语法格式,pkcs#8标准语法格式的和pkcs#1标准语法格式,其中pkcs#1规定,私钥包含(n,e,d,p,q),不可以被公开,可以推导出公钥。
在实际应用中,绝大多数对RSA的实现,都遵循pkcs的标准,即私钥能推出公钥,但公钥不能推出私钥
总结
通过上面的文章我们至少要知道以下几点
- 公钥和私钥不一样
- 私钥可以推导出公钥,但公钥无法推导出私钥(私钥包含公钥)
- 理论和实现 是有出入的,所以只学习理论是无法为我们解惑的,必须联系实际进行思考才能解答我们的疑问。
番外3
秘钥格式
生成的秘钥一般会通过PEM编码成文本来存储。具体如下:
- PKCS1语法格式私钥:传统格式,PHP、.NET一般使用此格式
- PKCS8语法格式私钥:java一般使用此格式
- PKCS1格式和PKCS8格式的私钥,导出的公钥内容是一摸一样的
公钥是不分 pkcs1 格式和 pkcs8格式的,因为公钥就只有一种语法格式。
RSA密钥语法
RSA公钥在PKCS#1标准中定义的语法
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
(n,e)
复制代码
RSA私钥在PKCS#1标准中定义的语法
RSAPrivateKey ::= SEQUENCE {
version Version, //版本
modulus INTEGER, // RSA合数模 n
publicExponent INTEGER, //RSA公开幂 e
privateExponent INTEGER, //RSA私有幂 d
prime1 INTEGER, //n的素数因子p
prime2 INTEGER, //n的素数因子q
exponent1 INTEGER, //值 d mod (p-1)
exponent2 INTEGER, //值 d mod (q-1)
coefficient INTEGER, //CRT系数 (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
(n,e,d,p,q)
复制代码
RSA私钥在PKCS#8标准中定义的语法
pkcs#8 全称 Private-Key Information Syntax Standard 私钥信息语法标准,是专门为私钥而设计的规范,所以是不存在PKCS#8格式的公钥这一说
PrivateKeyInfo ::= SEQUENCE {
version Version, //版本
privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, //算法标示符
privateKey PrivateKey, //私钥
attributes [0] IMPLICIT Attributes OPTIONAL
}
复制代码