Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 来自sqlite的RSA加密字符串的解密不同_Python_Sqlite_Cryptography_Rsa_Pycrypto - Fatal编程技术网

Python 来自sqlite的RSA加密字符串的解密不同

Python 来自sqlite的RSA加密字符串的解密不同,python,sqlite,cryptography,rsa,pycrypto,Python,Sqlite,Cryptography,Rsa,Pycrypto,我正在使用带有私钥/公钥的RSA。我试图加密字符串,将其保存在数据库(sqlite)中,然后再次检索并加密 当数据从sqlite中出来时,我无法再次解密数据。字符串是一样的,我有点迷路了 #!/usr/bin/env python3 from Crypto.PublicKey import RSA from Crypto import Random import sqlite3 import base64 # database layout # # CREATE TABLE secret

我正在使用带有私钥/公钥的RSA。我试图加密字符串,将其保存在数据库(sqlite)中,然后再次检索并加密

当数据从sqlite中出来时,我无法再次解密数据。字符串是一样的,我有点迷路了

#!/usr/bin/env python3

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


# database layout
# 
# CREATE TABLE secrets ( id INT, secret TEXT );
# INSERT INTO secrets (id,secret) VALUES (1,"");

# database
conn = sqlite3.connect('database.db')
c = conn.cursor()

# generate keys
private_key = RSA.generate(1024, Random.new().read)
public_key = private_key.publickey()

# save keys
f = open('public.pem', 'wb+')
f.write(public_key.exportKey('PEM'))
f.close()

f = open('private.pem', 'wb+')
f.write(private_key.exportKey('PEM'))
f.close()

# crypt
f = open('public.pem','rb')
encrypt_public_key = RSA.importKey(f.read())

secret = "123456"

enc_secret = encrypt_public_key.encrypt(secret.encode("utf-8"), 32)[0]
enc_secret_encoded = base64.b64encode(enc_secret)

print("Base64: " + str(enc_secret_encoded))

# save in db
c.execute('UPDATE secrets SET secret="%s" WHERE id=1' % (enc_secret_encoded))
conn.commit()

print("--------------- DECRYPTION ------------------------")

# decrypt
p = open('private.pem','rb')
decrypt_private_key = RSA.importKey(p.read())

c.execute('SELECT secret FROM secrets WHERE id=1')
result = c.fetchone()
encoded_secret = result[0]

print("Base64: " + encoded_secret)

decoded_secret = base64.b64decode(encoded_secret)
enc_secret = decrypt_private_key.decrypt(decoded_secret)

print("Decrypted: " + str(enc_secret))

输出:

$ ./stuck.py
Base64: b'bfAERXPFvrDRdr5Pcexu8JgHlKfDaUhkqJrSWZJbLwlKLWY8XHtIlBwrRfP7eMX9PTKo4t2CtpdXS6Fam4B+jR3/bYPxji0rHt1Aed64sLH4xAnxgh5B/qWidcYT5cPmvwMekGbCaMSgGjvNB4Js/yDRrW4+N8dqx3IoUAl8zgA='
--------------- DECRYPTION ------------------------
Base64: b'bfAERXPFvrDRdr5Pcexu8JgHlKfDaUhkqJrSWZJbLwlKLWY8XHtIlBwrRfP7eMX9PTKo4t2CtpdXS6Fam4B+jR3/bYPxji0rHt1Aed64sLH4xAnxgh5B/qWidcYT5cPmvwMekGbCaMSgGjvNB4Js/yDRrW4+N8dqx3IoUAl8zgA='
Decrypted: b'\x90\x07\xa2}\x96w\xda\xd3h\xf1\xd4\xc6z\xa5\xf3\x85\x97\xeb\xcfL\x0e\x1f;\x18\xd5\x98\xb3\xb2\xd0\x93.\xc9z\x1c\xc8\xac\xe4x\xbfT\xe4{\x1b\x19\xda\xfb/?A\xda_\xceHc\xd14X\x94\x8a\x94\xfc\x12\xc4\x86\xc9\x16\xc9b\xbf\xdaJ\xcf\xff\xe1J\x95\x03&\xda\x98\x9f\x10\xb1\tzW\xea\x9b\xd2\x13\xc1\x8d\x19\xe97\xd6\xeay\xf3\x83\xb7\xcf\xd3v\\`~\x07\xcea(\x81\xe1c\x08\x0b\x8c\xee\xc2\x87\xed\xc8\x08D\x8e\xe5\x83\xf4'
当您运行我的示例时,您将看到相同的加密字符串进入sqlite并再次退出,但是为什么我不能再次解密它并获得与
secret
相同的结果呢

更新:当我删除sqlite数据库时,它会按预期工作。因此,问题一定出在存储或检索数据的某个地方


非常感谢您的提示。

您在解码时获得了错误的base64/RSA顺序。这项工作:

#!/usr/bin/env python3

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

key_pair = RSA.generate(1024, Random.new().read(1024 // 8))
public_key = key_pair.publickey()

secret = "123456"

enc_secret = public_key.encrypt(secret.encode("utf-8"), 32)[0]
enc_secret_b64 = base64.b64encode(enc_secret)
print(enc_secret_b64)

enc_secret = base64.b64decode(enc_secret_b64)
secret = key_pair.decrypt(enc_secret)
print(secret.decode("utf-8"))
# 123456
还请注意,您需要调用
随机方法的
read
方法


除此之外:这不是RSA的目的。如果要使用RSA加密数据,则应仅将RSA用于密钥封装,并使用对称密码系统(例如AES)加密数据。

解码时,您的base64/RSA顺序错误。这项工作:

#!/usr/bin/env python3

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

key_pair = RSA.generate(1024, Random.new().read(1024 // 8))
public_key = key_pair.publickey()

secret = "123456"

enc_secret = public_key.encrypt(secret.encode("utf-8"), 32)[0]
enc_secret_b64 = base64.b64encode(enc_secret)
print(enc_secret_b64)

enc_secret = base64.b64decode(enc_secret_b64)
secret = key_pair.decrypt(enc_secret)
print(secret.decode("utf-8"))
# 123456
还请注意,您需要调用
随机方法的
read
方法

除此之外:这不是RSA的目的。如果要使用RSA加密数据,则应仅将RSA用于密钥封装,并使用对称加密系统(如AES)加密数据。

编码时返回的是
字节而不是字符串(这有点奇怪,因为base 64编码的全部目的是创建可打印字符串)

这意味着,当您将结果转换为字符串以保存在sqlite中时,它的格式为
b'XXX…XX'
,即,它保存为以
b
开头的字符串,并在实际的base64编码数据周围加上引号

解码时,默认值是丢弃任何非base64字符。因此,这会删除引号,但不会删除首字母
b
。这意味着您正在解码的数据前面有一个额外的
b
,因此您最终尝试解密错误的密码文本

您可以通过将
validate=True
添加到对base 64数据进行解码的调用中,以强制其验证输入来看到这一点。由于
字符,这将导致一个
binascii.Error

enc_secret = base64.b64decode(enc_secret_b64, validate=True)
修复方法是在保存到sqlite之前,将bytes对象从base 64编码解码为ASCII字符串。然后,只有“真实”的基本64个字符将保存到数据库中:

enc_secret_encoded = base64.b64encode(enc_secret).decode("ASCII")
编码时,返回一个
字节
对象而不是字符串(这有点奇怪,因为base 64编码的整个要点是创建一个可打印的字符串)

这意味着,当您将结果转换为字符串以保存在sqlite中时,它的格式为
b'XXX…XX'
,即,它保存为以
b
开头的字符串,并在实际的base64编码数据周围加上引号

解码时,默认值是丢弃任何非base64字符。因此,这会删除引号,但不会删除首字母
b
。这意味着您正在解码的数据前面有一个额外的
b
,因此您最终尝试解密错误的密码文本

您可以通过将
validate=True
添加到对base 64数据进行解码的调用中,以强制其验证输入来看到这一点。由于
字符,这将导致一个
binascii.Error

enc_secret = base64.b64decode(enc_secret_b64, validate=True)
修复方法是在保存到sqlite之前,将bytes对象从base 64编码解码为ASCII字符串。然后,只有“真实”的基本64个字符将保存到数据库中:

enc_secret_encoded = base64.b64encode(enc_secret).decode("ASCII")

我认为您不应该使用RSA密钥直接加密/解密数据。在中找不到
RsaKey.encode
Rsa.decode
。尝试使用基于RSA的混合加密方案,如图所示。对于RSA,您需要至少2048位的安全性。这将使您的数据非常庞大。你为什么不用AES?另外,在您的RSA中,您不使用填充方案,因为这种方案对许多攻击都是脆弱的。@kelalaka我同意这两种观点,这只是一个不太容易分心的例子,可以理解为什么它不起作用。我不认为您应该使用RSA密钥直接加密/解密数据。在中找不到
RsaKey.encode
Rsa.decode
。尝试使用基于RSA的混合加密方案,如图所示。对于RSA,您需要至少2048位的安全性。这将使您的数据非常庞大。你为什么不用AES?另外,在您的RSA中,您没有使用填充方案,因为这种方案会受到许多攻击。@kelalaka我同意这两种观点,这只是一个例子,不太容易让人分心,无法理解它为什么不起作用。您好,感谢您指出我缺少的.read(),但除此之外,代码完全相同,只是没有使用sqlite。当我从代码中删除sqlite存储时,它也在工作。ooops,你是对的。。。对不起,我好像误读了。。。此代码将解密为它应该。。。也许您可以添加
sqlite
并读/写
pem
,找出代码失败的地方。再次抱歉…您好,感谢您指出我缺少的.read(),但除此之外,代码完全相同,只是没有使用sqlite。当我从代码中删除sqlite存储时,它也在工作。ooops,你是对的。。。对不起,我好像误读了。。。此代码将解密为它应该。。。也许您可以添加
sqlite
并读/写
pem
,找出代码失败的地方。再次抱歉…哇。这正是问题所在。我没看见。非常感谢。哇。这正是问题所在。我没看见。谢谢。