非对称加密

986 阅读9分钟

非对称加密

非对称加密需要两个密钥,一个是公开密钥,另一个是私有密钥;公钥用作加密,私钥则用作解密。

使用公钥把明文加密后所得的密文,只能用相对应的私钥才能解密并得到原本的明文,最初用来加密的公钥不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密;

公钥可以公开,可任意向外发布;私钥不可以公开,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方。

常见的公钥加密算法有:RSA、ElGamal、Rabin(RSA的特例)、DSA、ECDSA。本文只讨论记录其中使用最广泛的RSA(苹果前面使用的就是此).

RSA

RSA学习这篇文章对于RSA是原理写的已经非常清晰了, 理解文章前需要知道几个概念.第一个是欧拉函数, 在特定的情况下产生一个定理叫费马小定理, 第二个是模反元素, 还有迪菲赫尔曼密钥交换.

数学理解

最终的数学生成就是 m^e (mod N) ≡ c , c^d (mod N) ≡ m.

  • m: 明文
  • c: 公钥加密后的密文
  • N: 一个非常大的质数(N由两个大质数的乘积p,q所得, 由p,q计算出φ(N)之后, 销毁掉p,q, φ(N)主要是用于e生成d的时候使用)
  • e: 小于N的质数
  • d: e关于N的模反元素
  • 公钥: (N , e)
  • 私钥: (N , d), 由上述N可知私钥可以生成公钥, 可以解释此算法为什么一般都是公钥开放, 私钥保存了.

数学的最后结果就是上面的两个公式.

下面的数学依据是对公式的解答, 怎么找到N, φ(N), e, d的关系, 从而实现非对称加密.

欧拉函数

在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(因此φ(1)=1)。

此函数以其首名研究者欧拉命名(Euler's totient function),它又称为Euler's totient function、φ函数、欧拉商数等。

例如φ(8)=4,因为1,3,5,7均和8互质。 φ(7)=6,因为1,2,3,4,5,6均和7互质。

若m,n互质,则 φ(mn)=φ(m)φ(n)

特殊性质:

  1. 当n为奇质数时,φ(2n)=φ(n).
  2. 若n为质数则φ(n)=(n-1). 我们主要是用到了, 欧拉函数的该理论计算. 公式为: m^φ(n) mod n ≡ 1(记住公式即可, 可验证, 但不必深究)

费马小定理

费马小定理是初等数论四大定理(威尔逊定理,欧拉定理(数论中的欧拉定理),中国剩余定理(又称孙子定理),费马小定理)之一,在初等数论中有着非常广泛和重要的应用。实际上,它是欧拉定理的一个特殊情况(即 ,见于词条“欧拉函数”。

欧拉定理的特殊情况:如果两个正整数m和n互质,而且n为质数!那么φ(n)结果就是n-1。

m^φ(n) mod n ≡ 1就进化成为了m^(n - 1) mod n ≡ 1.

例如,m = 3, n = 5, mn互质, m^(n - 1) = 3^(5-1) = 3^(4) = 81. || 81 mod 5 = 1. 大家可以用py去验证一些大数

模反元素,模倒数,或者模逆元(很重要, 主要是e和d以及φ(n)的关系)

整数 a 对模数 n 之模逆元存在的充分必要条件是 a 和 n 互质,若此模逆元存在,在模数 n 下的除法可以用和对应模逆元的乘法来达成,此概念和实数除法的概念相同。

也可以理解为如果两个正整数e和n互质,那么一定可以找到整数d,使得 ed-1 被n整除。 那么d就是e对于n的“模反元素”. ed mod n ≡ 1

ed ≡ kn + 1

最终生成公式 m ^ (e*d) mod n ≡ m

由上面三个

  1. m^φ(n) mod n ≡ 1由于 1 ^ k = 1, 所以得到m^ (k * φ(n)) mod n ≡ 1
  2. 由于双方都乘以m得到m^ (k * φ(n) + 1) mod n ≡ m
  3. 模倒数可得 e * d mod n ≡ 1得到e * d ≡ kn + 1, k是系数, n是任意数
  4. 所以当模反元素中的n, 等于飞马小定理中的φ(n)的时候(e和φ(n)互质), 就变成了最后的公式
  5. m ^ (e*d) mod n ≡ m

所以我们在知道n(p,q的乘积, φ(n)=(p-1)(q-1)), 可以得到φ(n), φ(n)就是模反元素中的和e互质的n. d就是e相对于φ(n)的模反元素.

最后可以看出, 非对称加密中e, d和n的关系就是e和φ(n)互质, d就是e相对于φ(n)的模倒数.

相当于c = m^e, 所以可以根据密文c, 私钥(d,N)得到明文m.

其实c = m^e, 带入到c^d mod n 里面, 还是相当于m^(e*d) mod n = m.

反向c = m^d, 带入到c^e mod n 里面, 还是相当于m^(e*d) mod n = m.

所以只有n, e, d已知n,e或者n,d的情况下, 谁都可以是私钥或者公钥.或者叫公开出去的叫公钥, 不公开的叫私钥

实际操作

mac中终端加密命令

Mac系统内置OpenSSL(开源加密库), OpenSSL中RSA算法常用指令主要有三个:

  • genrsa: 生成并输入一个RSA私钥
  • rasutl: 使用rsa进行各种加解密, 验证等
  • rsa: 处理密钥格式转换问题
生成一个密钥长度为1024位的私钥
openssl genrsa -out priv.pem 1024 
从私钥中提取公钥
openssl rsa -in priv.pem -pubout -out pub.pem 
查看私钥的明文
openssl rsa -in priv.pem -text -out priv.txt
使用rsa的pub.pem公钥加密, 并且输出加密文本enc.txt
openssl rsautl -encrypt -in msg.txt -inkey pub.pem -pubin -out enc.txt
使用rsa的priv.pem私钥加密, 并且输出加密文本dec.txt和加密文本msg一模一样
openssl rsautl -decrypt -in enc.txt -inkey priv.pem -out dec.txt

使用私钥加密和公钥解密在命令上有所不同
私钥加密(加了一个-sign签名命令)
openssl rsautl -sign -in msg.txt -inkey priv.pem -out privEnc.txt
公钥解密(加了一个-verify验证命令)
openssl rsautl -verify -in privEnc.txt -inkey pub.pem -pubin -out privDec.txt

公钥和私钥查看 截屏2021-04-29 下午3.54.39.png 私钥要比公钥大得多, 公钥是从私钥中提取的.有兴趣的可以查看命令中的privTxt.txt文件.

OC中的RSA代码

OC中使用的证书都是cer为后缀的, 我们的分发的p12文件就是相当于是私钥.

我们使用SecKeyEncrypt和SecKeyDecrypt函数进行加解密, 在系统framework的Security库中的SecKey.h文件中. 后面这篇文章相对比较全面的还是, 需要的时候可以参考.RSA代码

有兴趣的可以看看方法中的SecPadding参数, 里面有很多混合加密方案的参数, 用到哪个搜哪个.

非对称加密的安全性, 效率和破解

由于是模运算加上非常大的质数, 所以RSA的效率低, 要远低于对称加密, 以及摘要算法.所以一般对称加密都进行一些关键数据的加密传递.

2009年12月12日,编号为RSA-768(768 bits, 232 digits)数也被成功分解。这一事件威胁了现通行的1024-bit密钥的安全性,普遍认为用户应尽快升级到2048-bit或以上。

在查看资料的时候, 看到了一种非常有意思的破解思维, 就是计算机在进行模运算的时候, 不同的比特位1总是比0的运算时间要长, 如果可以得到很多数据和其运算的时间, 那么就有可能得到每个比特位上非常接近的数字.

疑惑

刚开始我一直在纠结, 究竟是rsa私钥含有公钥, 私钥生成公钥还是相互独立的. 因为从验证上来说, (n, e)是明文, (n, d是密文), d是根据e和φ(n)算出来的. 而在openssl上, 是根据私钥提取的公钥. 所以一直纠结,到底是私钥包含了公钥, 还是公钥生成了私钥.

查了点资料, 比较好的解释就是,

1.openssl生成的私钥是密钥对, 里面有公钥和私钥, 所以可以从公钥中提取出私钥. 这种情况下, 私钥是一定不能被泄漏的.

2.而密码学中的公钥和私钥就仅仅是(n, e), (n, d). 在两个大的质数p,q计算出n和φ(n), e,d之后, p,q,φ(n)就已经被丢弃了. 密钥可以知道的数据就只有n,e,d了. 想要解密就只能破解大质数n.

所以这种情况下, 不管是私钥还是公钥, 可以把任意一个密钥当做公钥或者私钥, 只要保证自己手里的那一个密钥不公开即可.

可以多看看openssl的文档, 文档实时更新, 有很多有意思的东西openssl

openssl version -d 可以得到openssl的安装目录, 然后打开目录, 找到最终的文件夹内有share目录里面也有文档对应的html.下面是文档大纲,有兴趣可以自己查查, 个人认为可以先看看openssl的命令和关键字的部分, 其余的用到什么在具体进行查看和使用

OpenSSL命令行

OpenSSL版本和配置

构建OpenSSL

OpenSSL命令查看

建立信托商店

手动转换

密钥和证书管理

密钥生成

创建证书签名请求

从现有证书创建CSR

CSR生成 | 签署自己的证书 | 创建对多个主机名有效的证书 | 检验证书 | 检查公共证书

密钥和证书转换

PEM和DER转换

PKCS#12(PFX)转换 PKCS#7转换.(p12)

TLS配置 | 获取支持的套件 | 加密的安全级别

配置TLS 1.3

配置OpenSSL默认值 | 推荐套件配置 | 生成DH参数 | 旧版套件配置

密码套件关键字 | 组合关键字 | 建筑密码套件列表 | 关键字修饰符

处理错误

创建私人证书颁发机构 | 特点和局限性

创建一个根CA | 根CA配置 | 根CA目录结构 | 根CA生成 | 根CA操作 | 根CA数据库文件的结构

创建用于OCSP签名的证书

创建下级CA | 从属CA配置 | 下级CA生成 | 下属CA运营

所以相当于纠结问题中的密钥, 一个是密码学的私钥, 一个是openssl的私钥,并不是同一个东西,也挺蛋疼的...

结论

非对称加密, 一般是结合对称加密和摘要算法一起混合使用的, 有很多种加密方案. iOS中的应用重签名, 以及https都离不开这些加密算法. 后续继续讨论.

欢迎讨论.