Загрузка класса в базу данных и получение его обратно
Мне нужно загрузить класс ключа для шифрования в БД, после чего получить его обратно для дешифровки. Вот код генерации ключей:
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.backends import default_backend
def generate():
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
return private_key, public_key
def encrypt(data, key): #public_key кодирование
return key.encrypt(data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
def decrypt(data, key): #private_key декодирование
return key.decrypt(data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Когда я заношу ключ в базу данных, он превращается в строку, по типу: <cryptography.hazmat.bindings._rust.openssl.rsa.RSAPrivateKey object at 0x"куча-цифр">
После получения ключа обратно и попытке дешифровки выходит ошибка:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\projects\pometki\database\database.py", line 37, in set_superkey
value = encrypt(value, keys[1])
^^^^^^^^^^^^^^^^^^^^^^^
File "D:\projects\pometki\crypter.py", line 17, in encrypt
return key.encrypt(data,
^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'encrypt'
То есть ключ должен быть объектом класса cryptography.hazmat.bindings._rust.openssl.rsa.RSAPrivateKey
Я пробовал использовать eval()
, но выходит ошибка
<cryptography.hazmat.bindings._rust.openssl.rsa.RSAPrivateKey object at "куча-цифр">
^
SyntaxError: invalid syntax
Как мне хранить эти ключи в базе данных, чтобы их можно было получить обратно?
(Вместо "куча-цифр" идут разные цифры, то есть вывод ошибки немного другой, просто не хочу чтобы мои ключи украли)
Код для использования базы данных:
from sqlite3 import connect as db_con
from crypter import *
def open_connect():
global connect, cursor
connect = db_con('database/database.db', check_same_thread=False)
cursor = connect.cursor()
def close_connect():
connect.close()
open_connect()
cursor.execute('CREATE TABLE IF NOT EXISTS system(superkey TEXT, private TEXT, public TEXT)')
cursor.execute('CREATE TABLE IF NOT EXISTS passwords(id INTEGER PRIMARY KEY, _type TEXT, data TEXT)')
def check_system_created():
cursor.execute('SELECT * FROM system')
return bool(cursor.fetchone())
def create_system(private, public):
cursor.execute(f'INSERT INTO system(private, public) VALUES("{private}", "{public}")')
connect.commit()
def access_to_keys():
global keys
cursor.execute('SELECT private, public FROM system')
data = cursor.fetchone()
keys = [eval(data[0]), eval(data[1])] #тут ошибка с eval
def get_superkey():
cursor.execute('SELECT superkey FROM system')
return decrypt(cursor.fetchone()[0], keys[0])
def set_superkey(value):
value = encrypt(value, keys[1])
cursor.execute(f'UPDATE system SET superkey={value}')
connect.commit()
Ответы (1 шт):
Я бы экспортировал ключ в формат DER, кодировал его в Base64 и сохранял получившуюся строку в базу данных.
Пример
import base64
from io import BytesIO, StringIO
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.serialization import load_der_private_key
def gen_key():
private_key = rsa.generate_private_key(
public_exponent=65537, key_size=2048, backend=default_backend()
)
return private_key
def export_key(pk:rsa.RSAPrivateKey) -> str:
der_bytes:bytes = pk.private_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
der_out = BytesIO()
base64.encode(BytesIO(der_bytes), der_out)
return str(der_out.getvalue(), "utf-8")
def import_key(b64_str:str) -> rsa.RSAPrivateKey:
input = StringIO(b64_str)
der_stream = BytesIO()
base64.decode(input, der_stream)
der_bytes : bytes = der_stream.getvalue()
private_key = load_der_private_key(der_bytes, None, default_backend())
return private_key
if __name__ == '__main__':
pk = gen_key()
der_b64 = export_key(pk)
print(der_b64)
pk2 = import_key(der_b64)
print(pk.public_key().public_numbers())
print(pk2.public_key().public_numbers())
Вывод:
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCcdJS7K/oz7p39onp4ErPZO9yN
BsRSmI5AjXKwQxNGOG4hNx+zk5UTCLwM4lF5WY+Iq0dkiAO2ed1FVMIC4dISFpwFdtceNwryxRpu
812M/OpSRkZTC7cBuhX7x16DONbJnNavhIFU2xcsT/6YHTeOdJifE3x8iECUB0/c8E1axslSr0Zn
NyPLY/lmV6yc43g5/rLlQDqUL4KaCVFOECjeZdjuNF+IQxhEC4R4+B7M8yuqFoKL22jwNXGC/JQF
VIgf11lNCj0AwCrzoIcwU6UmeIbPtFbOPG0Bb6frr2hs/fmQ0TvjfoSIPecZt1cmANXEijn018Tv
eGIMUtM1+MovAgMBAAECggEAM8gH87zV5fs7Mhdk9jmmaab803YiYv3X0vidtUW16t9BX9/pL5uQ
UsjoyFDdS07/iOm7SsQTioDh4ZDwV1jbGJ6AC/TttLPd/USL/52vYDrS6OEWZGTzsHAg14CAQOj+
eaLdkSDHV0jd7g4ZwsmkuhLP8pJV+Ld1vCiBX6vuxjSRJ/BxFPu17XsRRgFmOvrW6Wyfznl9JEkK
CehWddHRVVqplg2R1x6DYBz6u9Qh90kOm9qetOGyJQm1spgG84+lMfXsruV/T+KweFCKt3uwoWSc
1yXVhKioBwqlJiCRaaSs7tb7uJ+YaVUZaB1z/QY16qhcj+A44QKc2nNnyHV98QKBgQDNM8aN41Qy
MjiiONNi03PWzeOCu1ag2O6Vnwaf//PtSsRbiv/V69C6IdVXc6HlaxmFJcM6AMkxu7pQ5SIAQLpz
wJ7HdWdwJ2G3vJPFC/GiXFvNXLcfI6BN88UvDnHa8lOA8M7e56lRuX5PK8EZrP8JtAVTHMWgnqbk
JncTnU8h/wKBgQDDL5WvSV3ib5VmWtX/1yBCvAIO37aVUGqH//IEcf4BRVJqFop3WDyK/LeURsPX
ZMzvQxW4qP9O0aAyK0qIxeMfIm5pGkChmb+CQdTI/LpWtySTftezmP+kklWs7uZxzlH+W52EUeLj
iyTlhZtQLgSi5LYUaowQRcDwxpvFT2/30QKBgQC2sV4ZfUe82RGq/ETXO8NqfywLfJcH5ZulAkx3
rv2RSnu/tOVJpAXVccHrdjuxccTq0lAaGBEIgkbDNv0qlHZsEBZNJq3NIILTfsVhLd0X3HqvP9iZ
lLJoNJxd5NJhSFYn+j10H3SUGj3mZuIo5ei6ztfew0MAWb/kaIqjn+6QKQKBgFISXyleeyisbLCm
P1edeIY3EdJ5RQfR0YmwGG7AE+Mq5/WN1tlJ8+MpUnP5sX2PeBCfL7H+9aOJx4dw5p1OQCsmSjDN
hiGtSXaXAcclZaDyz2Fps39kNRJZKcdWiPWPoLCIi1pJKFMvfes4287CGtb3vowlJRHukqtrh7JW
rakRAoGBAMMbKKWtB2tUufgr9hUY0j+b72JloifeQMvbIBtlpiis0cOTvSYBULE5BOR0YFW7dQ4O
po47Do3yxPoxmtWkFZBhJslrihqGS/8jgn9mr0Bly3jp/7qihroQwjMeD3F+tl+oUxGuNBbjQygu
8/PzQj7hMnU5g1+pgPl5DKITfj2R
<RSAPublicNumbers(e=65537, n=19750663799059011431450533745957882752508425212326669741021428051212326057048447128244195037706584596016889765513008789884210476698663712374152024103707892971118728814980164673018765444797534164872839823161103419020351009532442634727419039775930437020478011146255231180674249845766337417763637002501946987667514481506884063226382898497051915292139340515604749232490204577835979908946819971364137982200857630230821862118353079729961828028765851896539395307986354805888072535098749547221258754910087430202835613866707226473281493782352899805868851928502952881946566307177860644277936566436649809472760294454972883978799)>
<RSAPublicNumbers(e=65537, n=19750663799059011431450533745957882752508425212326669741021428051212326057048447128244195037706584596016889765513008789884210476698663712374152024103707892971118728814980164673018765444797534164872839823161103419020351009532442634727419039775930437020478011146255231180674249845766337417763637002501946987667514481506884063226382898497051915292139340515604749232490204577835979908946819971364137982200857630230821862118353079729961828028765851896539395307986354805888072535098749547221258754910087430202835613866707226473281493782352899805868851928502952881946566307177860644277936566436649809472760294454972883978799)>
Видно, что публичные ключи для pk
и восстановленного из DER pk2
совпадают. Поэтому и сами приватные ключи равны.