由区块链引发的密码技术讨论(四)公钥

第四章 公钥

回顾第一章的场景:

小强与小红加密约会后,他需要订餐,但是他与餐厅客服没有见过面,不可能事先约定好密钥,虽然小强也可以使用与小红的密钥加密,但是餐厅客服也不清楚小强与小红之间的密钥“1999111120000520”,那通过邮件把密钥发送给餐厅客服?不行,这样也会被窃听者小白获取到。所以密钥怎么给别人?何时给别人?这个就是密钥配送问题了,由于加密与解密使用的是相同的密钥,所以称为对称密码。如果与其他人通信均使用相同的密钥,那么这个密钥其实也就没有那么的保密了,所以现代密码技术引入一个解决密钥配送的方法,叫做公钥密码。

4.1 什么是公钥密码

密钥分为加密密钥和解密密钥两种,发送者用加密密钥对消息进行加密,接收者用解密密钥对密文进行解密。加密密钥是任意公开的,因此加密密钥称为公钥,解密密钥绝对不能够公开,因此解密密钥称为私钥。同时,公钥和私钥是一对,由公钥进行加密的密文,必须使用该公钥对应的私钥才能够解密,也就是说公钥和私钥之间具有数学上非常密切的关系。

4.2 公钥密码的流程

公钥密钥的流程如下图:

1、接收者餐厅客服生成一对密钥,一个公钥,一个私钥,私钥必须保密,自己保管好;

2、接收者餐厅客服公布公钥,可以全世界公布,也可以谁要给谁,注意这里是餐厅客服的公钥,不是小强的公钥,也不是私钥;

3、发送者小强使用餐厅客服的公钥和算法(算法一般都是公开了)对“晚上6点,情侣套餐”这个信息进行加密;

4、发送者小强发送密文,就是发邮件;

5、接收者餐厅客服收到密文后,使用自己的私钥,即餐厅客服私钥和算法对密文进行解密。

以上就是基本的流程,与正常理解有点不同,最需注意的一点:谁接收,用其钥。

那算法是什么?密钥对是什么?能够通过公钥破解出私钥吗?接下来我们以最常见的公钥密钥算法RSA为例进行讨论。

4.3 RSA

1977年的一天,阳光明媚,普照大地,三位麻省理工学院的数学家罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起设计了一种算法,可以实现非对称加密,这个算法用他们三个人的名字命名,叫做RSA算法。直至今日,在公开密钥加密和电子商业中RSA被广泛使用。从提出到现今的四十多年里,经历了各种攻击的考验,逐渐为人们接受。

1、密钥对的生成过程

第一步:随机选择两个不相等的质数p和q,注意p和q越大,就越难破解。我们这里为了演示方便,选择p=17,q=19。

第二步:计算p和q的乘积n。

第三步:计算n的欧拉函数φ(n)。

上一章我们介绍了:

所以:

由于p和q都是质数,根据欧拉定理:

代入则

第四步:随机选择一个整数e,e必须满足1< e < φ(n),且e与φ(n) 互质。

与288互质的数有很多,如:5,7,11,13,17,19,23……为了演示方便,也为了我能够偷懒一下,我这里选择了13,在实际应用中,是选择比较大的数。

那么公钥出来了,这里记录一下

第五步:计算私钥,就是e对于φ(n)的模反元素d。

定义:有一个整数d,使得e乘以d除以φ(n)的余数为1,即

那么d就是e对于φ(n)的模反元素。因为e与φ(n) 互质,所以d是一定存在,下面是推导过程证明d是存在的:

那么可以设一个整数k,上面的公式等价于:

 

将e=13,φ(n)=288代入得到:

 

设x=d,y=-k,得出下面的二元一次方程,此方程可以根据扩展欧几里得算法求解:

 

扩展欧几里得算法(辗转相除法)比较有难度不做解释,可以使用下面的python代码计算,该代码采用递归算法,比较烧脑:

#ax+by=q,输入a,b,可计算x,y,q的值
def ext_ojld(a, b):
    if b == 0:
        return 1, 0, a
    else:
        x, y, q = ext_ojld(b, a % b)
        # q = gcd(a, b) = gcd(b, a%b)
        x, y = y, (x - (a // b) * y)
        return x, y, q

print(ext_ojld(13,288))

计算得出
(133, -6, 1)

所以,x=d=133

那么私钥出来了,这里记录一下

2、RSA加密解密算法

我们上面计算出e=13,n=323,d=133

RSA定义了密钥对如下:

公钥 =(e,n)

私钥 =(d,n)

RSA加解密公式如下:

 

我们来验证一下,假设明文为88,使用公钥e=13,n=323加密,计算得到密文为:

我们拿到密文为12,使用私钥d=133,n=323,计算明文为:

注:12的133次方很大,windows自带的计算器大数溢出,但是也不妨碍我们做mod运算。

是不是很神奇?在现实中,e,d这2个数都是比较大的,大到二进制的1024位,也就是2的1024次方,范围要这么大

(1-179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216)

所以,接下来我们讨论一下可靠性问题。

3、RSA可靠性

在整个密钥的生成过程中,我们使用到的数字:p,q,n,φ(n),e,d这6个数字,e,n是公开的,p,q,φ(n),d是不公开的,我们必须保护好d,那么怎么求得d?我们倒着推导尝试:

第一步:

如果e与φ(n)知道,就可以算出d,但是e已知,φ(n)不知,

第二步:

要知道φ(n),就必须知道p和q,但是p和q不知。

有人会说欧拉函数

n已知可求φ(n),但是此公式n必须为质数,显然n不是质数。

第三步:

我们知道n,但是p和q都是质数,将n进行质因数分解就可以破解,但是世界上还没有发现对大整数进行质因数分解的高效算法,这是一个数学难题,所以只要n最够大,分解得到p和q进而破译d是非常困难的。

下面是人类已经分解的最大整数(768)个二进制位,十进制是232位:
33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489
    ×
36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917
比它更大的质因数分解,还没有被报道过,可以说目前能被破解的最长RSA密钥就是768位。

4、现实破译场景难题

还有另外一种破解思路,回顾小强订餐的场景,结合上述介绍的计算机结果,网络上的黑客小白,想要破解餐厅客服的私钥,他就使用餐厅客服的公钥e=13,n=323加密“88”的数据信息,得到的密文是“12”。

根据解密公式:

n已知,明文已知,密文已知,从而想计算d,那么小白就回到第三章讲的离散对数问题了。

上述例子中

此例子d=133如此简单,小白也要从1尝试到133才能找出解,当数字很大时,求离散对数非常困难。

虽然说世界最快的计算机“天河二号”超级计算机每秒3386千万亿次,但是现实中的d(私钥)为2的1024次方,多少个0,或者说多少个亿亿亿我就数不清了,就算是“天河二号”也要计算机好多好多年才能试出来。总之,世界上还没有任何可靠的攻击RSA算法的方式,只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。

4.4 RSA简单实现

本章最后,留下一段实现RSA算法的简单代码,模拟小强发给餐厅客服的信息“晚上6点,情侣套餐”。

# -*- coding:utf-8 -*-
import rsa
def rsa_encrypt(d_str):
    #随机生成私钥和公钥,接受字符串进行加密,n取65537
    #密钥取1024位    
    (pubkey, privkey) = rsa.newkeys(1024)
    print('公钥:',pubkey)
    print('私钥:',privkey)
    # 将字符串进行编码
    content = d_str.encode('utf-8')
    print('编码结果:', content)
    # 公钥加密
    crypto = rsa.encrypt(content, pubkey)
    print ('公钥加密结果:', crypto)
    return crypto, privkey

def rsa_decrypt(crypto, privkey):
    #解密
    content = rsa.decrypt(crypto, privkey)
    #解码
    content = content.decode('utf-8')
    print ('解密结果:', content)

if __name__ == '__main__':
    text = rsa_encrypt('晚上6点,情侣套餐')
    rsa_decrypt(*text)

公钥: PublicKey(105079188695616957771490959672726773255912338751210201441080996911380237326305229798263817427620244151408314608669473769086923837281673858555101749374949397069260318259038797336696696976391420476730356820672965255633222806806624337578979947200880419937813190042183191950773614012585879047976309664245061911451, 65537)
私钥: PrivateKey(105079188695616957771490959672726773255912338751210201441080996911380237326305229798263817427620244151408314608669473769086923837281673858555101749374949397069260318259038797336696696976391420476730356820672965255633222806806624337578979947200880419937813190042183191950773614012585879047976309664245061911451, 65537, 37228339446778615781867473223385918614355686001256537028860943700281333147374477481207372581166584508774427527941414947959614943891895956815095390196867359738402500762267126865118255027965136039390219929118742490020985853538544389322975147935090596832497723957646893904696904247800596707361403644190280665497, 40113909035504348618647542326483225754148397069818955172387388312727259744423634334737561447724477196285393842358669811957004560906513751626151745966420866238823207, 2619520042352706263911255855433453859505654047137594144652892967336222372126672087061258669856523656626830784781503394840931445283136169278147693)
编码结果: b'\xe6\x99\x9a\xe4\xb8\x8a6\xe7\x82\xb9\xef\xbc\x8c\xe6\x83\x85\xe4\xbe\xa3\xe5\xa5\x97\xe9\xa4\x90'
公钥加密结果: b'<\x8ff\xb0}\x80\xb3\xe5\xd2\xc3\xfa\x8a\x15$v\x15\xeeN\x1a\xebu&\xbc;D\x074xvM:R%\xcd,m\xef\x8b\xf4C\x1c\x9a[\x9f\x0bW"%e\x12\xcb:`\x86&k\xf68\xdb\xfe\x86\xb0I\x0e?E\xf4\xcc\xd6\x19HM\xa0?f\xcc\xf0\x9b\xb2\xef\xa6\x8a\xd0\xb8dh\xd2W \x9bmy\xd9\xc8\x98\xac\xbf\xacX\xdf\xc2\x1f\x00-\xbe9(.Z\x16\xba\x8a\xe0B;\xcb#\x9e"\xe6\x16x\xd54\x1d\xfel@'
解密结果: 晚上6点,情侣套餐
发布了29 篇原创文章 · 获赞 4 · 访问量 7570

猜你喜欢

转载自blog.csdn.net/cd4836/article/details/103474971