两个用户之间的消息加密

问题描述

我正在编写一个 python 脚本来练习密码学。我想与可以向自己发送消息的用户创建一个小程序,这些消息必须加密和解密。我创建了 3 个类。第一个包含两个函数,我可以使用它们encryptdecrypt 使用公钥和私钥发送消息。第二个类是 Message 类,它有 4 个属性(消息的 sendertextrecipienttimestamp)。使用类方法 __str__,我创建了必须以这种格式发送的实际消息:From {the name of the sender}: {Message} {timestamp}。第三类是User。使用 User,我可以使用 namepublicprivate 密钥、一个用于接收加密消息的收件箱和一个名为 messages 的列表来初始化每个用户,用于存储收到的每条消息和解密。每个用户都可以向另一个用户发送消息,方法是用接收者的公钥加密消息,然后接收者可以用他自己的私钥解密加密的消息。我想通过使用 2 个函数 send 来做到这一点,它加密消息并将其发送到收件人收件箱。此函数必须由发送者使用,send 函数运行接收者的 receive 函数,该函数迭代新消息、decryptsappends 消息({ {1}}) 到消息列表。

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

我尝试使用 From {sender.name} ...encrypt 函数只是为了加密和解密一个简单的字符串(没有我添加用户和其他内容)并且实际工作。

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

我是密码学的绝对初学者,我可能使用过不好的做法。

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

decrypt

错误

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,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'

解决方法

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

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

第一个在 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,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 具有延展性,所以必须使用加密来为明文添加一些随机性,请参阅此 {{3} }.