两个用户之间的消息加密

Message encryption between two users

我正在编写 python 脚本只是为了练习密码学。我想创建一个小程序,用户可以向自己发送必须加密和解密的消息。我创建了 3 classes。第一个包含 2 个函数,我可以使用 encryptdecrypt 使用 public 和私钥发送消息。第二个class是Messageclass,它有4个属性(sender,消息的textrecipient和一个timestamp)。使用 class 方法 __str__,我创建了必须以这种格式发送的实际消息:From {the name of the sender}: {Message} {timestamp}。第三个class是User。使用 User,我可以使用 namepublicprivate 密钥初始化每个用户,一个接收加密消息的收件箱和一个名为 messages 的列表来存储收到的每条消息和解密。每个用户都可以通过使用收件人的 public 密钥加密消息来将消息发送给另一个用户,然后收件人可以使用自己的私钥解密加密的消息。我想通过使用 2 个函数 send 来完成此操作,这两个函数会对消息进行加密并将其发送到收件人的收件箱中。此函数必须由发件人使用,send 函数 运行 是收件人的 receive 函数,它遍历新消息,decryptsappends 消息 (From {sender.name} ...) 到消息列表。

然后我尝试通过创建 2 个用户(Bob 和 Alice)来 运行 程序并发送一些消息。但是我遇到了一些错误。

我尝试使用 encryptdecrypt 函数来加密和解密一个简单的字符串(没有用户和我添加的其他东西)并且确实有效。

我在这里找到了两个函数(加密和解密):https://medium.com/@securegns/implementing-asymmetric-encryption-to-secure-your-project-35368049cb5f

我是密码学的绝对初学者,我可能使用了错误的做法。

可能是什么问题?我想不通

import Crypto
from Crypto.PublicKey import RSA
from Crypto import Random
import base64
import datetime

class Crypt:

    @staticmethod
    def encrypt(public_key, text):
        cipher_text = public_key.encrypt(text, 32)[0]
        b64cipher = base64.b64encode(cipher_text)
        return b64cipher
    
    @staticmethod
    def decrypt(private_key, b64cipher):
        decoded_ciphertext = base64.b64decode(b64cipher)
        plain_text = private_key.decrypt(decoded_ciphertext)
        return plain_text

class Message:
    def __init__(self, sender, txt, recipient):
        self.sender = sender
        self.txt = txt
        self.recipient = recipient
        self.timestamp = datetime.datetime.now().date()

    def __str__(self):
        return f"From {self.sender}: {self.txt} {self.timestamp}"


class User:
    def __init__(self, name):
        random = Random.new().read
        self.name = name
        self.private_key = RSA.generate(1024, random)
        self.public_key = self.private_key.publickey()
        self.inbox = []
        self.messages = []

    def receive(self):
        # Decrypts encrypted messages in the inbox and transfers the decrypted messages into the messages 
          list
        for i in self.inbox:
            message = Crypt.decrypt(self.private_key, i)
            self.messages.append(message)
            self.inbox.pop()
        return self.messages

    def send(self, msg, recipient): 
        # User use send function and encrypts the message with the recipient's public key and appends into the recipient's inbox the encrypted message
        message = Message(self.name, msg, recipient)
        b64cipher = Crypt.encrypt(recipient.public_key, message.__str__())
        self.messages.append(message.__str__())
        recipient.inbox.append(b64cipher)
        recipient.receive()

Bob = User("Bob")

Alice = User("Alice")

Bob.send("Hi", Alice)
Alice.send("Hi Bob!", Bob)
Bob.send("How are you?", Alice)

错误


File "\encrypt.py", line 59, in send
    b64cipher = Crypt.encrypt(recipient.public_key, message.__str__())

File \encrypt.py", line 11, in encrypt
    cipher_text = public_key.encrypt(text, 32)[0]


File "Crypto\PublicKey\RSA.py", line 150, in encrypt
    return pubkey.pubkey.encrypt(self, plaintext, K)

File "\Crypto\PublicKey\pubkey.py", line 75, in encrypt
    ciphertext=self._encrypt(plaintext, K)

File "\Crypto\PublicKey\RSA.py", line 224, in _encrypt
    return (self.key._encrypt(c),)

File "\Crypto\PublicKey\_slowmath.py", line 65, in _encrypt
    return pow(m, self.e, self.n)
TypeError: unsupported operand type(s) for pow(): 'str', 'int', 'int'

解决方案

import Crypto
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from  Crypto.Cipher import PKCS1_OAEP
from Crypto import Random
import base64
import datetime


class Crypt:

    @staticmethod
    def encrypt(public_key, text):
        oaep = PKCS1_OAEP.new(public_key, SHA256)
        ciphertext = oaep.encrypt(bytes(text, encoding="ASCII"))
        # cipher_text = public_key.encrypt(text, 32)[0]
        b64cipher = base64.b64encode(ciphertext)
        return b64cipher

    @staticmethod
    def decrypt(private_key, b64cipher):
        decoded_ciphertext = base64.b64decode(b64cipher)
        oaep = PKCS1_OAEP.new(private_key, SHA256)
        plaintext = oaep.decrypt(decoded_ciphertext)

        # plain_text = private_key.decrypt(decoded_ciphertext)
        print("Decrypted Plaintext: {}".format(plaintext))
        return plaintext


class Message:
    def __init__(self, sender, txt, recipient):
        self.sender = sender
        self.txt = txt
        self.recipient = recipient
        self.timestamp = datetime.datetime.now().date()

    def __str__(self):
        return f"From {self.sender}: {self.txt} {self.timestamp}"


class User:
    def __init__(self, name):
        random = Random.new().read
        self.name = name
        self.private_key = RSA.generate(1024, random)
        self.public_key = self.private_key.publickey()
        self.inbox = []
        self.messages = []

    def receive(self):
        # Decrypts encrypted messages in the inbox and transfers the decrypted messages into the messages
        list
        for i in self.inbox:
            message = Crypt.decrypt(self.private_key, i)
            self.messages.append(message)
            self.inbox.pop()
            return self.messages

    def send(self, msg, recipient):
        # User use send function and encrypts the message with the recipient's public key and appends into the recipient's inbox the encrypted message
        message = Message(self.name, msg, recipient)
        b64cipher = Crypt.encrypt(recipient.public_key, message.__str__())
        self.messages.append(message.__str__())
        recipient.inbox.append(b64cipher)
        recipient.receive()


Bob = User("Bob")
Alice = User("Alice")
Bob.send("Hi", Alice)
Alice.send("Hi Bob!", Bob)
Bob.send("How are you?", Alice)

您是否正在使用 https://github.com/pycrypto/pycrypto 并且您的 python 版本是 >3.5? 它说 PyCrypto 是使用 Python 版本 2.1 到 3.3 编写和测试的。

请更新至https://github.com/Legrandin/pycryptodome,然后查看是否有效。 第二个库负责在调用 pow() 之前转换为 Integar。

第一个也在 this file 中进行了检查,但他们似乎正在使用 types.StringType,在 python 2.7 之后不再存在。他们在安装过程中使用 2to3 使其与 python3 一起使用,但 types.StringType 转换为字节,但在最新的 python.

上失败
-if isinstance(plaintext, types.StringType):
+if isinstance(plaintext, bytes):

同时检查 this reddit post 是否有其他加密库

这是你修改后的代码

import Crypto
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from  Crypto.Cipher import PKCS1_OAEP
from Crypto import Random
import base64
import datetime


class Crypt:

    @staticmethod
    def encrypt(public_key, text):
        oaep = PKCS1_OAEP.new(public_key, SHA256)
        ciphertext = oaep.encrypt(bytes(text, encoding="ASCII"))
        # cipher_text = public_key.encrypt(text, 32)[0]
        b64cipher = base64.b64encode(ciphertext)
        return b64cipher

    @staticmethod
    def decrypt(private_key, b64cipher):
        decoded_ciphertext = base64.b64decode(b64cipher)
        oaep = PKCS1_OAEP.new(private_key, SHA256)
        plaintext = oaep.decrypt(decoded_ciphertext)

        # plain_text = private_key.decrypt(decoded_ciphertext)
        print("Decrypted Plaintext: {}".format(plaintext))
        return plaintext


class Message:
    def __init__(self, sender, txt, recipient):
        self.sender = sender
        self.txt = txt
        self.recipient = recipient
        self.timestamp = datetime.datetime.now().date()

    def __str__(self):
        return f"From {self.sender}: {self.txt} {self.timestamp}"


class User:
    def __init__(self, name):
        random = Random.new().read
        self.name = name
        self.private_key = RSA.generate(1024, random)
        self.public_key = self.private_key.publickey()
        self.inbox = []
        self.messages = []

    def receive(self):
        # Decrypts encrypted messages in the inbox and transfers the decrypted messages into the messages
        list
        for i in self.inbox:
            message = Crypt.decrypt(self.private_key, i)
            self.messages.append(message)
            self.inbox.pop()
            return self.messages

    def send(self, msg, recipient):
        # User use send function and encrypts the message with the recipient's public key and appends into the recipient's inbox the encrypted message
        message = Message(self.name, msg, recipient)
        b64cipher = Crypt.encrypt(recipient.public_key, message.__str__())
        self.messages.append(message.__str__())
        recipient.inbox.append(b64cipher)
        recipient.receive()


Bob = User("Bob")
Alice = User("Alice")
Bob.send("Hi", Alice)
Alice.send("Hi Bob!", Bob)
Bob.send("How are you?", Alice)

它打印出正确的明文。我使用 OAEP 进行加密和解密,因为不建议在 RSA 中单独加密明文,因为 RSA 具有延展性,因此必须使用为明文添加一些随机性的加密,请参阅此 link.