I'm working on an app that is using a database that is encrypted by sqlcipher. The passwort for this encryption is stored by cacheword.
To make a backup of my database I used the following code:
// ggf. Datenbank öffnen
openGuard();
mDb.execSQL("ATTACH DATABASE '" + outFileName + "' AS backup KEY 'asdfghjkl';");
mDb.rawExecSQL("SELECT sqlcipher_export('backup');");
mDb.execSQL("DETACH DATABASE backup;");
The method openGuard() is used to check if the database is opend yet and if not do this.
I've checked the backup by using an empty key to make an unencrypted copy of my database. Then I can use it on adb shell and use sql-statements to get the wanted data.
My problem now for a long time is that I'm not able to use my backup to restore the database of my app. I tried this code:
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(backupFile, "asdfghjkl", null);
db.execSQL("ATTACH DATABASE '" + dbFile + "' AS encrypted KEY '" + mCacheWord.getEncryptionKey() + "';");
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
Alternatively I tried
db.execSQL("ATTACH DATABASE '" + dbFile + "' AS encrypted KEY '" + encodeRawKey(mCacheWord.getEncryptionKey()) + "';");
But in both cases I get the following error message:
10-30 00:56:42.845: I/Database(14407): sqlite returned: error code = 26, msg = statement aborts at 5: [ATTACH DATABASE '/data/data/.../databases/database.db' AS encrypted KEY '[B#42082da0';] file is encrypted or is not a database
10-30 00:56:42.845: E/Database(14407): Failure 26 (file is encrypted or is not a database) on 0x63bdedb0 when executing 'ATTACH DATABASE '/data/data/.../databases/database.db' AS encrypted KEY '[B#42082da0';'
Is there anyone how can help me with my problem?
Looks like you've gotten accidentally "hung up" trying to decrypt by supplying the key via the ATTACH DATABASE statement. Looking at Example 2: Decrypt a SQLCipher database to a Plaintext Database of the API, there's a comment that reads -- empty key will disable encryption. So, presumably your initial decryption code attempt should first execute the PRAGMA key = statement (to supply the key) and then the ATTACH DATABASE statement with empty key (to decrypt) something like this:
db.execSQL("PRAGMA key = '" + mCacheWord.getEncryptionKey() + "';");
db.execSQL("ATTACH DATABASE '" + dbFile + "' AS encrypted KEY '';");
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
Another brief example about this can be seen in this the SQLCipher Users mailing list discussion.
I believe the problem may have to do with the fact that you are using CacheWord, which manages the encryption key separately from SQLCipher. You should verify the format of the string returned from getEncryptionKey() and ensure that it matches the proper format for a raw key in SQLCIpher.
Related
I have created a certificate on SQL server for encrypting my database backups. I used the following article for instructions.
https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/backup-encryption?view=sql-server-2016
I need to restore this database to multiple servers. I can use the following code to import/create the certificate on another server.
-- Copy Certificate to target then create
CREATE CERTIFICATE myCertificate
FROM FILE = 'C:\Temp\CertBackup.cer'
WITH PRIVATE KEY (FILE = 'C:\Temp\CertBackup.pvk',
DECRYPTION BY PASSWORD = 'myPassword');
GO
I would like to be able to import this certificate to many servers at once instead of running this command on each server. Should I script this with Powershell or is there a better way?
DECLARE #password VARCHAR(40) = 'f00bar!23'
select name, 'create certificate ' + QUOTENAME(name) + ' from binary = '
+ CONVERT(VARCHAR(MAX), CERTENCODED(CERT_ID(name)), 1)
+ ' with private key ( binary = '
+ CONVERT(VARCHAR(MAX), CERTPRIVATEKEY(CERT_ID(name), #password), 1)
+ ', decryption by password = ''' + #password + ''')'
FROM sys.[certificates] AS [c]
WHERE name = '«cert name here»';
Run that and it will generate a T-SQL statement that will allow you to create the certificate without having to use a certificate backup. The above assumes that the private key for the certificate is protected by a database master key. If it's protected by a password, you'll have to modify the code accordingly (left as an exercise for the reader).
Note: #password is only used to protect the certificate in transit. That is, it is not the password for the certificate itself.
Please pardon me for my English grammar.
I'm currently coding a system and I was wondering if you could establish a new connection after you created a database in a server.
This is the Connection String:
Dim DBCon As SqlConnection = New SQLConnection("Data Source=(localdb)\DbLocal;Integrated Security=True")
If I want to create a database I use a command - the database name is bounded after a textbox, it goes like:
Dim dbName As String = txtdbName.Text
myCommand = "CREATE database " & dbName
The database gets created, but after I start a query that creates a table - the table does not save in the created database. So with my beginner skills in VB.Net and MSSQL, I deduced it was because of my Connection String, so I tried messing with it:
Dim myConnectionString As SqlConnection = New SqlConnection("Data Source=(localdb)\DbLocal;Database=" & dbName & ";Integrated Security=True;Pooling=False")
I wrote the above code before the create a table query, but after I run it, the tables I created in the query didn't go to the database. I was wondering if there's a 'right' way to do this. I tried mixing different codes that I found online, but they produce the same result.
Edit: My create table query:
myCommand = "CREATE TABLE tblPerson (PersonID int, LastName varchar(300), FirstName varchar(300), Address varchar(300), City varchar(300))"
The way I would do this is to add a USE statement before the CREATE TABLE. So the CREATE TABLE command would look like this:
"USE " & dbName & ";
GO
CREATE TABLE ..."
EDIT: As pointed out in the comments, the GO separator cannot be used in a .NET SQL Command.
Instead one can use three-part naming to specify the database like this:
"CREATE TABLE " & dbName & ".dbo.MyTable ( ..."
Or use SMO which does allow one to use the GO separator. This technique is thoroughly described in the accepted answer to this question.
In SQL server user have to follow below steps to restore database from backup file.
right click on the Databases container within object explorer.
from context menu select Restore database.
Specify To Database as either a new or existing database.
Specify Source for restore as from device.
Select Backup media as File.
Click the Add button and browse to the location of the BAK file.
Is there any script/command to restore the same without doing the above methods?
Just before you click on the last OK button on SSMS Backup/Restore Wizard ... you can Click on the script drop down button and pick script to New Query Window (The script drop down is Next to the Help button and above the Source/Database Name) and it will generate the Exact command that SSMS will execute against the DB. So you can use that command from the Query window to do the same thing programatically in TSQL. Indeed you can even put that inside a Stored PRocedure if you want to execute the same command all the time like so:
CREATE PROCEDURE dbo.dbBackup AS
BEGIN
RESTORE DATABASE [MyDataBaseName] FROM DISK = N'C:\SQLData\MyDB.bak'
WITH FILE = 1, NOUNLOAD, STATS = 5
END
And to take it one more level you could assign that SP to a hotkey as explained over here : https://www.mssqltips.com/sqlservertip/1287/assign-shortcuts-to-commands-in-sql-server-management-studio/
To access the screen below, open a query window and select from the menu Tools -> Options and then under the Environment node select Keyboard --> Query Shortcuts this will allow you to assign a stored procedure to execute for the Hotkey combination that is best for you.
One thing to be care full about though is to make sure that this does not replace an existing DB because you could accidentally overwrite a good DB if the restore command includes that option
"Automate" is a very broad term in your question, but if C# is an option, you can use the SQLCommand Class to execute the Restore, as below
sqlCmd.CommandText = "RESTORE DATABASE [" + restoreDbName + "] FROM DISK =
N'" + backupFileName + "' WITH FILE = 1, MOVE '" + logicalNameMdf + "' TO '"
+ restorePathMdf + "', MOVE '" + logicalNameLdf + "' TO '" + restorePathLdf + "', "
+ " NOUNLOAD, REPLACE";
sqlCmd.ExecuteNonQuery();
Been working on my first Entity Framework project. As part of the project I am going to be creating a number of SSRS reports. In order to connect to the database I need to have a Reports user that will only access to the specific database on the server. In the past i have always written a script to add Database users but I want to know is there a way that i can do this using Entity Framework instead?
Assuming your user already has a login defined at the SQL Server level (Security > Logins), you can call the following method from your DB initializer seed method to add the user to the database:
private void AddDbUser(MyDataContext myDB)
{
string accountDomainName = "AccountDomainName"; // replace with user's login domain
string accountLoginID = "AccountLoginID"; // replace with user's login ID
string sql =
"USE [MyDB]" +
"CREATE USER [MyNewUser] FOR LOGIN [" + accountDomainName + "\\" + accountLoginID + "]" +
"ALTER AUTHORIZATION ON SCHEMA::[db_datareader] TO [" + accountLoginID + "]" +
"ALTER AUTHORIZATION ON SCHEMA::[db_datawriter] TO [" + accountLoginID + "]" +
"EXEC sp_addrolemember N'db_datawriter', N'" + accountLoginID + "'" +
"EXEC sp_addrolemember N'db_datareader', N'" + accountLoginID + "'";
myDB.Database.ExecuteSqlCommand(sql);
}
The exact SQL needed is dependent on your configuration. To have SQL Server generate the SQL for your scenario, you could open the add user dialog in SSMS (Database > Users > New User...), fill out the fields, and click the "Script" button at the top instead of hitting OK at the bottom. Note that any "GO" lines will need to be removed from the generated script before pasting it into the method above.
You would need to tell EF to use the appropriate stored procedures to do so. You could also wrap these up in a sproc of your own that wraps the relevant commands. There is no native "CreateReportsUser" type method within EF that I know of.
Edit: I probably should have provided this reference to be a "complete" answer. Apologies.
Here's how you can do what I recommend: How to call Stored Procedure in Entity Framework 6 (Code-First)?
We attached the database PStorage to the server.
Then I tried to create the login & user using the following code:
Dim con As New SqlConnection
Dim query As SqlCommand
con.ConnectionString = "Server=(LocalHost);Data Source=LocalHost\SQLEXPRESS;Database=PSTORAGE;Integrated Security=TRUE"
con.Open()
query.CommandText = "IF NOT EXISTS(SELECT [LoginName] FROM MASTER.DBO.SYSLOGINS WHERE [Name]='UserCP') CREATE LOGIN UserCP WITH PASSWORD='CPPassword'"
query.ExecuteNonQuery()
query.Dispose()
query.CommandText = "IF NOT EXISTS(SELECT [Name] FROM SYS.DATABASE_PRINCIPALS WHERE [Name]='CPUser') CREATE USER CPUser FOR LOGIN UserCP"
query.ExecuteNonQuery() 'This line is throwing the error -> Login Failed for the User 'UserCP'.
query.Dispose()
The error we are getting after executing the second query is
Login failed for the user 'UserCP'
While attaching the database the same error occurs. Then we had to use sqlCmd.
In all the systems this method works fine. But in one of our customers system this problem occurs. What might be the reason?
After a lot of tries we could come to know that the folder was compressed [All the file names were in blue colour]. Since the database files were inside the compressed folder- none of the operations could be done on them perfectly.
Right click on the database folder, Press on Properties
Press on Advanced
Untick the Compress contents to save disk space
Save the changes made