任务三:Crypto学习
内容:
借助PPT,了解DH 密钥交换实现原理,通过代码实现client/server端交互,通过DH密钥交换进行DES 密钥传输,之后利用DES加密进行数据传输
DH密钥交换
定义
DH是Diffie和Hellman两人在一篇具有独创意义的论文中首次提出的公钥算法,并且给出了公钥密码学的定义。这种公钥算法常被称为Diffie-Hell满密钥交换。许多商业产品都使用了这种密钥交换技术。
DH密钥交换技术的目的是使两个用户能安全的交换密钥,在接下来的密文传输过程能够安全,所以这种算法仅限于进行密钥交换。
原理
算法的有效性在于计算离散对数的困难性。定义离散数对,首先定义素数p的本源根:素数p的本源根是一个整数,且其幂可以产生1到p-1之间所有整数。这样,如果说a是p的本源根,则
a mod p,a2 mod p,…an-1mod p
的值各不相同,它是整数1到p-1的一个置换。
对任意整数b和素数p的本源根a,可以找到唯一的指数使得:
b=ai(mod p),0≤i≤(p-1)
指数i称为b的以a为底的模p离散数对,记为dloga,p(b)。
过程
1.Alice和Bob共享一个素数q以及整数a(a<q),且要求a是q的本源根。
2.Alice产生一个私钥XA(XA<q);Bob产生一个私钥XB(XB<q)。
3.Alice计算公钥YA=αX~A~ mod q;Bob计算公钥YB=αX~B~ mod q。
4.Alice和Bob交换YA和YB。即使YA和YB被窃听了也没有关系。
5.Alice计算共享密钥K=(YB)X~A~ mod q;Bob计算共享密钥K=(YA)X~B~ mod q。
6.这是Alice和Bob都有了共享密钥,可以通过共享密钥来加密传输信息。
client/server端交互
内容
client/server端指的是服务器/客户机,简称位C/S结构。其中服务器负责数据的管理,客户机负责完成与用户的交互任务。
客户机:通过局域网与服务器相联,接受用户的服务请求,并通过网络向服务器提出请求,请求向数据库进行操作。
服务器:接收客户机的请求,将数据提交给客户机,客户机将税局进行计算,然后将计算结果呈现给用户。服务器还要提供完善的安全保护及对数据完整性的处理等操作,并允许多个客户机同时访问服务器,这对服务器的硬件处理功能提了很高的要求。
特点:C/S结构在技术上已经成熟,主要特点在于交互性强、具有安全的存储模式、响应速度快、利于处理大量数据。但是C/S结构缺少通用性,系统维护、升级需要重新开发,增加了维护和管理的成本和难度,进一步的数据扩展难度较大,所以C/S结构只能适用于小型的局域网中。
代码实现
要用python实现client/server端交互,那么就需要创建两个端口,即服务端和客户端。
服务端:
import socket
s=socket.socket()
host=socket.gethostname()
port=8000
s.bind((host,port))
s.listen(5)
while True:
c,addr=s.accept()
print'got connection from',addr
data='thank you for connecting'
c.send(data.encode())
c.close()
客户端:
import socket
s=socket.socket()
host=socket.gethostname()
port=8000
s.connect((host,port))
print(s.recv(1024).decode())
服务端运行结果如下:
客户端运行结果如下:
DH密钥交换进行DES 密钥传输
DES密钥传输:
DES算法的输入密钥长度为64位,但只有其中的56位有效。将64位密钥置于8×8矩阵中,每行的第8位被忽略,被忽略的8位数字被用来奇偶效验。所以DH密钥交换需要传输的密钥长度为64位。
代码实现如下:
import math
import random
def judge_prime(p): #素数判断
if p<=1:
return False
i=2
while i*i<=p:
if p%i==0:
return False
i+=1
return True
#得到所有原根
def get_generator(p):
a=2
list=[]
while a<p:
flag=1
while flag!=p:
if(a**flag)%p==1:
break
flag+=1
if flag==(p-1):
list.append(a)
a+=1
return list
#A,B得到各自的计算数
def get_calculation(p,a,X):
Y=(a**X)%p
return Y
#A,B得到交换计算书后的密钥
def get_key(X,Y,p):
key=(Y**X)%p
return key
if__name__=="__main__":
#得到指定的素数
flag=False
while flag==False:
print('Please input a prime:',end=")
p=input()
p=int(p)
flag=judge_prime(p)
print(str(p)+'is a prime!')
#得到一个素数的一个原根
list=get_generator(p)
print(str(p) + ' 的一个原根为:', end = '')
print(list[-1])
print('------------------------------------------------------------------------------')
#得到A的私钥
XA = random.randint(0, p-1)
print('A随机生成的私钥为:%d' % XA)
#得到B的私钥
XB = random.randint(0, p-1)
print('B随机生成的私钥为:%d' % XB)
print('------------------------------------------------------------------------------')
#得待A的计算数
YA = get_calculation(p, int(list[-1]), XA)
print('A的计算数为:%d' % YA)
#得到B的计算数
YB = get_calculation(p, int(list[-1]), XB)
print('B的计算数为:%d' % YB)
print('------------------------------------------------------------------------------')
#交换后A的密钥
key_A = get_key(XA, YB, p)
print('A的生成密钥为:%d' % key_A)
#交换后B的密钥
key_B = get_key(XB, YA, p)
print('B的生成密钥为:%d' % key_B)
print('---------------------------True or False------------------------------------')
print(key_A==key_B)