说明
pysqlcipher3是针对Python 3使用的pysqlcipher的一个分支, 尽管仍然维护对Python 2的支持。它仍然处于测试阶段, 尽管这个库包含的最新的代码量很少,并且大量借鉴了核心Python sqlite源代码,同时链接到libsqlcipher。
在执行任何操作之前,您必须传入PRAGMA key
from pysqlcipher3 import dbapi2 as sqlite
conn = sqlite.connect('test.db')
c = conn.cursor()
c.execute("PRAGMA key='password'")
c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''')
c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""")
conn.commit()
c.close()
可以使用hexdump -C test.db验证您的数据库文件是否被加密,机密的二进制字段是
ab 7f 61 7a 33 9d 07 f4 08 68 c9 b0 4f e3 34 60 |..az3....h..O.4`|
bb 9d 9c 3d 9e ce 69 57 b6 2f 36 c4 fd 13 bd 61 |...=..iW./6....a|
77 bf e3 1d 65 b5 ea f7 d2 fc 98 31 23 66 a0 1e |w...e......1#f..|
a4 4f fa 66 49 36 84 a1 3e 0c 21 98 84 07 eb 07 |.O.fI6..>.!.....|
准备工作
openssl
安装openssl,选择对应版本即可,不要选择Light 版本
https://slproweb.com/products/Win32OpenSSL.html
环境变量增加OPENSSL_CONF
编译sqlite
下载 sqlcipher,编译文件
git clone https://github.com/sqlcipher/sqlcipher.git
nmake /f Makefile.msc
nmake需要在 x64 Native Tools Command Prompt for VS的终端下使用
编译会报错,只要生成sqlite3.h, sqlite3.c文件即可
想完整编译需要修改Makefile.msc再构建,https://youtu.be/SFHGeetZ0po 完整编译视频
将sqlite3.c和sqlite.h复制到根目录下的amalgamation,以及amalgamation\sqlcipher
tcl
magicsplat版本tcl地址为https://www.magicsplat.com/tcl-installer/
setup.py修改
quote_argument
对于python3.8版本
def quote_argument(arg):
quote = '"' if sys.platform != 'win32' else '\\"'
return quote + arg + quote
对于python3.12版本
def quote_argument(arg):
quote = '"' if sys.platform == 'win32' else '\\"'
return quote + arg + quote
openssl路径
修改setup.py中对应静态库位置,注意最新版libcrypto.lib的位置
安装
python setup.py build_amalgamation
python setup.py install
加密示例代码
借助GPT可以写一个加密sqlite的类
from pysqlcipher3 import dbapi2 as sqlite3
class EncryptedDatabase:
def __init__(
self,
db_name="standard_e.db",
new_db_name="standard.db",
):
self.db_name = db_name ##未加密数据库
self.new_db_name = new_db_name ##加密数据库
self.password = Config.db_code
if os.path.exists(self.new_db_name):
os.remove(self.new_db_name)
# 原始数据库
latest_tb_name = get_latest_std_table(
db_name=db_name, encrypt=False
) # 替换为你的表名
tb_names = ["users",latest_tb_name]
# for table in tb_names:
# self.create_table(table)
self.copy_data()
def create_table(self, tb_name):
conn = sqlite3.connect(self.new_db_name)
cursor = conn.cursor()
cursor.execute(f"PRAGMA key = '{self.password}'")
create_table_query = f"""
CREATE TABLE IF NOT EXISTS {tb_name} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category TEXT,
name TEXT,
code TEXT UNIQUE,
effective_date TEXT,
status TEXT,
publish_date TEXT
)
"""
cursor.execute(create_table_query)
conn.commit()
conn.close()
def copy_data(self):
conn = sqlite3.connect(self.db_name)
cursor = conn.cursor()
cursor.execute(
f"ATTACH DATABASE '{self.new_db_name}' AS encrypted KEY '{self.password}'"
)
cursor.execute(f"SELECT sqlcipher_export('encrypted')")
cursor.execute(f"DETACH DATABASE encrypted")
conn.close()
测试
Navicat无法打开加密的数据库
附录
编译了3个wheel文件
wheel下载地址