密码学用于安全目的。使用 Python 的 IDEA 加密模式 CTR 进行加密/解密的示例并不多。本章的目标是:
- 在站点到站点通信中扩展并实现 RSA 数字签名方案。
- 使用哈希(SHA-1)确保消息的完整性。
- 生成简单的密钥传输协议。
- 使用 IDEA 加密密钥。块密码模式为计数器模式(CTR)。
1: 服务器端实现
import socket
import hashlib
import os
import time
import itertools
import threading
import sys
import Crypto.Cipher.AES as AES
from Crypto.PublicKey import RSA
from CryptoPlus.Cipher import IDEA
# 从管理员处获取服务器地址和端口号
host= raw_input("Server Address - > ")
port = int(input("Port - > "))
# 检查服务器和端口的布尔值
check = False
done = False
def animate():
for c in itertools.cycle(['....','.......','..........','............']):
if done:
break
sys.stdout.write('\rCHECKING IP ADDRESS AND NOT USED PORT '+c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\r -----SERVER STARTED. WAITING FOR CLIENT-----\n')
try:
# 设置套接字
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((host,port))
server.listen(5)
check = True
except BaseException:
print "-----Check Server Address or Port-----"
check = False
if check is True:
# 服务器退出
shutdown = False
# 打印"服务器启动消息"
thread_load = threading.Thread(target=animate)
thread_load.start()
time.sleep(4)
done = True
# 绑定客户端和地址
client,address = server.accept()
print ("CLIENT IS CONNECTED. CLIENT'S ADDRESS ->",address)
print ("\n-----WAITING FOR PUBLIC KEY & PUBLIC KEY HASH-----\n")
# 客户端的消息(公钥)
getpbk = client.recv(2048)
# 将字符串转换为密钥
server_public_key = RSA.importKey(getpbk)
# 在服务器端对公钥进行哈希处理,以验证客户端的哈希
hash_object = hashlib.sha1(getpbk)
hex_digest = hash_object.hexdigest()
if getpbk != "":
print (getpbk)
client.send("YES")
gethash = client.recv(1024)
print ("\n-----HASH OF PUBLIC KEY----- \n"+gethash)
if hex_digest == gethash:
# 创建会话密钥
key_128 = os.urandom(16)
# 使用 CTR 模式加密会话密钥
en = AES.new(key_128,AES.MODE_CTR,counter = lambda:key_128)
encrypto = en.encrypt(key_128)
# 进行 SHA1 哈希处理
en_object = hashlib.sha1(encrypto)
en_digest = en_object.hexdigest()
print ("\n-----SESSION KEY-----\n"+en_digest)
# 使用公钥加密会话密钥
E = server_public_key.encrypt(encrypto,16)
print ("\n-----ENCRYPTED PUBLIC KEY AND SESSION KEY-----\n"+str(E))
print ("\n-----HANDSHAKE COMPLETE-----")
client.send(str(E))
while True:
# 来自客户端的消息
newmess = client.recv(1024)
# 将消息从十六进制解码以解密加密版本的消息
decoded = newmess.decode("hex")
# 将 en_digest(会话密钥)用作密钥
key = en_digest[:16]
print ("\nENCRYPTED MESSAGE FROM CLIENT -> "+newmess)
# 解密来自客户端的消息
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
print ("\n**New Message** "+time.ctime(time.time()) +" > "+dMsg+"\n")
mess = raw_input("\nMessage To Client -> ")
if mess != "":
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
eMsg = ideaEncrypt.encrypt(mess)
eMsg = eMsg.encode("hex").upper()
if eMsg != "":
print ("ENCRYPTED MESSAGE TO CLIENT-> " + eMsg)
client.send(eMsg)
client.close()
else:
print ("\n-----PUBLIC KEY HASH DOESNOT MATCH-----\n")
2: 客户端实现
import time
import socket
import threading
import hashlib
import itertools
import sys
from Crypto import Random
from Crypto.PublicKey import RSA
from CryptoPlus.Cipher import IDEA
# 加载动画
done = False
def animate():
for c in itertools.cycle(['....','.......','..........','............']):
if done:
break
sys.stdout.write('\rCONFIRMING CONNECTION TO SERVER '+c)
sys.stdout.flush()
time.sleep(0.1)
# 生成公钥和私钥
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
private = key.exportKey()
# 对公钥进行哈希处理
hash_object = hashlib.sha1(public)
hex_digest = hash_object.hexdigest()
# 设置套接字
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 从用户处获取主机和端口
host = raw_input("Server Address To Be Connected -> ")
port = int(input("Port of The Server -> "))
# 绑定地址和端口
server.connect((host, port))
# 打印"服务器启动消息"
thread_load = threading.Thread(target=animate)
thread_load.start()
time.sleep(4)
done = True
def send(t,name,key):
mess = raw_input(name + " : ")
key = key[:16]
# 将消息和名称合并
whole = name+" : "+mess
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
eMsg = ideaEncrypt.encrypt(whole)
# 将加密的消息转换为十六进制以便于阅读
eMsg = eMsg.encode("hex").upper()
if eMsg != "":
print ("ENCRYPTED MESSAGE TO SERVER-> "+eMsg)
server.send(eMsg)
def recv(t,key):
newmess = server.recv(1024)
print ("\nENCRYPTED MESSAGE FROM SERVER-> " + newmess)
key = key[:16]
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
print ("\n**New Message From Server** " + time.ctime(time.time()) + " : " + dMsg + "\n")
while True:
server.send(public)
confirm = server.recv(1024)
if confirm == "YES":
server.send(hex_digest)
# 连接消息
msg = server.recv(1024)
en = eval(msg)
decrypt = key.decrypt(en)
# 进行 SHA1 哈希处理
en_object = hashlib.sha1(decrypt)
en_digest = en_object.hexdigest()
print("\n-----ENCRYPTED PUBLIC KEY AND SESSION KEY FROM SERVER-----")
print(msg)
print("\n-----DECRYPTED SESSION KEY-----")
print(en_digest)
print("\n-----HANDSHAKE COMPLETE-----\n")
alais = raw_input("\nYour Name -> ")
while True:
thread_send = threading.Thread(target=send,args=("------Sending Message------",alais,en_digest))
thread_recv = threading.Thread(target=recv,args=("------Receiving Message------",en_digest))
thread_send.start()
thread_recv.start()
thread_send.join()
thread_recv.join()
time.sleep(0.5)
time.sleep(60)
server.close()