PyCryptodome RSA签名和验证

时间:2018-02-03 19:30:22

标签: python sockets pycrypto pycryptodome

我正在研究一个使用套接字模块在python中通过互联网传输数据的程序。我现在正尝试使用pycryptodome模块实现加密。我正在使用Salsa20传输正常消息并传输Salsa20密钥我正在使用RSA。问题是代码在验证哈希时引发了ValueError。这是协议:

  1. 客户端连接到服务器(并生成Salsa20密钥)
  2. 服务器生成RSA密钥对并将公钥发送到客户端
  3. 客户端生成自己的密钥对并发送公钥
  4. 客户端使用公钥
  5. 加密Salsa20密钥
  6. 客户端签名并发送加密的Salsa20密钥哈希
  7. 客户端发送加密的Salsa20密钥
  8. 服务器对未签名的加密密钥进行哈希处理,并验证它是否与签名的密钥相同(这是问题发生的行)
  9. 服务器解密未签名密钥
  10. 我反复检查和打印,哈希是一样的。套接字不是问题。

    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
    

    客户端具有相同的套接字相关功能和导入的模块。

    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
    

    您认为验证不起作用的原因是什么?谢谢你的帮助。

1 个答案:

答案 0 :(得分:3)

客户端正在发回服务器的公钥而不是自己的公钥。 这一行:

 send_message(rsa_server_key.publickey().exportKey(), connection)

应该是:

 send_message(rsa_client_key.publickey().exportKey(), connection)