Python中的加密数据库文件
我在Python中有一个SQLite数据库。这个应用程序可以正常运行,但我希望没有人能在没有密码的情况下读取这个数据库。我该如何在Python中实现这个功能呢?
4 个回答
5
你可以使用存储在内存(RAM)中的数据库,并且只保存你通过加密模块得到的加密版本。然后,你可以通过解密你存储的内容,重新在内存中创建这个数据库:
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
import base64
from os import getcwd
import sqlite3
import gzip
def key_creation(password):
kdf=PBKDF2HMAC(algorithm = hashes.SHA256(), salt=b'\xfaz\xb5\xf2|\xa1z\xa9\xfe\xd1F@1\xaa\x8a\xc2', iterations=1024, length=32, backend=default_backend())
key=Fernet(base64.urlsafe_b64encode(kdf.derive(password)))
return key
def encryption(b, password):
f=key_creation(password)
safe=f.encrypt(b)
return safe
def decryption(safe, password):
f=key_creation(password)
b=f.decrypt(safe)
return b
def open_cdb(name,password):
f=gzip.open(getcwd()+name+'_crypted.sql.gz','rb')
safe=f.read()
f.close()
content=decryption(safe,password)
content=content.decode('utf-8')
con=sqlite3.connect(':memory:')
con.executescript(content)
return con
def save_cdb(con,name,password):
fp=gzip.open(getcwd()+name+'_crypted.sql.gz','wb')
b=b''
for line in con.iterdump():
b+=bytes('%s\n','utf8') % bytes(line,'utf8')
b=encryption(b,password)
fp.write(b)
fp.close()
if __name__=='__main__':
password=b'Sw0rdFish'
name='PRODUCTS'
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE PRODUCTS (ID INT PRIMARY KEY NOT NULL,\nNAME TEXT NOT NULL,\nPRICE REAL NOT NULL,\nTAXES REAL NOT NULL);')
save_cdb(conn,name,password)
conn.close()
conn = open_cdb(name,password)
cursor = conn.execute('select * from ' + name)
headers = list(map(lambda x: x[0], cursor.description))
print(headers)
for x in cursor:
for j in range(len(x)):
print(headers[j]+' ',x[j])
print('\n')
conn.close()
5
正如Frontware所建议的,你可以使用sqlcipher。
pysqlcipher这个Python包可以让你更方便地使用,因为它把sqlcipher的代码整合在一起,编译成了一个扩展。
使用pysqlcipher就像使用普通的sqlite.dbapi2一样,只需要设置正确的加密参数就可以了。
8
我的应用程序可能会同时运行多个实例,所以我不能仅仅对SQLite数据库文件进行加密。我也觉得在Python中加密数据不是个好主意,因为这样一来就无法在数据库中进行任何数据操作。我想到了以下几种方法:
- 使用之前提到的SQLCipher。我需要为Python编写自己的绑定,并自己编译(或者支付费用)。
- 使用PyCrypto来加密数据库文件。我会实现一个SQL服务器来解密数据库文件,然后处理来自客户端的请求。每当没有未处理的请求时,它会重新加密数据库。这种方法会比较慢,并且会让数据库在某些时候处于临时解密状态。
我没能成功编译SQLCipher,它还使用了OpenSSL(对于简单的AES 128来说,这个库太庞大了)。我发现了wxSQLite3,并了解了如何分离SQLite的加密。我成功地让它与最新版本的SQLite3一起工作。wxSQLite3支持AES 256。我的下一步是将PySQLite(Python内置的SQLite库)与修改过的sqlite3.dll一起编译,并调整PySQLite以支持wxSQLite3的sqlite3.dll中的扩展加密。