/** * Derive an encryption key for a cipher contex key based on the raw password. * * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill * the key space (i.e 64 hex chars for a 256 bit key) then the key data will be used directly. * * Otherwise, a key data will be derived using PBKDF2 * * returns SQLITE_OK if initialization was successful * returns SQLITE_NOMEM if the key could't be derived (for instance if pass is null or pass_sz is 0) */ static int codec_key_derive(codec_ctx ctx, cipher_ctx c_ctx) { CODEC_TRACE("codec_key_derive: entered c_ctx.pass=%s, c_ctx.pass_sz=%d ctx.iv=%d ctx.iv_sz=%d c_ctx.kdf_iter=%d c_ctx.key_sz=%d\n", c_ctx.pass, c_ctx.pass_sz, c_ctx.iv, c_ctx.iv_sz, c_ctx.key_sz); if (c_ctx.pass != null && c_ctx.pass_sz > 0) { // if pass is not null if ((c_ctx.pass_sz == (c_ctx.key_sz * 2) + 3) && c_ctx.pass.StartsWith("x'", StringComparison.InvariantCultureIgnoreCase)) { int n = c_ctx.pass_sz - 3; /* adjust for leading x' and tailing ' */ string z = c_ctx.pass.Substring(2); // + 2; /* adjust lead offset of x' */ CODEC_TRACE("codec_key_derive: deriving key from hex\n"); c_ctx.key = sqlite3HexToBlob(null, z, n); } else { CODEC_TRACE("codec_key_derive: deriving key using AES256\n"); Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(c_ctx.pass, c_ctx.iv, 2010); c_ctx.key_sz = 32; c_ctx.key = k1.GetBytes(c_ctx.key_sz); } #if NET_2_0 Aes.BlockSize = 0x80; Aes.FeedbackSize = 8; Aes.KeySize = 0x100; Aes.Mode = CipherMode.CBC; #endif c_ctx.encryptor = Aes.CreateEncryptor(c_ctx.key, c_ctx.iv); c_ctx.decryptor = Aes.CreateDecryptor(c_ctx.key, c_ctx.iv); return(SQLITE_OK); } ; return(SQLITE_ERROR); }
/** * Derive an encryption key for a cipher contex key based on the raw password. * * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill * the key space (i.e 64 hex chars for a 256 bit key) then the key data will be used directly. * * Otherwise, a key data will be derived using PBKDF2 * * returns SQLITE_OK if initialization was successful * returns SQLITE_NOMEM if the key could't be derived (for instance if pass is null or pass_sz is 0) */ static int codec_key_derive(codec_ctx ctx, cipher_ctx c_ctx) { CODEC_TRACE("codec_key_derive: entered c_ctx.pass=%s, c_ctx.pass_sz=%d ctx.iv=%d ctx.iv_sz=%d c_ctx.kdf_iter=%d c_ctx.key_sz=%d\n", c_ctx.pass, c_ctx.pass_sz, c_ctx.iv, c_ctx.iv_sz, c_ctx.key_sz); if (c_ctx.pass != null && c_ctx.pass_sz > 0) { // if pass is not null if ((c_ctx.pass_sz == (c_ctx.key_sz * 2) + 3) && sqlite3StrNICmp(c_ctx.pass, "x'", 2) == 0) { int n = c_ctx.pass_sz - 3; /* adjust for leading x' and tailing ' */ string z = c_ctx.pass.Substring(2); // + 2; /* adjust lead offset of x' */ CODEC_TRACE("codec_key_derive: deriving key from hex\n"); c_ctx.key = sqlite3HexToBlob(null, z, n); } else { CODEC_TRACE("codec_key_derive: deriving key using AES256\n"); Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(c_ctx.pass, c_ctx.iv, 2010); c_ctx.key_sz = 32; c_ctx.key = k1.GetBytes(c_ctx.key_sz); } c_ctx.encryptor = Aes.CreateEncryptor(c_ctx.key, c_ctx.iv); c_ctx.decryptor = Aes.CreateDecryptor(c_ctx.key, c_ctx.iv); return(SQLITE_OK); } ; return(SQLITE_ERROR); }
/** * Initialize a new cipher_ctx struct. This function will allocate memory * for the cipher context and for the key * * returns SQLITE_OK if initialization was successful * returns SQLITE_NOMEM if an error occured allocating memory */ static int cipher_ctx_init(ref cipher_ctx iCtx) { iCtx = new cipher_ctx(); //iCtx = sqlite3Malloc( sizeof( cipher_ctx ) ); //ctx = *iCtx; //if ( ctx == null ) return SQLITE_NOMEM; //memset( ctx, 0, sizeof( cipher_ctx ) ); //ctx.key = sqlite3Malloc( EVP_MAX_KEY_LENGTH ); //if ( ctx.key == null ) return SQLITE_NOMEM; return(SQLITE_OK); }
/** * Set the raw password / key data for a cipher context * * returns SQLITE_OK if assignment was successfull * returns SQLITE_NOMEM if an error occured allocating memory * returns SQLITE_ERROR if the key couldn't be set because the pass was null or size was zero */ static int cipher_ctx_set_pass(cipher_ctx ctx, string zKey, int nKey) { ctx.pass = null; // codec_free( ctx.pass, ctx.pass_sz ); ctx.pass_sz = nKey; if (!String.IsNullOrEmpty(zKey) && nKey > 0) { //ctx.pass = sqlite3Malloc(nKey); //if(ctx.pass == null) return SQLITE_NOMEM; ctx.pass = zKey;//memcpy(ctx.pass, zKey, nKey); return(SQLITE_OK); } return(SQLITE_ERROR); }
/** * Compare one cipher_ctx to another. * * returns 0 if all the parameters (except the derived key data) are the same * returns 1 otherwise */ static int cipher_ctx_cmp(cipher_ctx c1, cipher_ctx c2) { CODEC_TRACE("cipher_ctx_cmp: entered c1=%d c2=%d\n", c1, c2); if (c1.key_sz == c2.key_sz && c1.pass_sz == c2.pass_sz && c1.pass == c2.pass ) { return(0); } return(1); }
/** * Copy one cipher_ctx to another. For instance, assuming that read_ctx is a * fully initialized context, you could copy it to write_ctx and all yet data * and pass information across * * returns SQLITE_OK if initialization was successful * returns SQLITE_NOMEM if an error occured allocating memory */ static int cipher_ctx_copy(cipher_ctx target, cipher_ctx source) { //byte[] key = target.key; CODEC_TRACE("cipher_ctx_copy: entered target=%d, source=%d\n", target, source); //codec_free(target.pass, target.pass_sz); source.CopyTo(target);//memcpy(target, source, sizeof(cipher_ctx); //target.key = key; //restore pointer to previously allocated key data //memcpy(target.key, source.key, EVP_MAX_KEY_LENGTH); //target.pass = sqlite3Malloc(source.pass_sz); //if(target.pass == null) return SQLITE_NOMEM; //memcpy(target.pass, source.pass, source.pass_sz); return(SQLITE_OK); }
/** * free and wipe memory associated with a cipher_ctx */ static void cipher_ctx_free(ref cipher_ctx ictx) { cipher_ctx ctx = ictx; CODEC_TRACE("cipher_ctx_free: entered ictx=%d\n", ictx); ctx.pass = null;//codec_free(ctx.pass, ctx.pass_sz); if (ctx.key != null) { Array.Clear(ctx.key, 0, ctx.key.Length);//codec_free(ctx.key, ctx.key_sz); } if (ctx.iv != null) { Array.Clear(ctx.iv, 0, ctx.iv.Length); } ictx = new cipher_ctx();// codec_free( ref ctx, sizeof( cipher_ctx ) ); }
public void CopyTo(cipher_ctx ct) { ct.derive_key = derive_key; ct.pass = pass; ct.pass_sz = pass_sz; if (key != null) { ct.key = new byte[key.Length]; key.CopyTo(ct.key, 0); } ct.key_sz = key_sz; if (iv != null) { ct.iv = new byte[iv.Length]; iv.CopyTo(ct.iv, 0); } ct.iv_sz = iv_sz; }
public cipher_ctx Copy() { cipher_ctx c = new cipher_ctx(); c.derive_key = derive_key; c.pass = pass; c.pass_sz = pass_sz; if (key != null) { c.key = new byte[key.Length]; key.CopyTo(c.key, 0); } c.key_sz = key_sz; if (iv != null) { c.iv = new byte[iv.Length]; iv.CopyTo(c.iv, 0); } c.iv_sz = iv_sz; return(c); }
/* * ctx - codec context * pgno - page number in database * size - size in bytes of input and output buffers * mode - 1 to encrypt, 0 to decrypt * in - pointer to input bytes * out - pouter to output bytes */ static int codec_cipher(cipher_ctx ctx, Pgno pgno, int mode, int size, byte[] bIn, byte[] bOut) { //int iv; //int tmp_csz, csz; CODEC_TRACE("codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size); /* just copy raw data from in to out when key size is 0 * i.e. during a rekey of a plaintext database */ if (ctx.key_sz == 0) { Array.Copy(bIn, bOut, bIn.Length);//memcpy(out, in, size); return(SQLITE_OK); } MemoryStream dataStream = new MemoryStream(); CryptoStream encryptionStream; if (mode == CIPHER_ENCRYPT) { encryptionStream = new CryptoStream(dataStream, ctx.encryptor, CryptoStreamMode.Write); } else { encryptionStream = new CryptoStream(dataStream, ctx.decryptor, CryptoStreamMode.Write); } encryptionStream.Write(bIn, 0, size); encryptionStream.FlushFinalBlock(); dataStream.Position = 0; dataStream.Read(bOut, 0, (int)dataStream.Length); encryptionStream.Close(); dataStream.Close(); return(SQLITE_OK); }
public void CopyTo( cipher_ctx ct ) { ct.derive_key = derive_key; ct.pass = pass; ct.pass_sz = pass_sz; if ( key != null ) { ct.key = new byte[key.Length]; key.CopyTo( ct.key, 0 ); } ct.key_sz = key_sz; if ( iv != null ) { ct.iv = new byte[iv.Length]; iv.CopyTo( ct.iv, 0 ); } ct.iv_sz = iv_sz; ct.encryptor = encryptor; ct.decryptor = decryptor; }
/** * free and wipe memory associated with a cipher_ctx */ static void cipher_ctx_free( ref cipher_ctx ictx ) { cipher_ctx ctx = ictx; CODEC_TRACE( "cipher_ctx_free: entered ictx=%d\n", ictx ); ctx.pass = null;//codec_free(ctx.pass, ctx.pass_sz); if ( ctx.key != null ) Array.Clear( ctx.key, 0, ctx.key.Length );//codec_free(ctx.key, ctx.key_sz); if ( ctx.iv != null ) Array.Clear( ctx.iv, 0, ctx.iv.Length ); ictx = new cipher_ctx();// codec_free( ref ctx, sizeof( cipher_ctx ) ); }
/** * Initialize a a new cipher_ctx struct. This function will allocate memory * for the cipher context and for the key * * returns SQLITE_OK if initialization was successful * returns SQLITE_NOMEM if an error occured allocating memory */ static int cipher_ctx_init( ref cipher_ctx iCtx ) { iCtx = new cipher_ctx(); //iCtx = sqlite3Malloc( sizeof( cipher_ctx ) ); //ctx = *iCtx; //if ( ctx == null ) return SQLITE_NOMEM; //memset( ctx, 0, sizeof( cipher_ctx ) ); //ctx.key = sqlite3Malloc( EVP_MAX_KEY_LENGTH ); //if ( ctx.key == null ) return SQLITE_NOMEM; return SQLITE_OK; }
/** * Compare one cipher_ctx to another. * * returns 0 if all the parameters (except the derived key data) are the same * returns 1 otherwise */ static int cipher_ctx_cmp( cipher_ctx c1, cipher_ctx c2 ) { CODEC_TRACE( "cipher_ctx_cmp: entered c1=%d c2=%d\n", c1, c2 ); if ( c1.key_sz == c2.key_sz && c1.pass_sz == c2.pass_sz && c1.pass == c2.pass ) return 0; return 1; }
/** * Copy one cipher_ctx to another. For instance, assuming that read_ctx is a * fully initialized context, you could copy it to write_ctx and all yet data * and pass information across * * returns SQLITE_OK if initialization was successful * returns SQLITE_NOMEM if an error occured allocating memory */ static int cipher_ctx_copy( cipher_ctx target, cipher_ctx source ) { //byte[] key = target.key; CODEC_TRACE( "cipher_ctx_copy: entered target=%d, source=%d\n", target, source ); //codec_free(target.pass, target.pass_sz); source.CopyTo( target );//memcpy(target, source, sizeof(cipher_ctx); //target.key = key; //restore pointer to previously allocated key data //memcpy(target.key, source.key, EVP_MAX_KEY_LENGTH); //target.pass = sqlite3Malloc(source.pass_sz); //if(target.pass == null) return SQLITE_NOMEM; //memcpy(target.pass, source.pass, source.pass_sz); return SQLITE_OK; }
/** * Derive an encryption key for a cipher contex key based on the raw password. * * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill * the key space (i.e 64 hex chars for a 256 bit key) then the key data will be used directly. * * Otherwise, a key data will be derived using PBKDF2 * * returns SQLITE_OK if initialization was successful * returns SQLITE_NOMEM if the key could't be derived (for instance if pass is null or pass_sz is 0) */ static int codec_key_derive( codec_ctx ctx, cipher_ctx c_ctx ) { CODEC_TRACE( "codec_key_derive: entered c_ctx.pass=%s, c_ctx.pass_sz=%d ctx.iv=%d ctx.iv_sz=%d c_ctx.kdf_iter=%d c_ctx.key_sz=%d\n", c_ctx.pass, c_ctx.pass_sz, c_ctx.iv, c_ctx.iv_sz, c_ctx.key_sz ); if ( c_ctx.pass != null && c_ctx.pass_sz > 0 ) { // if pass is not null if ( ( c_ctx.pass_sz == ( c_ctx.key_sz * 2 ) + 3 ) && sqlite3StrNICmp( c_ctx.pass, "x'", 2 ) == 0 ) { int n = c_ctx.pass_sz - 3; /* adjust for leading x' and tailing ' */ string z = c_ctx.pass.Substring( 2 );// + 2; /* adjust lead offset of x' */ CODEC_TRACE( "codec_key_derive: deriving key from hex\n" ); c_ctx.key = sqlite3HexToBlob( null, z, n); } else { CODEC_TRACE( "codec_key_derive: deriving key using AES256\n" ); Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes( c_ctx.pass, c_ctx.iv, 2010 ); c_ctx.key_sz = 32; c_ctx.key = k1.GetBytes( c_ctx.key_sz ); } c_ctx.encryptor = Aes.CreateEncryptor( c_ctx.key, c_ctx.iv ); c_ctx.decryptor = Aes.CreateDecryptor( c_ctx.key, c_ctx.iv ); return SQLITE_OK; }; return SQLITE_ERROR; }
/* * ctx - codec context * pgno - page number in database * size - size in bytes of input and output buffers * mode - 1 to encrypt, 0 to decrypt * in - pointer to input bytes * out - pouter to output bytes */ static int codec_cipher( cipher_ctx ctx, Pgno pgno, int mode, int size, byte[] bIn, byte[] bOut ) { int iv; int tmp_csz, csz; CODEC_TRACE( "codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size ); /* just copy raw data from in to out when key size is 0 * i.e. during a rekey of a plaintext database */ if ( ctx.key_sz == 0 ) { Array.Copy( bIn, bOut, bIn.Length );//memcpy(out, in, size); return SQLITE_OK; } MemoryStream dataStream = new MemoryStream(); CryptoStream encryptionStream; if ( mode == CIPHER_ENCRYPT ) { encryptionStream = new CryptoStream( dataStream, ctx.encryptor, CryptoStreamMode.Write ); } else { encryptionStream = new CryptoStream( dataStream, ctx.decryptor, CryptoStreamMode.Write ); } encryptionStream.Write( bIn, 0, size ); encryptionStream.FlushFinalBlock(); dataStream.Position = 0; dataStream.Read( bOut, 0, (int)dataStream.Length ); encryptionStream.Close(); dataStream.Close(); return SQLITE_OK; }
public cipher_ctx Copy( ) { cipher_ctx c = new cipher_ctx(); c.derive_key = derive_key; c.pass = pass; c.pass_sz = pass_sz; if ( key != null ) { c.key = new byte[key.Length]; key.CopyTo( c.key, 0 ); } c.key_sz = key_sz; if ( iv != null ) { c.iv = new byte[iv.Length]; iv.CopyTo( c.iv, 0 ); } c.iv_sz = iv_sz; c.encryptor = encryptor; c.decryptor = decryptor; return c; }
/* * ctx - codec context * pgno - page number in database * size - size in bytes of input and output buffers * mode - 1 to encrypt, 0 to decrypt * in - pointer to input bytes * out - pouter to output bytes */ static int codec_cipher(cipher_ctx ctx, int mode, int size, byte[] bIn, byte[] bOut) { if (bIn == null || bOut == null) { throw new ArgumentNullException(); } if (bIn == bOut) { throw new ArgumentException("bin == bout"); } if (bIn.Length != bOut.Length) { throw new ArgumentException("Length aren't equal"); } int iv; int tmp_csz, csz; //CODEC_TRACE("codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size); /* just copy raw data from in to out when key size is 0 * i.e. during a rekey of a plaintext database */ if (ctx.key_sz == 0) { Array.Copy(bIn, bOut, bIn.Length); //memcpy(out, in, size); return(SQLITE_OK); } if (mode == CIPHER_ENCRYPT) { using (var msEncrypt = new MemoryStream(bIn.Length)) { using ( var csEncrypt = new CryptoStream( msEncrypt, ctx.encryptor, CryptoStreamMode.Write ) ) { csEncrypt.Write(bIn, 0, bIn.Length); } var msData = msEncrypt.ToArray(); Array.Copy(msData, bOut, msData.Length); } } else { using (var inputMs = new MemoryStream(bIn)) { using (var outputMs = new MemoryStream(bOut)) { var buffer = new byte[4096]; using ( var csDecrypt = new CryptoStream( inputMs, ctx.decryptor, CryptoStreamMode.Read ) ) { var read = csDecrypt.Read(buffer, 0, buffer.Length); while (read > 0) { outputMs.Write(buffer, 0, read); read = csDecrypt.Read(buffer, 0, buffer.Length); } } var outputMsData = outputMs.ToArray(); if (outputMsData.Length != bOut.Length) { throw new ArgumentException("Length"); } Array.Copy(outputMsData, bOut, outputMsData.Length); } } } return(SQLITE_OK); }
/** * Set the raw password / key data for a cipher context * * returns SQLITE_OK if assignment was successfull * returns SQLITE_NOMEM if an error occured allocating memory * returns SQLITE_ERROR if the key couldn't be set because the pass was null or size was zero */ static int cipher_ctx_set_pass( cipher_ctx ctx, string zKey, int nKey ) { ctx.pass = null; // codec_free( ctx.pass, ctx.pass_sz ); ctx.pass_sz = nKey; if ( !String.IsNullOrEmpty( zKey ) && nKey > 0 ) { //ctx.pass = sqlite3Malloc(nKey); //if(ctx.pass == null) return SQLITE_NOMEM; ctx.pass = zKey;//memcpy(ctx.pass, zKey, nKey); return SQLITE_OK; } return SQLITE_ERROR; }