Sqlite не может открыть файл базы данных зашифрован или не является базой данных?

Я работаю над приложением Windows.net 2.0 с базой данных sqlite, моя строка подключения остается в app.config вроде

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

В строке подключения я определил пароль как "mypassword", если я удалю этот пароль, все работает хорошо, но когда я использую предложение пароля, это дает мне ошибку в синтаксисе connection.open(), который

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

Я искал в сети и обнаружил некоторую проблему с версией, но я использую версию 3 только в том виде, в каком я указал в строке подключения, я также попытался удалить "version = 3", но проблема осталась прежней.

Я делаю это в первый раз, каково его решение?

Ответ 1

Когда вы укажете пароль в строке подключения и база данных уже существует, SQLite предполагает, что база данных зашифрована и будет пытаться расшифровать ее с помощью указанного пароля. Если вы еще не установили пароль в базе данных, это приведет к ошибке "файл зашифрован", поскольку предоставленный пароль не может использоваться для дешифрования незашифрованной базы данных.

Вы можете либо удалить базу данных, и 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");

Ссылка: Шифрование, дешифрование и прикрепление к зашифрованным базам данных

Ответ 2

2 Ответ на загрузку в основном правильный, но я хотел добавить свое, потому что есть некоторые пояснения. Как сказал 2Toad, это правильно:

Когда вы укажете пароль в строке подключения и база данных уже существует, SQLite предполагает, что база данных зашифрована и попытается расшифровать ее с помощью указанного пароля. Если вы еще не установили пароль в базе данных, это приведет к ошибке "файл зашифрован", поскольку предоставленный пароль не может использоваться для дешифрования незашифрованной базы данных.

Но эта ошибка также может произойти, если вы попытаетесь использовать conn.SetPassword("something") после того, как у вас уже есть другой в строке подключения. Или, если вы выполняете conn.ChangePassword("somethingelse"), но все еще имеете Password=something в строке соединения.

Существует несколько сценариев:

  • В базе данных был применен пароль, и он находится в строке подключения.
  • У вас есть пароль в строке подключения, но в базе данных нет ни одного приложения, либо пароль в строке не соответствует БД.
  • В базе данных никогда не было пароля, и вы хотите изменить его.
  • В базе данных есть пароль, и вы хотите изменить его.

Решения:

  • Таким образом, код 2Toad, предоставленный для выполнения conn.ChangePassword("somethingelse"), является только неполным и не учитывает, где вы находитесь, что еще вы сделали и что вы хотите делать в будущем. Если у вас есть существующий пароль, и вы хотите его изменить, это правильно, но вы также должны быть уверены, что строка подключения будет обновлена ​​впоследствии или последующие подключения не будут выполнены с ошибкой file is encrypted.

  • Этот сценарий происходит, если вы очистите пароль с помощью conn.SetPassword(""), а затем попробуйте conn.ChangePassword("somethingelse") без первого подключения к базе данных без Password=something в строке подключения. То, что Password=something должно быть удалено из строки подключения, поскольку пароль был удален программно из БД, и БД попытается соединиться с этим. Если он не удаляется из строки подключения одновременно с удаленным из БД программным способом, вы получите ту же ошибку file is encrypted.

  • Поскольку я начал с conn.SetPassword("something") в самом начале, когда у меня не было введенного пароля (и я считаю, что это способ сделать это), я не могу проверить следующее, не создавая другого SQLite DB, но я не думаю, что вы можете позвонить conn.ChangePassword("something"), если у вас никогда не было пароля. Вы должны сделать conn.SetPassword("something") для исходного набора, а затем поместите Password=something в строку подключения.

  • Как я сменил пароль, я сделал 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
    

Это получилось отлично. Я полагаю, вы также можете не очистить его от строки подключения и просто сделать 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

Лично я сохраняю пароль как зашифрованный в файле приложения (web).config и вызываю его в переменную в моем приложении onload и динамически строю из нее строку подключения.

Что я знаю, если вы удалите SQLite DB и попытаетесь вызвать его, вы просто получите сообщение об ошибке - а не заново созданный SQLite DB с новым паролем из вашей строки подключения - по крайней мере, при использовании и вызове из приложения С#.NET.

UPDATE Если вам нужна функция, которая будет использоваться для обновления пароля после его наличия, вы не хотите иметь .SetPassword(), но .ChangePassword(). Я обнаружил, что лучше также всегда его исключить, а затем изменить, как в моем первом примере в # 4.