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