C# sqlite无法打开数据库文件是加密的还是不是数据库?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16030601/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 23:46:19  来源:igfitidea点击:

sqlite unable to open database file is encrypted or is not a database?

c#winformsvisual-studio-2010sqlite

提问by Mogli

I am working on a windows application .net 2.0 with sqlite database, my connection string stays in app.config like

我正在使用带有 sqlite 数据库的 Windows 应用程序 .net 2.0,我的连接字符串保留在 app.config 中,例如

<connectionStrings>
<add name="SQLiteDB" 
     connectionString="Data Source=|DataDirectory|database.s3db;version=3;password=mypassword;" 
     providerName="System.Data.Sqlite"/>
</connectionStrings>

In the connection string i have defined password as "mypassword" if i remove this password everything is working well but when i use password clause, it gives me error in connection.open() syntax that

在连接字符串中,我已将密码定义为“mypassword”,如果我删除此密码,一切正常,但是当我使用密码子句时,它在 connection.open() 语法中出现错误

File opened that is not a database file
file is encrypted or is not a database

I searched on net and found some version issue but i am using version 3 only as i stated in connection string i also tried removing the "version=3" but problem remains the same.

我在网上搜索并发现了一些版本问题,但我只使用版本 3,正如我在连接字符串中所述,我也尝试删除“版本 = 3”,但问题仍然存在。

I am doing this first time, what is the solution of it?

我是第一次这样做,它的解决方案是什么?

采纳答案by 2Toad

When you specify a password in the connection string, and the database already exists, SQLite assumes the database is encrypted and will try to decrypt it with said password. If you haven't set a password on the database yet, this will result in the "file is encrypted" error, because the supplied password can't be used to decrypt an unencrypted database.

当您在连接字符串中指定密码并且数据库已经存在时,SQLite 假定数据库已加密并尝试使用该密码对其进行解密。如果您还没有在数据库上设置密码,这将导致“文件已加密”错误,因为提供的密码不能用于解密未加密的数据库。

You can either delete the database, and SQLite will create a new encrypted database using the password in the connection string. Or, you can encrypt your existing database using the ChangePassword()method:

您可以删除数据库,SQLite 将使用连接字符串中的密码创建一个新的加密数据库。或者,您可以使用以下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");

Reference: Encrypting, decrypting and attaching to encrypted databases

参考:加密、解密和附加到加密数据库

回答by vapcguy

2Toad's answer is mostly correct, but I wanted to add my own because there are some clarifications to be made. As 2Toad said, this is correct:

2Toad 的答案大部分是正确的,但我想添加我自己的答案,因为有一些需要澄清的地方。正如 2Toad 所说,这是正确的:

When you specify a password in the connection string, and the database already exists, SQLite assumes the database is encrypted and will try to decrypt it with said password. If you haven't set a password on the database yet, this will result in the "file is encrypted" error, because the supplied password can't be used to decrypt an unencrypted database.
当您在连接字符串中指定密码并且数据库已经存在时,SQLite 假定数据库已加密并尝试使用该密码对其进行解密。如果您还没有在数据库上设置密码,这将导致“文件已加密”错误,因为提供的密码不能用于解密未加密的数据库。

But this error can also happen if you try to use conn.SetPassword("something")after you already had another one in the connection string. Or if you do conn.ChangePassword("somethingelse"), but still have Password=somethingin the connection string.

但是,如果您conn.SetPassword("something")在连接字符串中已经有另一个之后尝试使用,也会发生此错误。或者如果你这样做了conn.ChangePassword("somethingelse"),但仍然有Password=something连接字符串。

There are several scenarios to consider:

有几种情况需要考虑:

  1. The database has had a password applied, and it is in the connection string.
  2. You have a password in the connection string, but the database does not have one applied, or the password in the string does not match the DB.
  3. The database has never had a password, and you want to change it.
  4. The database has had a password, and you want to change it.
  1. 数据库已应用密码,它位于连接字符串中。
  2. 您在连接字符串中有密码,但数据库没有应用密码,或者字符串中的密码与数据库不匹配。
  3. 数据库从来没有密码,而您想更改它。
  4. 数据库有密码,您想更改它。

Resolutions:

决议:

  1. So the code 2Toad provided to perform conn.ChangePassword("somethingelse")is only half-correct and doesn't take into account where you are, what else you've done, and what you want to do in the future. If you have an existing password and you want to change it, this is correct, but you also have to be sure the connection string is updated afterwards, or subsequent connections will fail with the file is encryptederror.

  2. This scenario happens if you blank the password using conn.SetPassword("")and then try conn.ChangePassword("somethingelse")without first connecting to the database without the Password=somethingin the connection string. That Password=somethingwould have to be removed from the connection string, because the password has been removed programmatically from the DB and the DB will try connecting with that. If it's not removed from the connection string at the same time as it's removed from the DB programmatically, you'll get the same file is encryptederror.

  3. Because I started out by doing a conn.SetPassword("something")in the very beginning when I didn't have a password applied (and I believe this is the way to do that), I cannot verify the following without creating another SQLite DB, but I do not believe you can call conn.ChangePassword("something")if you never had a password in the first place. You should do conn.SetPassword("something")for the initial set, and then put Password=somethingin your connection string.

  4. The way I did a change of a password was where I did conn.ChangePassword("somethingelse")only after doing conn.SetPassword("")and clearing the Password=somethingfrom the connection string:

    // Changes an encrypted database to unencrypted and removes password
    string connString = "Data Source=c:\test.db3;Password=something";    
    SQLiteConnection conn = new SQLiteConnection(connString);
    conn.SetPassword("");
    //conn.Open();    // doesn't work because connString hasn't been updated
    
    // Update connString
    connString = "Data Source=c:\test.db3;";    
    conn = new SQLiteConnection(connString);
    conn.Open();  // we've opened the DB without a password
    
    // Re-encrypts the database. The connection remains valid and usable afterwards until closed - then the connection string needs updating.    
    conn.ChangePassword("somethingelse");
    conn.Close();
    
    // Update connString
    connString = "Data Source=c:\test.db3;Password=somethingelse";   
    conn = new SQLiteConnection(connString); // must re-instantiate!
    conn.Open();  // we've opened the DB with our new password
    
  1. 因此,2Toad 提供的执行代码conn.ChangePassword("somethingelse")只对了一半,并没有考虑到您在哪里,您还做了什么,以及您将来想做什么。如果您有一个现有密码并且想要更改它,这是正确的,但您还必须确保之后更新连接字符串,否则后续连接将因file is encrypted错误而失败。

  2. 如果您将密码清空conn.SetPassword(""),然后尝试conn.ChangePassword("somethingelse")在没有Password=something连接字符串的情况下先连接到数据库,则会发生这种情况。这Password=something必须从连接字符串中删除,因为密码已通过编程方式从 DB 中删除,并且 DB 将尝试使用该密码进行连接。如果它没有在以编程方式从数据库中删除的同时从连接字符串中删除,您将收到相同的file is encrypted错误。

  3. 因为我一开始conn.SetPassword("something")没有应用密码时做了一个(我相信这是这样做的方法),所以我无法在不创建另一个 SQLite DB 的情况下验证以下内容,但我不相信你conn.ChangePassword("something")如果您一开始没有密码,可以打电话。你应该做conn.SetPassword("something")初始设置,然后放入Password=something你的连接字符串。

  4. 我更改密码的方式是在conn.ChangePassword("somethingelse")执行conn.SetPassword("")Password=something从连接字符串中清除之后才执行的操作:

    // Changes an encrypted database to unencrypted and removes password
    string connString = "Data Source=c:\test.db3;Password=something";    
    SQLiteConnection conn = new SQLiteConnection(connString);
    conn.SetPassword("");
    //conn.Open();    // doesn't work because connString hasn't been updated
    
    // Update connString
    connString = "Data Source=c:\test.db3;";    
    conn = new SQLiteConnection(connString);
    conn.Open();  // we've opened the DB without a password
    
    // Re-encrypts the database. The connection remains valid and usable afterwards until closed - then the connection string needs updating.    
    conn.ChangePassword("somethingelse");
    conn.Close();
    
    // Update connString
    connString = "Data Source=c:\test.db3;Password=somethingelse";   
    conn = new SQLiteConnection(connString); // must re-instantiate!
    conn.Open();  // we've opened the DB with our new password
    

This worked out fine. I suppose you can also not clear it from the connection string and simply do conn.ChangePassword("somethingelse"), and then add Password=somethingelseto your string, afterwards:

这工作得很好。我想您也不能从连接字符串中清除它,只需执行conn.ChangePassword("somethingelse"),然后添加Password=somethingelse到您的字符串中,然后:

    // Opens an encrypted database   
    string connString = "Data Source=c:\test.db3;Password=something";    
    SQLiteConnection conn = new SQLiteConnection(connString);
    conn.Open();    

    // Encrypts the database. The connection remains valid and usable afterwards until closed - then the connection string needs updating.    
    conn.ChangePassword("somethingelse");
    conn.Close();

    // Update connString
    connString = "Data Source=c:\test.db3;Password=somethingelse";   
    conn = new SQLiteConnection(connString);
    conn.Open();     // we've opened the DB with our new password

Personally, I store the password as encrypted in an app (web) .config file, and call it into a variable in my application onload and dynamically build my connection string from it.

就个人而言,我将密码以加密形式存储在应用程序 (web) .config 文件中,并将其调用到我的应用程序 onload 中的变量中,并从中动态构建我的连接字符串。

That I know of, if you delete a SQLite DB and try to call it, you will simply get an error - not a re-created SQLite DB with a new password from your connection string - at least when using and calling it from a C# .NET app.

据我所知,如果您删除一个 SQLite DB 并尝试调用它,您只会收到一个错误 - 而不是使用连接字符串中的新密码重新创建的 SQLite DB - 至少在从 C# 使用和调用它时.NET 应用程序。

UPDATEIf you need a function that will be used for updating the password after you already have one, you don't want to have .SetPassword(), but .ChangePassword(). I found it is also better to always blank it out, then change it, like in my first example in #4.

更新如果您需要一个在您已经拥有密码后用于更新密码的功能,您不希望拥有.SetPassword(),但是.ChangePassword()。我发现最好始终将其清空,然后更改它,就像我在 #4 中的第一个示例一样。