SpocWeb / csharp-sqlite

Exported from code.google.com/p/csharp-sqlite to continue. Pull Requests welcome!
Other
0 stars 0 forks source link

System.ArgumentException when using encryption on Mono for Android #136

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Compile with SQLITE_HAS_CODEC
2. Create brand new database by connecting to new file
2. Issued PRAGMA hexkey='0x0102030405060708090a0b0c0d0e0f10' to db
3. Execute any SQL - e.g. a CREATE TABLE statement

What is the expected output? What do you see instead?

Should execute the SQL without error

What version of the product are you using? On what operating system?

csharp-sqlite 3.7.7.1
Monodroid 4.0.1

Please provide any additional information below.

I have gotten csharp-sqlite working fine on Monodroid by using the Silverlight 
compilation profile and altering a few compiler directive statements in the 
os_win_c class to avoid using IsolatedStorage for file access.

Csharp-sqlite works fine without encryption turned on, however it crashes when 
I try to run any SQL turning on encryption with the PRAGMA command.
This is on a brand new database.

It seems that the inbound 1024 byte [] is encrypted by CryptoStream into a 1040 
byte long result, which then cannot be read into the 1024 byte outbound byte [] 
buffer.

Did this code ever work?  
As far as I know, Monodroid's implementation of AESManaged is exactly the same 
as .Net/Silverlight.
Surely an encrypted form of plaintext will always be bigger?

Stack trace below.

01-16 15:10:02.236 I/MonoDroid( 2496): UNHANDLED EXCEPTION: 
System.ArgumentException: offset+count
01-16 15:10:02.236 I/MonoDroid( 2496): Parameter name: The size of the buffer 
is less than offset + count.
01-16 15:10:02.236 I/MonoDroid( 2496): at System.IO.MemoryStream.Read 
(byte[],int,int) [0x0003b] in 
/home/jon/Development/xamarin/mono/mcs/class/corlib/System.IO/MemoryStream.cs:24
6
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.codec_cipher 
(Community.CsharpSqlite.Sqlite3/cipher_ctx,uint,int,int,byte[],byte[]) 
[0x000ae] in C:\Libs\Csharp-Sqlite\crypto.cs:412
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.sqlite3Codec 
(Community.CsharpSqlite.Sqlite3/codec_ctx,byte[],uint,int) [0x001d5] in 
C:\Libs\Csharp-Sqlite\crypto.cs:521
01-16 15:10:02.236 I/MonoDroid( 2496): at (wrapper delegate-invoke) 
<Module>.invoke_byte[]__this___Sqlite3/codec_ctx_byte[]_uint_int 
(Community.CsharpSqlite.Sqlite3/codec_ctx,byte[],uint,int) <IL 0x0005d, 0x0011f>
01-16 15:10:02.236 I/MonoDroid( 2496): at Community.CsharpSqlite.Sqlite3.CODEC2 
(Community.CsharpSqlite.Sqlite3/Pager,byte[],uint,int,byte[]&) [0x0001b] in 
C:\Libs\Csharp-Sqlite\pager_c.cs:491
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.pager_write_pagelist 
(Community.CsharpSqlite.Sqlite3/Pager,Community.CsharpSqlite.Sqlite3/PgHdr) 
[0x00142] in C:\Libs\Csharp-Sqlite\pager_c.cs:4581
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.sqlite3PagerCommitPhaseOne 
(Community.CsharpSqlite.Sqlite3/Pager,string,bool) [0x00280] in 
C:\Libs\Csharp-Sqlite\pager_c.cs:6756
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.sqlite3BtreeCommitPhaseOne 
(Community.CsharpSqlite.Sqlite3/Btree,string) [0x0004c] in 
C:\Libs\Csharp-Sqlite\btree_c.cs:3596
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.vdbeCommit 
(Community.CsharpSqlite.Sqlite3/sqlite3,Community.CsharpSqlite.Sqlite3/Vdbe) 
[0x00112] in C:\Libs\Csharp-Sqlite\vdbeaux_c.cs:2451
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.sqlite3VdbeHalt 
(Community.CsharpSqlite.Sqlite3/Vdbe) [0x001a1] in 
C:\Libs\Csharp-Sqlite\vdbeaux_c.cs:2920
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.sqlite3VdbeExec 
(Community.CsharpSqlite.Sqlite3/Vdbe) [0x0073e] in 
C:\Libs\Csharp-Sqlite\vdbe_c.cs:1089
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.sqlite3Step 
(Community.CsharpSqlite.Sqlite3/Vdbe) [0x00145] in 
C:\Libs\Csharp-Sqlite\vdbeapi_c.cs:568
01-16 15:10:02.236 I/MonoDroid( 2496): at 
Community.CsharpSqlite.Sqlite3.sqlite3_step 
(Community.CsharpSqlite.Sqlite3/Vdbe) [0x0004c] in 
C:\Libs\Csharp-Sqlite\vdbeapi_c.cs:649

Original issue reported on code.google.com by p...@inalysis.com on 16 Jan 2012 at 5:29

GoogleCodeExporter commented 8 years ago
Hi there,

It is strange. I ran piece of code in Windows Phone 7.5 (Mango) project and it 
seems to be problem of framework itself. Nothing in common with sqlite as far 
for me.

Try this sample code (paste in new WP7 Mango project):

byte[] bIn =  new byte[1024];
for (int i = 0; i < 1024; ++i)
{
    bIn[i] = (byte)(i % 256);
}
byte[] bOut = new byte[1024];

AesManaged Aes = new AesManaged();
ICryptoTransform ict =  Aes.CreateEncryptor(
    new byte[]{191, 43, 134, 145, 128, 154, 235, 192, 76, 83, 56, 
        97, 29, 40, 219, 152, 136, 43, 30, 104, 200, 197, 243, 
        254, 58, 190, 183, 143, 216, 142, 47, 247}, 
    new byte[]{0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 
        0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00});

MemoryStream dataStream = new MemoryStream();
CryptoStream encryptionStream;

encryptionStream = new CryptoStream(dataStream, ict, CryptoStreamMode.Write);

encryptionStream.Write(bIn, 0, size);
encryptionStream.FlushFinalBlock();
dataStream.Position = 0;

dataStream.Read(bOut, 0, (int)dataStream.Length);
encryptionStream.Close();
dataStream.Close();

This piece of code causes the same problem of encryption byte[1024] into 
byte[1040] array.

Sounds interesting, doesn't it?

Original comment by bWeg...@gmail.com on 27 Jan 2012 at 7:22

GoogleCodeExporter commented 8 years ago
It is because of extra bytes due to AesManaged padding.

Original comment by bWeg...@gmail.com on 27 Jan 2012 at 10:13

GoogleCodeExporter commented 8 years ago
The encrypted form is 16 bytes bigger, and the IV is 16 bytes...co-incidence?  
I think not.  Maybe AESManaged adds the IV by default?

Original comment by p...@inalysis.com on 27 Jan 2012 at 10:16

GoogleCodeExporter commented 8 years ago
I have found solution.
Must replace original encrypting algorithm used in sqlite3 because sqlite3 
requires that encrypted data buffer is the same size as the incoming 
unencrypted data buffer.
I used an implementation from 
http://www.codeproject.com/Articles/7546/A-CBC-Stream-Cipher-in-C-With-wrappers-
for-two-ope (by author: vcepa) and changed it.
Changed immplementation such that padding is disabled (as required by sqlite3). 
Size of data buffer passed to encryption algorithm must be multiplicity of AES 
block size (in this case 16B). That is not an issue in sqlite3 because it is 
based on 1024B pages and 1024 % 16 = 0. 
I hope it will be done in future releases of sqlite3 implementations. 
Fell free to contact me if you need details (by posting a comment).

Original comment by bWeg...@gmail.com on 2 Mar 2012 at 10:30

GoogleCodeExporter commented 8 years ago
bWeg just found the same error, tried to use the solution you provide but cant 
find CreateEncryptor/CreateDecryptor.
Can you attach the solution?

Original comment by jvi...@gmail.com on 5 Mar 2012 at 10:05

GoogleCodeExporter commented 8 years ago
I started with http://viciproject.com/wiki/Projects/CoolStorage/WindowsPhone. 
Really nice sqlite3 wrapper based on MIT licence. I ran some tests and figured 
out that cipher implementation in sqlite3 port is broken for Windows Phone. It 
is based on Silverlight framework's AesManaged class which makes endcoded data 
bigger than the original data. An author of that port made an assumption that 
size of both incoming and outgoing buffers are the same. Unfortunately 
AesManaged class in opposition to 'full' .NET Framework's AesManaged class does 
not have enum property called Padding. This switcher determines to add or not 
an extra padding bytes to outgoing encrypted stream. Padding bytes are 
responsible for difference in size. In fact it makes this port to Mango not 
working with db encryption. I managed to work around this issue by using custom 
encryption algorithm based on publicly accessible code of AES encryption posted 
at 
http://www.codeproject.com/Articles/7546/A-CBC-Stream-Cipher-in-C-With-wrappers-
for-two-ope. I used mentioned algorithm and change it to not add padding bytes 
to achieve either incoming and outgoing cipher byte buffers to be the same size.

Cannot attach my source because it was done as a part of my full time job and I 
did not receive permission from my employee to do so. Sorry.

Original comment by bWeg...@gmail.com on 19 Mar 2012 at 10:33

GoogleCodeExporter commented 8 years ago
I have just fixed it as I need it in my current project.
https://code.google.com/r/ivankirkorau-csharp-sqlite-encrypted/source/detail?r=e
8c2c0ea82569f8c79d29fc724e58fbe97af7fef

Check it out. It works as it applies the fix around AesManaged that adds IV by 
default and requires one already in place to decrypt. Also pageSize change with 
reserved space should be enabled when you set a key or hexkey.

Original comment by ivan.kirkorau on 11 Jul 2013 at 1:17