HTTPS简介(二):非对称加密RSA

别等时光非礼了梦想. 提交于 2020-02-10 13:02:47

我们如何决定密钥是什么?

如果只有发送方和接收方知道密钥,对称密钥密码术是很安全的。在凯撒密码中,密钥是一个偏移值,这个偏移值决定每个字母应该偏移多少。在我们的例子中,我们使用的偏移值是 3,但是也能是 4 或者 12。

不过这么设计会有个问题:在用信鸽传递信息之前,如果 Alice 和 Bob 之前从没见过,他们没有安全的方式创建一个密钥。如果他们将密钥包含在信息之中,Mallory 将拦截信息并且发现密钥。后果就是:无论 Alice 和 Bob 发送的信息是否加密,Mallory 都能读取或者改变拦截到的信息。

这是一个典型的中间人攻击例子。避免它的唯一方法是改变之前的密码系统。

那么有没有这种方式,Alice 和 Bob 之前从没见过,Alice 想要给 Bob 传递一条信息,一开始Alice 先写一封空的信给Bob ,Bob发一个密钥给Alice。这个密钥要一个特点只能用来加密,对自己加密的文件都没办法解密,只有Bob 才能够解开。也就是说在密钥在传输的过程中即使被Mallory 截获了信鸽,Mallory知道了这个密钥,拿到了这个密钥也只是用来加密,他即使接下里截获到了Alice 用大家都拿到的密钥加密信息发给 Bob的信件,他也没办法解开密文。

这是另外一套密码系统。

他跟之前的有不一样的地方,第一就是他需要两次通讯过程,第二就是给出去的密钥只能用来加密无法用来解密。

这种在网络中传输,可能被很多人截获的密钥,叫做公钥,Bob 用来解开密文的密码较为私钥。

RSA算法

上面的这套密码系统重要的一点是加密和解密能够分开,加密和解密能够分开,加密和解密不是简简单单互逆过程,即使是加密的人,自己都没办法解开。这样就安全多了。
用数学表达:
加密:
Y=E(X)Y=E(X)
其中 X表示明文,Y表示经过函数E转换后的值即密文。
解密:
X=E(Y)X=E(Y)
这里跟上面f(反函数)不同的是E,D不是互逆的。

现在就是来找E,D了,已经有人找好了,先看看:

加密公式:

XemodN=YX^e mod N = Y

解密公式:

X=YdmodNX = Y^d mod N

这个公式是怎么工作的:

取N = 319 ,e = 17,d=33

现在要加密的数X = 40

密文Y=4017mod319Y=40^{17} mod 319计算得到Y=61。这样就完成了加密的过程,在这个过程中我们用到了两个数,N(319),e(17)。d(33)我们是没有给的,他没办法进行解密。

不信试试

6117mod319=11861^{17} mod 319=118

而用d(33)进行解密

6133mod319=4061^{33} mod 319=40

刚才加密的是40,结果是正确的。

这种加密方式为RSA加密算法。拥有公钥和密钥。

openssl中的RSA过程

理论的知识有了,我们不需要自己编写代码来实现这一个过程,强大的openssl可以很好的实现这一个过程,如果还没有安装openssl,可以自行安装。

使用openssl 建立这一个过程,首先,创建私钥:

openssl genrsa -out private_key.pem 2048

显示创建成功:

Generating RSA private key, 2048 bit long modulus
............+++
..........................+++
e is 65537 (0x10001)

Bob 拥有了这个私钥,当Alice 要过来跟他通讯的时候,第一次发送公钥给Alice ,公钥的生成如下:

root@ubuntu:~/openssl_ca/new_rsa# openssl rsa -in private_key.pem -out public_key.pem -outform PEM -pubout
writing RSA key

Alice 拿到了public_key.pem 公钥,对需要的文件进行加密,假设信的名称为hellofile.txt

echo "Welcome in my worls." > hellofile.txt

使用公钥对hellofile.txt 进行加密。

openssl rsautl -encrypt -inkey public_key.pem -pubin -in hellofile.txt -out hellofile_encrypt.dat

得到了hellofile_encrypt.dat,这时候公钥是无法解密的。

root@ubuntu:~/openssl_ca/new_rsa# openssl rsautl -decrypt -inkey public_key.pem -in hellofile_encrypt.dat -out new_hellofile.txt
unable to load Private Key
140480186250904:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:701:Expecting: ANY PRIVATE KEY

Alice 使用公共网络把hellofile_encrypt.dat文件发给Bob ,Bob 使用私钥解密该文件。

openssl rsautl -decrypt -inkey private_key.pem -in hellofile_encrypt.dat -out new_hellofile.txt

查看new_hellofile.txt 的内容。

root@ubuntu:~/openssl_ca/new_rsa# cat new_hellofile.txt 
Welcome in my worls.

openssl中的数字证书过程

加密公式:

XemodN=YX^e mod N = Y

解密公式:

X=YdmodNX = Y^d mod N

这个过程是RSA的加密过程,逆过程是数字证书的签名过程。

生成数字证书:

X=YdmodNX = Y^d mod N

得到X的签名证书,把证书X和源文件Y发个客户端,客户端进行验证。

验证签名:

XemodN=YX^e mod N = Y

如软件的签名证书,在打包软件的时候使用私钥生成数字签名软件,在客户端使用公钥进行签名的验证。这是一个很好地防止软件包被修改的方法。

把刚才生成公钥和私钥的过程构建为脚本:

generate_cert.sh

#!/bin/bash

echo $1

#Step 1: Generate a Private Key
echo -------------------------------------------- 1 
openssl genrsa -des3 -out $1.key 1024

#Step 2: Generate a CSR (Certificate Signing Request)
echo -------------------------------------------- 2
openssl req -new -key $1.key -out $1.csr

#Step 3: Remove Passphrase from Key 
echo -------------------------------------------- 3
cp $1.key $1.key.org
openssl rsa -in $1.key.org -out $1.key


#Step 4: Generating a Self-Signed Certificate
echo -------------------------------------------- 4
openssl x509 -req -days 365 -in $1.csr -signkey $1.key -out $1.crt


#Step 5: Generating PEM Certificate 
echo ---------------------- 5
cat $1.crt > $1.pem
cat $1.key >> $1.pem


echo --------------------------------------------  TERMINATED

生成s2e.pem 公钥密钥。

generate_cert.sh s2e

创建ok.p7e

echo "verify " > ok.p7e

对文件进行签名:

openssl cms -sign -binary -in ok.p7e -out ok.p7e.p7m.pem -nodetach -outform DER -signer s2e.pem

参看签名后的文件 ok.p7e.p7m.pem。

0<82>^Dk^F      *<86>H<86>÷^M^A^G^B <82>^D\0<82>^DX^B^A^A1^M0^K^F       `<86>H^Ae^C^D^B^A0^W^F  *<86>H<86>÷^M^A^G^A 
^D^Hverify
 <82>^B/0<82>^B+0<82>^A<94>^B   ^@ÕZ£ê<84>^Q^V<86>0^M^F *<86>H<86>÷^M^A^A^K^E^@0Z1^K0   ^F^CU^D^F^S^Bcn1^K0     ^F^CU^D^H^L^Bfj1^K0     ^F^CU^D^G^L^Bxm1^Q0^O^F^CU^D
^L^Hchox Ltd1^M0^K^F^CU^D^K^L^Ddemo1^O0^M^F^CU^D^C^L^Fxx.com0^^^W^M181128080158Z^W^M191128080158Z0Z1^K0 ^F^CU^D^F^S^Bcn1^K0     ^F^CU^D^H^L^Bfj1^K0     ^F^CU^D^G^L^Bxm1^Q0^O^F^CU^D
^L^Hchox Ltd1^M0^K^F^CU^D^K^L^Ddemo1^O0^M^F^CU^D^C^L^Fxx.com0<81><9f>0^M^F      *<86>H<86>÷^M^A^A^A^E^@^C<81><8d>^@0<81><89>^B<81><81>^@¨Ê|^NË'ôglr<82>Ú^Uýã?<90>ÚaÈñ   Cé£eÈØ5s¢Ü4^S^AnëSJBëÏ<9e>KráÊ<99>sâsð!^Nª^Rð×W^M^H÷Ûl´^CHÉÎnqi<82>,<8b>^P^C'õùÖ^ZLKV=¾ñ.^[<9a>^MS^MÞötG@ W9<81>^X<98>¯}n<99>^\Æ~´È^Gä^U<92>´\±z-Î>p»^B^C^A^@^A0^M^F   *<86>H<86>÷^M^A^A^K^E^@^C<81><81>^@^FÖoúèÆ=Äç<8a>§m7^E¦0Ë£<97>C^U3<8c>KYÜÃäeä<94>^Mù^P¾^Wà<8c>78~Vi±Û^A^Oä51WA0^E^M^L
Òµ<99><8c>Å)OÃËãÃ9î4ò<9f>6§Á<^Ra<9a><80><9e>y,ù^^<91>$7ò]76º<83>        <8d>Æ(:ʶGFSô<80>4V.¼²sÈàxþééM<99>âú<9f><84>Ý·p1<82>^Aö0<82>^Aò^B^A^A0g0Z1^K0   ^F^CU^D^F^S^Bcn1^K0     ^F^CU^D^H^L^Bfj1^K0     ^F^CU^D^G^L^Bxm1^Q0^O^F^CU^D
^L^Hchox Ltd1^M0^K^F^CU^D^K^L^Ddemo1^O0^M^F^CU^D^C^L^Fxx.com^B  ^@ÕZ£ê<84>^Q^V<86>0^K^F `<86>H^Ae^C^D^B^A <81>ä0^X^F    *<86>H<86>÷^M^A ^C1^K^F *<86>H<86>÷^M^A^G^A0^\^F        *<86>H<86>÷^M^A ^E1^O^W^M181129095832Z0/^F      *<86>H<86>÷^M^A ^D1"^D QÿBÃÓ¹^H<96> B<9a>L^MÊ~m<84><99>cÛÿ¦Ø:+Dº\ `Gc0y^F       *<86>H<86>÷^M^A ^O1l0j0^K^F     `<86>H^Ae^C^D^A*0^K^F   `<86>H^Ae^C^D^A^V0^K^F  `<86>H^Ae^C^D^A^B0
^F^H*<86>H<86>÷^M^C^G0^N^F^H*<86>H<86>÷^M^C^B^B^B^@<80>0^M^F^H*<86>H<86>÷^M^C^B^B^A@0^G^F^E+^N^C^B^G0^M^F^H*<86>H<86>÷^M^C^B^B^A(0^M^F  *<86>H<86>÷^M^A^A^A^E^@^D<81><80>)ñ7BUXYÓ^N?Ü^T@ÝÝõµf©E^P^U<95>SÌ2ÿ<83>ð,Û^Yè^Nç8.<8e>û<8b>6}^H<8a>50^E<94>çËÏ!Çr<8c>BJNffÄgû:^L<83>©^GMkk<98>
µï^^<97>nqë^\^HÄ>Ï(\^H<86>^GHaâ<87>^Zrþ9¹<9a><90>ßÇ@ÏôåÐçTiô^\^?
^ECa>M]°¹­Ì^^ÑÃ

验证文件签名文件:

openssl cms -verify -noverify -in ok.p7e.p7m.pem

如果签名完以后的文件被修改以后,验证无法通过。


转载请标明来之:大家来编程

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!