保护SQLite数据库的密码,这可行吗?

112

我需要面对一个新的小项目。它将有大约7到9个表,其中最大的一个表每月增长速度最多为1000行。

我想使用SQLite作为我的数据库......但是如果有人想要更改数据库中的数据,我需要保护它。

我的主要问题是:

是否可以像在Access上那样给SQLite数据库设置密码保护?

开发语言将采用C#,但我正在寻找一些免费的解决方案。


3
您可能想查看[SQLiteCrypt](http://sqlite-crypt.com/index.htm)。 - Mike Buckbee
1
https://dev59.com/bG035IYBdhLWcg3wBLRL#5877130 - OliJG
如果您需要频繁锁定/解锁数据库进行调试,请尝试使用此工具http://goo.gl/12VnQd。 - Mangesh
你可以在这里找到解决方案 输入链接描述 - Ishwar Rimal
可能是重复的问题,关于SQLite加密/密码保护 - iammilind
8个回答

87

你可以为SQLite3数据库设置密码。在执行任何操作之前,请按照以下步骤设置密码。

SQLiteConnection conn = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;");
conn.SetPassword("password");
conn.Open();

那么下一次您可以像这样访问它

conn = new SQLiteConnection("Data Source=MyDatabase.sqlite;Version=3;Password=password;");
conn.Open();

这将防止任何GUI编辑器查看您的数据。如果您提供密码,某些编辑器可以解密数据库。使用的算法是RSA。

以后如果您想要更改密码,请使用

conn.ChangePassword("new_password");

要重置或删除密码,请使用

conn.ChangePassword(String.Empty);

到目前为止,我发现唯一能够打开受密码保护的数据库的免费工具是SQLite2009 Pro,详见此答案 - JumpingJezza
这个例子是用什么语言写的?看起来像是.NET? - pim
2
从技术上讲,.NET是一个框架。这里展示的语言是C#。 - vapcguy
2
请注意,如果没有提供密码,则Open()不会在受密码保护的SQLite数据库上失败,这可能超出您的预期!失败的是对打开文件进行的任何后续数据或元数据操作。 - Cristian Scutaru
1
奇怪的是,这段代码在VB.Net中无法工作。我收到一个错误,说SetPassword和ChangePassword都不是SQLiteConnection的成员。 - user3267567
显示剩余3条评论

36
您可以使用sqlite .net提供程序(System.Data.SQLite)的内置加密。有关详细信息,请参见http://web.archive.org/web/20070813071554/http://sqlite.phxsoftware.com/forums/t/130.aspx 要对现有未加密的数据库进行加密,或更改加密数据库的密码,请打开数据库,然后使用SQLiteConnection的ChangePassword()函数。
// Opens an unencrypted database
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.Open();
// Encrypts the database. The connection remains valid and usable afterwards.
cnn.ChangePassword("mypassword");

要解密现有的加密数据库,请使用空密码调用ChangePassword()函数:
// Opens an encrypted database
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3;Password=mypassword");
cnn.Open();
// Removes the encryption on an encrypted database.
cnn.ChangePassword(null);

要打开现有的加密数据库或创建新的加密数据库,请在ConnectionString中指定密码,如上例所示,或在打开新的SQLiteConnection之前调用SetPassword()函数。在ConnectionString中指定的密码必须是明文,但在SetPassword()函数中提供的密码可以是二进制字节数组。
// Opens an encrypted database by calling SetPassword()
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.SetPassword(new byte[] { 0xFF, 0xEE, 0xDD, 0x10, 0x20, 0x30 });
cnn.Open();
// The connection is now usable

默认情况下,使用ATTACH关键字将在将另一个数据库文件附加到现有连接时使用与主数据库相同的加密密钥。要更改此行为,可以使用以下KEY修饰符:

如果您正在使用明文密码附加加密的数据库:

// Attach to a database using a different key than the main database
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.Open();
cmd = new SQLiteCommand("ATTACH DATABASE 'c:\\pwd.db3' AS [Protected] KEY 'mypassword'", cnn);
cmd.ExecuteNonQuery();

使用二进制密码附加加密数据库:

// Attach to a database encrypted with a binary key
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");
cnn.Open();
cmd = new SQLiteCommand("ATTACH DATABASE 'c:\\pwd.db3' AS [Protected] KEY X'FFEEDD102030'", cnn);
cmd.ExecuteNonQuery();

2
这个仅包含链接的回答其实是为什么我们不在SO上使用仅链接回答的一个明显例子。实际链接已经消失了,它不再存在。我们之所以能够看到该网站,是因为它被web.archive.org自动归档。 - Hanlet Escaño
它不再起作用了,在最新版本中找不到这样的功能。 - MindRoasterMir
您可以使用sqlite .net提供程序(System.Data.SQLite)的内置加密。我不确定“内置”是什么意思。但如果要使用System.Data.SQLite的SetPassword()或ChangePassword()方法,仍需要2000美元的SQLite加密扩展许可证,对吗? - RonC

16

使用SQLCipher,它是SQLite的开源扩展,可以为数据库文件提供透明的256位AES加密。http://sqlcipher.net


2
速度如何?如果我使用Sqlcipher会降低性能吗? - TomSawyer
任何关于此案的强大解决方案都将基于对称加密算法,即使在RSA的情况下也是如此。 RSA(如前所述)仅用于加密对称算法的密钥,而不使用RSA加密任何内容。 AES256是一种非常高效和安全的对称算法。直接使用它似乎是一个很好的选择。但是要注意密钥! - Mohamed Hamzaoui

7
您可以使用SEE插件对SQLite数据库进行加密。这样可以防止未经授权的访问/修改。
引用SQLite文档:
“SQLite加密扩展(SEE)是SQLite的增强版本,使用128位或256位AES加密数据库文件,以帮助防止未经授权的访问或修改。整个数据库文件都被加密,因此对于外部观察者,数据库文件看起来像是包含白噪声的文件,没有任何标识该文件为SQLite数据库。”
您可以在此链接中找到有关此插件的更多信息。

8
这个扩展也是SQLite的一个付费插件。 - John Boker

3
如果您使用的是FluentNHibernate,则可以使用以下配置代码:
private ISessionFactory createSessionFactory()
{
    return Fluently.Configure()
            .Database(SQLiteConfiguration.Standard.UsingFileWithPassword(filename, password))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<DBManager>())
            .ExposeConfiguration(this.buildSchema)
            .BuildSessionFactory();    
}

private void buildSchema(Configuration config)
{
        if (filename_not_exists == true)
        {
            new SchemaExport(config).Create(false, true);
        }
}    

方法UsingFileWithPassword (文件名,密码)加密数据库文件并设置密码。
仅在创建新的数据库文件时运行。旧文件未加密,如果使用此方法打开,则会打开失败。


3

其中一个选择是VistaDB。它可以对数据库(甚至是表格)进行密码保护(可选加密)。


2
有更高效和免费的方法! - Saw
1
@MSS 但是 - 正如我所说的,VistaDB解决方案确实有一些优势,包括在表级别上进行单独加密,而不是对整个数据库连接进行加密。我不知道其他任何.NET本地选项可以实现这一点。它还是纯托管的,与大多数其他选项不同 - 只因为它不是免费的,并不意味着没有更高效或更好的选择 - 这完全取决于使用要求。 - Reed Copsey

2
我知道这是一个老问题,不过最简单的解决方案难道不是在操作系统层面上保护文件吗?只需防止用户访问该文件,他们就不能接触它。虽然我不确定这是否是理想的解决方案。

2
我不确定这是否是一个好的解决方案,因为任何人都可以使用USB启动到另一个操作系统并读取文件。 - nurettin
我认为这是一个公平的观点,但在这种情况下应该禁用USB。如果有人可以物理接触您的计算机,那么还有很多其他事情可以做。 - David Price
你想保护敏感数据,这样只有其他事情会出错。 - tripleee
使用SQLite数据库,这是完全不可能的。您需要使用户能够读取和写入它,这意味着SQLite数据库所在文件夹的ACL也必须允许他们拥有这些权限。您可以通过仅允许实际用户对该文件夹进行授权来保护其免受非用户的侵害,但您仍然面临“内部威胁”。 - vapcguy

0
为什么需要加密数据库?用户可以轻松地反汇编您的程序并找出密钥。如果您要对网络传输进行加密,则考虑使用PGP,而不是将加密层挤入数据库层中。

9
启动时可能会要求用户输入密码,这样就无法通过反汇编程序获得密钥。 - kgadek
1
使用Redgate Reflector或ILSpy。 - Zev Spitz
5
为什么要将密钥放入程序中?你不会这样做,可以从用户密码生成一个密钥并使用它,这样就不需要在源代码中包含任何秘密信息。 - trampster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接