PyCryptodome RSA 签名和验证
PyCryptodome RSA signature and verification
我正在开发一个程序,该程序使用套接字模块在 python 中通过互联网传输数据。我现在正在尝试使用 pycryptodome 模块实现加密。我正在使用 Salsa20 传输普通消息并传输我正在使用 RSA 的 Salsa20 密钥。问题是代码在验证散列时引发了 ValueError。这是协议:
- 客户端连接到服务器(并生成一个Salsa20密钥)
- 服务器生成RSA密钥对,发送public密钥给客户端
- 客户端生成自己的密钥对并发送public密钥
- 客户端用public密钥
加密Salsa20密钥
- 客户端签名并发送加密的 Salsa20 密钥的哈希值
- 客户端发送加密的Salsa20密钥
- 服务器对未签名的加密密钥进行哈希处理,并验证它与已签名的密钥相同(这是出现问题的行)
- 服务器解密未签名的密钥
我反复检查打印,hash都是一样的。插座不是问题。
recv_message和send_message函数是我用来打包发送和接收协议的函数。在程序中套接字是预先设置的,所以这里是服务器的重要部分。
import socket
from Crypto.Cipher import Salsa20, PKCS1_OAEP
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
def send_message(message_to_send, connection):
if type(message_to_send) is bytes:
message = message_to_send
else:
message = str(message_to_send).encode()
length_of_msg = str(len(message))
length_of_msg = ('0' * (5-len(length_of_msg))) + length_of_msg # This part is adding zeros as padding so that the first message is always 5 chars
connection.send(length_of_msg.encode())
connection.send(message)
def recv_message(connection, no_decode=False):
length_of_msg = int(connection.recv(5))
message = connection.recv(length_of_msg)
if not no_decode:
message = message.decode('utf-8')
return message
def get_key(connection):
rsa_server_key = RSA.generate(2048)
send_message(rsa_server_key.publickey().exportKey(), connection)
rsa_client_key = RSA.import_key(recv_message(connection, no_decode=True))
key_signed = recv_message(connection, no_decode=True)
key_unsigned = recv_message(connection, no_decode=True)
hash_verify = pkcs1_15.new(rsa_client_key)
hash_verify.verify(SHA256.new(data=key_unsigned), key_signed)
rsa_cipher = PKCS1_OAEP.new(rsa_server_key)
key = rsa_cipher.decrypt(key_unsigned)
return key
客户端有相同的socket相关功能和导入模块
def share_key(key_to_send, connection):
rsa_server_key = RSA.import_key(recv_message(connection, no_decode=True))
rsa_client_key = RSA.generate(2048)
send_message(rsa_server_key.publickey().exportKey(), connection)
rsa_cipher = PKCS1_OAEP.new(rsa_server_key)
salsa_key_unsigned = rsa_cipher.encrypt(key_to_send)
key_signer = pkcs1_15.new(rsa_client_key)
send_message(key_signer.sign(SHA256.new(data=salsa_key_unsigned)), connection)
send_message(salsa_key_unsigned, connection)
追溯是:
Traceback (most recent call last):
File "0,9Serverside.py", line 686, in <module>
main()
File "0,9Serverside.py", line 670, in main
key_input = get_key(server)
File "0,9Serverside.py", line 243, in get_key
hash_verify.verify(SHA256.new(data=salsa_key_unsigned), salsa_key_signature)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/Crypto/Signature/pkcs1_15.py", line 139, in verify
raise ValueError("Invalid signature")
ValueError: Invalid signature
您认为验证无效的原因可能是什么。谢谢你的帮助。
客户端发回服务器的 public 密钥而不是它自己的 public 密钥。
该行:
send_message(rsa_server_key.publickey().exportKey(), connection)
应该是:
send_message(rsa_client_key.publickey().exportKey(), connection)
我正在开发一个程序,该程序使用套接字模块在 python 中通过互联网传输数据。我现在正在尝试使用 pycryptodome 模块实现加密。我正在使用 Salsa20 传输普通消息并传输我正在使用 RSA 的 Salsa20 密钥。问题是代码在验证散列时引发了 ValueError。这是协议:
- 客户端连接到服务器(并生成一个Salsa20密钥)
- 服务器生成RSA密钥对,发送public密钥给客户端
- 客户端生成自己的密钥对并发送public密钥
- 客户端用public密钥 加密Salsa20密钥
- 客户端签名并发送加密的 Salsa20 密钥的哈希值
- 客户端发送加密的Salsa20密钥
- 服务器对未签名的加密密钥进行哈希处理,并验证它与已签名的密钥相同(这是出现问题的行)
- 服务器解密未签名的密钥
我反复检查打印,hash都是一样的。插座不是问题。
recv_message和send_message函数是我用来打包发送和接收协议的函数。在程序中套接字是预先设置的,所以这里是服务器的重要部分。
import socket
from Crypto.Cipher import Salsa20, PKCS1_OAEP
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
def send_message(message_to_send, connection):
if type(message_to_send) is bytes:
message = message_to_send
else:
message = str(message_to_send).encode()
length_of_msg = str(len(message))
length_of_msg = ('0' * (5-len(length_of_msg))) + length_of_msg # This part is adding zeros as padding so that the first message is always 5 chars
connection.send(length_of_msg.encode())
connection.send(message)
def recv_message(connection, no_decode=False):
length_of_msg = int(connection.recv(5))
message = connection.recv(length_of_msg)
if not no_decode:
message = message.decode('utf-8')
return message
def get_key(connection):
rsa_server_key = RSA.generate(2048)
send_message(rsa_server_key.publickey().exportKey(), connection)
rsa_client_key = RSA.import_key(recv_message(connection, no_decode=True))
key_signed = recv_message(connection, no_decode=True)
key_unsigned = recv_message(connection, no_decode=True)
hash_verify = pkcs1_15.new(rsa_client_key)
hash_verify.verify(SHA256.new(data=key_unsigned), key_signed)
rsa_cipher = PKCS1_OAEP.new(rsa_server_key)
key = rsa_cipher.decrypt(key_unsigned)
return key
客户端有相同的socket相关功能和导入模块
def share_key(key_to_send, connection):
rsa_server_key = RSA.import_key(recv_message(connection, no_decode=True))
rsa_client_key = RSA.generate(2048)
send_message(rsa_server_key.publickey().exportKey(), connection)
rsa_cipher = PKCS1_OAEP.new(rsa_server_key)
salsa_key_unsigned = rsa_cipher.encrypt(key_to_send)
key_signer = pkcs1_15.new(rsa_client_key)
send_message(key_signer.sign(SHA256.new(data=salsa_key_unsigned)), connection)
send_message(salsa_key_unsigned, connection)
追溯是:
Traceback (most recent call last):
File "0,9Serverside.py", line 686, in <module>
main()
File "0,9Serverside.py", line 670, in main
key_input = get_key(server)
File "0,9Serverside.py", line 243, in get_key
hash_verify.verify(SHA256.new(data=salsa_key_unsigned), salsa_key_signature)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/Crypto/Signature/pkcs1_15.py", line 139, in verify
raise ValueError("Invalid signature")
ValueError: Invalid signature
您认为验证无效的原因可能是什么。谢谢你的帮助。
客户端发回服务器的 public 密钥而不是它自己的 public 密钥。 该行:
send_message(rsa_server_key.publickey().exportKey(), connection)
应该是:
send_message(rsa_client_key.publickey().exportKey(), connection)