客户端和服务器之间的套接字和消息加密解密
使用的语言: Python 2.7(下载链接: https : //www.python.org/downloads/ )
使用的库:
* PyCrypto (下载链接: https : //pypi.python.org/pypi/pycrypto )
* PyCryptoPlus (下载链接: https : //github.com/doegox/python-cryptoplus )
库安装:
PyCrypto: 解压缩文件。转到目录并打开 linux 终端(alt + ctrl + t)和 CMD(shift +右键单击+在此处选择命令提示符)以获取 Windows。之后编写 python setup.py install(在 Windows 操作系统中正确设置了 Sure Python 环境)
PyCryptoPlus: 与最后一个库相同。
任务实施: 任务分为两部分。一个是握手过程,另一个是通信过程。套接字设置:
-
在创建公钥和私钥以及哈希公钥时,我们需要立即设置套接字。为了设置套接字,我们需要导入另一个带有
import socket
的模块并连接(用于客户端)或绑定(用于服务器)IP 地址和端口以及来自用户的套接字。- - - - - 客户端 - - - - -
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))
- - - - - 服务器端 - - - - -
try: #setting up socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((host,port)) server.listen(5) except BaseException: print "-----Check Server Address or Port-----"
“socket.AF_INET,socket.SOCK_STREAM”将允许我们使用
accept()
函数和消息传递基础。而不是它,我们也可以使用“socket.AF_INET,socket.SOCK_DGRAM”,但那时我们将不得不使用setblocking(value)
。
握手过程:
- (CLIENT)第一项任务是创建公钥和私钥。要创建私钥和公钥,我们必须导入一些模块。它们是:从 Crypto 导入 Random 和从 Crypto.PublicKey 导入 RSA。要创建密钥,我们必须编写几行简单的代码:
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
random_generator 派生自来自加密导入随机模块。密钥源自来自 Crypto.PublicKey 导入 RSA,它将通过生成随机字符来创建大小为 1024 的私钥。Public 从先前生成的私钥导出公钥。
-
(CLIENT)创建公钥和私钥后,我们必须使用 SHA-1 哈希对公钥进行哈希处理以发送到服务器。要使用 SHA-1 哈希,我们需要通过编写
import hashlib
来导入另一个模块。要哈希公钥,我们写了两行代码:hash_object = hashlib.sha1(public) hex_digest = hash_object.hexdigest()
这里 hash_object 和 hex_digest 是我们的变量。在此之后,客户端将发送 hex_digest 和 public 到服务器,Server 将通过比较从客户端获得的散列和公钥的新散列来验证它们。如果新哈希和来自客户端的哈希匹配,它将转移到下一个过程。由于从客户端发送的公共字符串形式,它将无法用作服务器端的密钥。为了防止这种情况并将字符串公钥转换为 rsa 公钥,我们需要编写 server_public_key = RSA.importKey(getpbk)
,这里 getpbk 是来自客户端的公钥。
-
(服务器)下一步是创建会话密钥。在这里,我使用
os
模块创建一个随机密钥“key =os.urandom(16)
”,这将给我们一个 16 位长的密钥,之后我在“AES.MODE_CTR”中加密了该密钥并再次哈希使用 SHA-1:#encrypt CTR MODE session key en = AES.new(key_128,AES.MODE_CTR,counter = lambda:key_128) encrypto = en.encrypt(key_128) #hashing sha1 en_object = hashlib.sha1(encrypto) en_digest = en_object.hexdigest()
所以 en_digest 将是我们的会话密钥。
-
(SERVER)握手过程的最后一部分是加密从客户端获得的公钥和在服务器端创建的会话密钥。
#encrypting session key and public key E = server_public_key.encrypt(encrypto,16)
加密后,服务器将密钥作为字符串发送给客户端。
-
(CLIENT)从服务器获取(公共密钥和会话密钥)的加密字符串后,客户端将使用先前与公钥一起创建的私钥对它们进行解密。由于加密(公共和会话密钥)是字符串形式,现在我们必须使用
eval()
将其作为密钥取回。如果解密完成,则握手过程也完成,因为双方都确认他们正在使用相同的密钥。要解密:en = eval(msg) decrypt = key.decrypt(en) # hashing sha1 en_object = hashlib.sha1(decrypt) en_digest = en_object.hexdigest()
我在这里使用了 SHA-1,以便在输出中可读。
沟通过程:
对于通信过程,我们必须使用来自两侧的会话密钥作为 IDEA 加密 MODE_CTR 的 KEY。双方将使用会话密钥使用 IDEA.MODE_CTR 加密和解密消息。
-
(加密)对于 IDEA 加密,我们需要大小为 16bit 的密钥和必须可调用的计数器。计数器在 MODE_CTR 中是必需的。我们加密和散列的会话密钥现在大小为 40,它将超过 IDEA 加密的限制密钥。因此,我们需要减小会话密钥的大小。为了减少,我们可以使用普通的 python 内置函数 string [value:value]。其中值可以是根据用户选择的任何值。在我们的例子中,我已经完成了“key [:16]”,它将从键中获取 0 到 16 个值。这种转换可以通过密钥[1:17]或密钥[16:]等多种方式完成。接下来的部分是通过编写
IDEA.new()
来创建新的 IDEA 加密函数,它将需要 3 个参数进行处理。第一个参数将是 KEY,第二个参数将是 IDEA 加密的模式(在我们的例子中,IDEA。MODE_CTR)和第三个参数将是 counter =,它是必须可调用的函数。counter =将保持函数返回的字符串大小。要定义 counter =,我们必须使用合理的值。在这种情况下,我通过定义 lambda 使用了 KEY 的大小。我们可以使用 Counter.Util 而不是使用 lambda,它为 counter =生成随机值。要使用 Counter.Util,我们需要从 crypto 导入计数器模块。因此,代码将是: 要使用 Counter.Util,我们需要从 crypto 导入计数器模块。因此,代码将是: 要使用 Counter.Util,我们需要从 crypto 导入计数器模块。因此,代码将是:ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
一旦将 ideaEncrypt
定义为我们的 IDEA 加密变量,我们就可以使用内置的加密函数来加密任何消息。
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable eMsg =
eMsg.encode("hex").upper()
在此代码段中,whole 是要加密的消息,eMsg 是加密消息。加密消息后,我将其转换为 HEXADECIMAL 以使其可读,而 upper()
是内置函数,使字符变为大写。之后,该加密消息将被发送到对方站进行解密。
- (解密)
要解密加密的消息,我们需要使用相同的参数和相同的密钥创建另一个加密变量,但这次变量将解密加密的消息。与上次相同的代码。但是,在解密消息之前,我们需要解码来自十六进制的消息,因为在我们的加密部分中,我们用十六进制编码加密消息以使其可读。因此,整个代码将是:
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
这些过程将在服务器端和客户端完成,以进行加密和解密。