add pragma page_size compatibility so it will operate on encrypted databases
[sqlcipher.git] / test / sqlcipher-core.test
blobc4b5e3bf44c1aa49b1b2244f16c5c67c203d05a8
1 # SQLCipher
2 # codec.test developed by Stephen Lombardo (Zetetic LLC)
3 # sjlombardo at zetetic dot net
4 # http://zetetic.net
6 # Copyright (c) 2018, ZETETIC LLC
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 #     * Redistributions of source code must retain the above copyright
10 #       notice, this list of conditions and the following disclaimer.
11 #     * Redistributions in binary form must reproduce the above copyright
12 #       notice, this list of conditions and the following disclaimer in the
13 #       documentation and/or other materials provided with the distribution.
14 #     * Neither the name of the ZETETIC LLC nor the
15 #       names of its contributors may be used to endorse or promote products
16 #       derived from this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 # DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 # This file implements regression tests for SQLite library.  The
30 # focus of this script is testing code cipher features.
32 # NOTE: tester.tcl has overridden the definition of sqlite3 to
33 # automatically pass in a key value. Thus tests in this file
34 # should explicitly close and open db with sqlite_orig in order
35 # to bypass default key assignment.
37 set testdir [file dirname $argv0]
38 source $testdir/tester.tcl
39 source $testdir/sqlcipher.tcl
41 # The database is initially empty.
42 # set an hex key create some basic data
43 # create table and insert operations should work
44 # close database, open it again with the same
45 # hex key. verify that the table is readable
46 # and the data just inserted is visible
47 setup test.db "\"x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'\""
48 do_test will-open-with-correct-raw-key {
49   sqlite_orig db test.db
50   execsql {
51     PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'";
52     SELECT name FROM sqlite_schema WHERE type='table';
53     SELECT * from t1;
54   }
55 } {ok t1 test1 test2}
56 db close
57 file delete -force test.db
59 # set an encryption key (non-hex) and create some basic data
60 # create table and insert operations should work
61 # close database, open it again with the same
62 # key. verify that the table is readable
63 # and the data just inserted is visible
64 setup test.db "'testkey'"
65 do_test will-open-with-correct-derived-key {
67   sqlite_orig db test.db
68   execsql {
69     PRAGMA key = 'testkey';
70     SELECT name FROM sqlite_schema WHERE type='table';
71     SELECT * from t1;
72   }
73 } {ok t1 test1 test2}
74 db close
75 file delete -force test.db
77 # set an encryption key (non-hex) and create
78 # temp tables, verify you can read from
79 # sqlite_temp_master
80 setup test.db "'testkey'"
81 do_test test-temp-master {
82   sqlite_orig db test.db
83   execsql {
84     PRAGMA key = 'testkey';
85     CREATE TEMPORARY TABLE temp_t1(a,b);
86     INSERT INTO temp_t1(a,b) VALUES ('test1', 'test2');
87     SELECT name FROM sqlite_temp_master WHERE type='table';
88     SELECT * from temp_t1;
89   }
90 } {ok temp_t1 test1 test2}
91 db close
92 file delete -force test.db
94 # verify that a when a standard database is encrypted the first
95 # 16 bytes are not "SQLite format 3\0" 
96 do_test test-sqlcipher-header-overwrite {
97   sqlite_orig db test.db
98   execsql {
99     PRAGMA key = 'test';
100     CREATE TABLE t1(a,b);
101   }
102   db close
103   set header [hexio_read test.db 0 16]
104   string equal $header "53514C69746520666F726D6174203300"
105 } {0}
106 file delete -force test.db
108 # open the database and try to read from it without
109 # providing a passphrase. verify that the 
110 # an error is returned from the library
111 setup test.db "'testkey'"
112 do_test wont-open-without-key {
113   sqlite_orig db test.db
114   catchsql {
115     SELECT name FROM sqlite_schema WHERE type='table';
116   }
117 } {1 {file is not a database}}
118 db close
119 file delete -force test.db
121 # open the database and try to set an invalid
122 # passphrase. verify that an error is returned
123 # and that data couldn't be read
124 setup test.db "'testkey'"
125 do_test wont-open-with-invalid-derived-key {
126   sqlite_orig db test.db
127   catchsql {
128     PRAGMA key = 'testkey2';
129     SELECT name FROM sqlite_schema WHERE type='table';
130   }
131 } {1 {file is not a database}}
132 db close
133 file delete -force test.db
135 # open the database and try to set an invalid
136 # hex key. verify that an error is returned
137 # and that data couldn't be read
138 setup test.db "'testkey'"
139 do_test wont-open-with-invalid-raw-key {
140   sqlite_orig db test.db
141   catchsql {
142     PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836480'";
143     SELECT name FROM sqlite_schema WHERE type='table';
144   }
145 } {1 {file is not a database}}
146 db close
147 file delete -force test.db
149 # test a large number of inserts in a transaction to a memory database 
150 do_test memory-database {
151   sqlite_orig db :memory:
152   execsql {
153     PRAGMA key = 'testkey3';
154     BEGIN;
155     CREATE TABLE t2(a,b);
156   }
157   for {set i 1} {$i<=25000} {incr i} {
158     set r [expr {int(rand()*500000)}]
159     execsql "INSERT INTO t2 VALUES($i,$r);" 
160   }
161   execsql {
162     COMMIT;
163     SELECT count(*) FROM t2;
164     DELETE FROM t2;
165     SELECT count(*) FROM t2;
166   } 
167 } {25000 0}
168 db close
170 # test a large number of inserts in a transaction for multiple pages
171 do_test multi-page-database {
172   sqlite_orig db test.db
173   execsql {
174     PRAGMA key = 'testkey';
175     CREATE TABLE t2(a,b);
176     BEGIN;
177   }
178   for {set i 1} {$i<=25000} {incr i} {
179     set r [expr {int(rand()*500000)}]
180     execsql "INSERT INTO t2 VALUES($i,$r);" 
181   }
182   execsql {
183     COMMIT;
184     SELECT count(*) FROM t2;
185   } 
186 } {25000}
187 db close
188 file delete -force test.db
190 # attach an encrypted database
191 # without specifying key, verify it fails
192 # even if the source passwords are the same
193 # because the kdf salts are different
194 setup test.db "'testkey'"
195 do_test attach-database-with-default-key {
196   sqlite_orig db2 test2.db
197   set rc {}
199   execsql {
200     PRAGMA key = 'testkey';
201     PRAGMA cipher_add_random = "x'deadbaad'";
202     CREATE TABLE t2(a,b);
203     INSERT INTO t2 VALUES ('test1', 'test2'); 
204   } db2
206   lappend rc [catchsql {
207     ATTACH 'test.db' AS db;
208   } db2]
210   lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]]
212 } {{1 {file is not a database}} 0}
213 db2 close
214 file delete -force test.db
215 file delete -force test2.db
217 # attach an empty encrypted database
218 # without specifying key, verify the database has the same
219 # salt and as the original 
220 setup test.db "'testkey'"
221 do_test attach-empty-database-with-default-key {
222   sqlite_orig db test.db
223   set rc {}
225   execsql {
226     PRAGMA  key='testkey';
227     INSERT INTO t1(a,b) values (1,2);
228     ATTACH DATABASE 'test2.db' AS test;
229     CREATE TABLE test.t1(a,b);
230     INSERT INTO test.t1 SELECT * FROM t1;
231     DETACH DATABASE test;
232   }
234   sqlite_orig db2 test2.db
236   lappend rc [execsql {
237     PRAGMA  key='testkey';
238     SELECT count(*) FROM t1;
239   } db2]
240   lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]]
241 } {{ok 2} 1}
242 db close
243 db2 close
244 file delete -force test.db
245 file delete -force test2.db
247 # attach an empty encrypted database as the first operation on a keyed database. Verify
248 # that the new database has the same salt as the original.
250 # HISTORICAL NOTE: The original behavior of SQLCipher under these conditions
251 # was that the databases would have different salts but the same keys. This was because
252 # derivation of the key spec would not have occurred yet. However, upstream check-in
253 # https://sqlite.org/src/info/a02da71f3a80dd8e changed this behavior by
254 # forcing a read of the main database schema during the attach operation.
255 # This causes the main database to be opened and the key derivation logic to fire which
256 # reads the salt. Thus the current behavior of this test should now be identical
257 # to the previous attach-empty-database-with-default-key.
259 setup test.db "'testkey'"
260 do_test attach-empty-database-with-default-key-first-op {
261   sqlite_orig db test.db
262   set rc {}
264   execsql {
265     PRAGMA  key='testkey';
266     ATTACH DATABASE 'test2.db' AS test;
267     CREATE TABLE test.t1(a,b);
268     INSERT INTO test.t1 SELECT * FROM t1;
269     DETACH DATABASE test;
270   }
272   sqlite_orig db2 test2.db
274   lappend rc [execsql {
275     PRAGMA  key='testkey';
276     SELECT count(*) FROM t1;
277   } db2]
279   lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]]
280 } {{ok 1} 1}
281 db close
282 db2 close
283 file delete -force test.db
284 file delete -force test2.db
286 # attach an empty encrypted database 
287 # on a keyed database when PRAGMA cipher_store_pass = 1
288 # and verify different salts
289 setup test.db "'testkey'"
290 do_test attach-empty-database-with-cipher-store-pass {
291   sqlite_orig db test.db
292   set rc {}
294   execsql {
295     PRAGMA  key='testkey';
296     PRAGMA cipher_store_pass = 1;
297     INSERT INTO t1(a,b) VALUES (1,2);
298     ATTACH DATABASE 'test2.db' AS test;
299     CREATE TABLE test.t1(a,b);
300     INSERT INTO test.t1 SELECT * FROM t1;
301     DETACH DATABASE test;
302   }
304   sqlite_orig db2 test2.db
306   lappend rc [execsql {
307     PRAGMA  key='testkey';
308     SELECT count(*) FROM t1;
309   } db2]
310   lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]]
311 } {{ok 2} 0}
312 db close
313 db2 close
314 file delete -force test.db
315 file delete -force test2.db
317 # attach an encrypted database
318 # without specifying key, verify it attaches
319 # correctly when PRAGMA cipher_store_pass = 1
320 # is set
321 do_test attach-database-with-default-key-using-cipher-store-pass {
322     sqlite_orig db1 test.db  
323     execsql {
324         PRAGMA key = 'testkey';
325         CREATE TABLE t1(a,b);
326         INSERT INTO t1(a,b) VALUES('foo', 'bar');        
327     } db1
328     db1 close
330     sqlite_orig db2 test2.db
331     execsql {
332       PRAGMA key = 'testkey';
333       CREATE TABLE t2(a,b);
334       INSERT INTO t2 VALUES ('test1', 'test2'); 
335     } db2
336     db2 close
338     sqlite_orig db1 test.db
339     execsql {
340         PRAGMA key = 'testkey';
341         PRAGMA cipher_store_pass = 1;
342         ATTACH DATABASE 'test2.db' as db2;
343         SELECT sqlcipher_export('db2');
344         DETACH DATABASE db2;
345     } db1
346     db1 close
348     sqlite_orig db2 test2.db  
349     execsql {
350         PRAGMA key = 'testkey';
351         SELECT * FROM t1;
352     } db2
354 } {ok foo bar}
355 db2 close
356 file delete -force test.db
357 file delete -force test2.db
359 # attach an encrypted database
360 # where both database have the same
361 # key explicitly and verify they have different
362 # salt values
363 setup test.db "'testkey'"
364 do_test attach-database-with-same-key {
365   sqlite_orig db2 test2.db
366   
367   set rc {}
369   execsql {
370     PRAGMA key = 'testkey';
371     CREATE TABLE t2(a,b);
372     INSERT INTO t2 VALUES ('test1', 'test2'); 
373   } db2
375   lappend rc [execsql {
376     SELECT count(*) FROM t2;
377     ATTACH 'test.db' AS db KEY 'testkey';
378     SELECT count(*) FROM db.t1;
379   } db2]
380   
381   lappend rc [string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]]
382 } {{1 1} 0}
383 db2 close
384 file delete -force test.db
385 file delete -force test2.db
387 # attach an encrypted database
388 # where databases have different keys
389 setup test.db "'testkey'"
390 do_test attach-database-with-different-keys {
391   sqlite_orig db2 test2.db
393   execsql {
394     PRAGMA key = 'testkey2';
395     CREATE TABLE t2(a,b);
396     INSERT INTO t2 VALUES ('test1', 'test2'); 
397   } db2
398   
399   execsql {
400     ATTACH 'test.db' AS db KEY 'testkey';
401     SELECT count(*) FROM db.t1;
402     SELECT count(*) FROM t2;
403   } db2
405 } {1 1}
406 db2 close
407 file delete -force test.db
408 file delete -force test2.db
410 # test locking across multiple handles
411 setup test.db "'testkey'"
412 do_test locking-across-multiple-handles-start {
413   sqlite_orig db test.db
415   execsql {
416     PRAGMA key = 'testkey';
417     BEGIN EXCLUSIVE;
418     INSERT INTO t1 VALUES(1,2);
419   } 
420   
421   sqlite_orig dba test.db
422   catchsql {
423     PRAGMA key = 'testkey';
424       SELECT count(*) FROM t1;
425   } dba
427  } {1 {database is locked}} 
429 do_test locking-accross-multiple-handles-finish {
430  execsql {
431     COMMIT;
432   }
434   execsql {
435     SELECT count(*) FROM t1;
436   } dba
437 } {2}
438 db close
439 dba close
440 file delete -force test.db
442 # alter schema
443 setup test.db "'testkey'"
444 do_test alter-schema {
445   sqlite_orig db test.db
446   execsql {
447     PRAGMA key = 'testkey';
448     ALTER TABLE t1 ADD COLUMN c;
449     INSERT INTO t1 VALUES (1,2,3);
450     INSERT INTO t1 VALUES (1,2,4);
451     CREATE TABLE t1a (a);
452     INSERT INTO t1a VALUES ('teststring');
453   }
454   db close
456   sqlite_orig db test.db
457   execsql {
458     PRAGMA key = 'testkey';
459     SELECT count(*) FROM t1 WHERE a IS NOT NULL;
460     SELECT count(*) FROM t1 WHERE c IS NOT NULL;
461     SELECT * FROM t1a;
462   } 
464 } {ok 3 2 teststring}
465 db close
466 file delete -force test.db
468 # test alterations of KDF iterations and ciphers
469 # rekey then add
470 setup test.db "'testkey'"
471 do_test verify-errors-for-rekey-kdf-and-cipher-changes {
472   sqlite_orig db test.db
473   execsql {
474     PRAGMA key = 'testkey';
475     PRAGMA rekey_kdf_iter = 1000;
476     PRAGMA rekey_cipher = 'aes-256-ecb';
477   } 
478 } {ok {PRAGMA rekey_kdf_iter is no longer supported.} {PRAGMA rekey_cipher is no longer supported.}}
479 db close
480 file delete -force test.db
483 setup test.db "'testkey'"
484 do_test verify-errors-for-cipher-change {
485   sqlite_orig db test.db
486   execsql {
487     PRAGMA key = 'testkey';
488     PRAGMA cipher = 'aes-256-ecb';
489   } 
490 } {ok {PRAGMA cipher is no longer supported.}}
491 db close
492 file delete -force test.db
495 # 1. create a database with a custom page size, 
496 # 2. create table and insert operations should work
497 # 3. close database, open it again with the same
498 #    key and page size
499 # 4. verify that the table is readable
500 #    and the data just inserted is visible
501 do_test custom-pagesize-pragma-cipher-page-size {
502   sqlite_orig db test.db
504   execsql {
505     PRAGMA key = 'testkey';
506     PRAGMA cipher_page_size = 8192;
507     CREATE table t1(a,b);
508     BEGIN;
509   }
511   for {set i 1} {$i<=1000} {incr i} {
512     set r [expr {int(rand()*500000)}]
513     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
514   }
516   execsql {
517     COMMIT;
518   } 
520   db close
521   sqlite_orig db test.db
523   execsql {
524     PRAGMA key = 'testkey';
525     PRAGMA cipher_page_size = 8192;
526     SELECT count(*) FROM t1;
527   }
529 } {ok 1000}
530 db close
531 file delete -force test.db
533 # run the same logic as previous test but use
534 # pragma page_size instead
535 do_test custom-pagesize-pragma-pagesize {
536   sqlite_orig db test.db
538   execsql {
539     PRAGMA key = 'testkey';
540     PRAGMA page_size = 8192;
541     CREATE table t1(a,b);
542     BEGIN;
543   }
545   for {set i 1} {$i<=1000} {incr i} {
546     set r [expr {int(rand()*500000)}]
547     execsql "INSERT INTO t1 VALUES($i,'value $r');"
548   }
550   execsql {
551     COMMIT;
552   }
554   db close
555   sqlite_orig db test.db
557   execsql {
558     PRAGMA key = 'testkey';
559     PRAGMA page_size = 8192;
560     SELECT count(*) FROM t1;
561   }
563 } {ok 1000}
564 db close
565 file delete -force test.db
567 # open the database with the default page size
568 ## and verfiy that it is not readable 
569 do_test custom-pagesize-must-match {
570   sqlite_orig db test.db
571   execsql {
572     PRAGMA key = 'testkey';
573     PRAGMA cipher_page_size = 8192;
574     CREATE table t1(a,b);
575   }
577   db close
578   sqlite_orig db test.db
580   catchsql {
581     PRAGMA key = 'testkey';
582     SELECT name FROM sqlite_schema WHERE type='table';
583   }
584 } {1 {file is not a database}}
585 db close
586 file delete -force test.db
589 # 1. create a database with WAL journal mode
590 # 2. create table and insert operations should work
591 # 3. close database, open it again
592 # 4. verify that the table is present, readable, and that
593 #    the journal mode is WAL
594 do_test journal-mode-wal {
595   sqlite_orig db test.db
597   execsql {
598     PRAGMA key = 'testkey';
599     PRAGMA journal_mode = WAL;
600     CREATE table t1(a,b);
601     BEGIN;
602   }
604   for {set i 1} {$i<=1000} {incr i} {
605     set r [expr {int(rand()*500000)}]
606     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
607   }
609   execsql {
610     COMMIT;
611   } 
613   db close
614   sqlite_orig db test.db
616   execsql {
617     PRAGMA key = 'testkey';
618     SELECT count(*) FROM t1;
619     PRAGMA journal_mode;
620   }
622 } {ok 1000 wal}
623 db close
624 file delete -force test.db
626 # open a database and try to use an invalid
627 # passphrase. verify that an error is returned
628 # and that data couldn't be read. without closing the databsae
629 # set the correct key and verify it is working.
630 setup test.db "'testkey'"
631 do_test multiple-key-calls-safe-wrong-key-first {
632   sqlite_orig db test.db
633   set rc {}
635   lappend rc [catchsql {
636     PRAGMA key = 'testkey2';
637     SELECT count(*) FROM sqlite_schema;
638   }]
640   lappend rc [execsql {
641     PRAGMA key = 'testkey';
642     SELECT count(*) FROM sqlite_schema;
643   }]
644 } {{1 {file is not a database}} {ok 1}}
645 db close
646 file delete -force test.db
648 # open a databse and use the valid key. Then
649 # use pragma key to try to set an invalid key
650 # without closing the database. It should not do anything
652 setup test.db "'testkey'"
653 do_test multiple-key-calls-safe {
654   sqlite_orig db test.db
655   execsql {
656     PRAGMA key = 'testkey';
657     PRAGMA cache_size = 0; 
658     SELECT name FROM sqlite_schema WHERE type='table';
659     PRAGMA key = 'wrong key'; 
660     SELECT name FROM sqlite_schema WHERE type='table';
661     PRAGMA key = 'testkey'; 
662     SELECT name FROM sqlite_schema WHERE type='table';
663   }
664 } {ok t1 ok t1 ok t1}
666 db close
667 file delete -force test.db
669 # 1. create a database with a custom hmac kdf iteration count, 
670 # 2. create table and insert operations should work
671 # 3. close database, open it again with the same
672 #    key and  hmac kdf iteration count
673 # 4. verify that the table is readable
674 #    and the data just inserted is visible
675 do_test custom-hmac-kdf-iter {
676   sqlite_orig db test.db
678   execsql {
679     PRAGMA key = 'testkey';
680     PRAGMA kdf_iter = 10;
681     CREATE table t1(a,b);
682     BEGIN;
683   }
685   for {set i 1} {$i<=1000} {incr i} {
686     set r [expr {int(rand()*500000)}]
687     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
688   }
690   execsql {
691     COMMIT;
692   } 
694   db close
695   sqlite_orig db test.db
697   execsql {
698     PRAGMA key = 'testkey';
699     PRAGMA kdf_iter = 10;
700     SELECT count(*) FROM t1;
701   }
703 } {ok 1000}
704 db close
706 # open the database with the default hmac
707 # kdf iteration count
708 # to verify that it is not readable 
709 do_test custom-hmac-kdf-iter-must-match {
710   sqlite_orig db test.db
711   catchsql {
712     PRAGMA key = 'testkey';
713     SELECT name FROM sqlite_schema WHERE type='table';
714   }
715 } {1 {file is not a database}}
716 db close
717 file delete -force test.db
719 # open the database and turn on auto_vacuum
720 # then insert a bunch of data, delete it 
721 # and verify that the file has become smaller
722 # but can still be opened with the proper
723 # key
724 do_test auto-vacuum {
725   sqlite_orig db test.db
726   set rc {}
728   execsql {
729     PRAGMA key = 'testkey';
730     PRAGMA auto_vacuum=FULL;
731     CREATE table t1(a,b);
732     BEGIN;
733   }
735   for {set i 1} {$i<=10000} {incr i} {
736     set r [expr {int(rand()*500000)}]
737     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
738   }
740   lappend rc [execsql {
741     COMMIT;
742     SELECT count(*) FROM t1;
743   }]
745   # grab current size of file
746   set sz [file size test.db]
747   
748   # delete some records, and verify
749   # autovacuum removes them
750   execsql {
751     DELETE FROM t1 WHERE rowid > 5000;
752   } 
754   db close
756   # grab new file size, post
757   # autovacuum
758   set sz2 [file size test.db]
760   # verify that the new size is 
761   # smaller than the old size
762   if {$sz > $sz2} { lappend rc true }
764   sqlite_orig db test.db
766   lappend rc [execsql {
767     PRAGMA key = 'testkey';
768     SELECT count(*) FROM t1;
769   }]
771 } {10000 true {ok 5000}}
772 db close
773 file delete -force test.db
775 # test kdf_iter and other pragmas 
776 # before a key is set. Verify that they
777 # are no-ops
778 do_test cipher-options-before-keys {
779   sqlite_orig db test.db
781   execsql {
782     PRAGMA kdf_iter = 1000;
783     PRAGMA cipher_page_size = 8192;
784     PRAGMA cipher_use_hmac = OFF;
785     PRAGMA key = 'testkey';
786     CREATE table t1(a,b);
787     INSERT INTO t1 VALUES(1,2);
788   }
789   db close
791   sqlite_orig db test.db
793   execsql {
794     PRAGMA key = 'testkey';
795     SELECT count(*) FROM t1;
796   }
798 } {ok 1}
799 db close
800 file delete -force test.db
802 # verify memory security behavior
803 # initially should report OFF
804 # then enable, check that it is ON
805 # try to turn if off, but verify that it
806 # can't be unset.
807 do_test verify-memory-security {
808     sqlite_orig db test.db
809     execsql {
810         PRAGMA cipher_memory_security;
811         PRAGMA cipher_memory_security = ON;
812         PRAGMA cipher_memory_security;
813         PRAGMA cipher_memory_security = OFF;
814         PRAGMA cipher_memory_security;
815     }
816 } {0 1 1}
817 db close
818 file delete -force test.db
820 # create two new database files, write to each
821 # and verify that they have different (i.e. random)
822 # salt values
823 do_test test-random-salt {
824   sqlite_orig db test.db
825   sqlite_orig db2 test2.db
826   execsql {
827     PRAGMA key = 'test';
828     CREATE TABLE t1(a,b);
829     INSERT INTO t1(a,b) VALUES (1,2);
830   }
831   execsql {
832     PRAGMA key = 'test';
833     CREATE TABLE t1(a,b);
834     INSERT INTO t1(a,b) VALUES (1,2);
835   } db2
836   db close
837   db2 close
838   string equal [hexio_read test.db 0 16] [hexio_read test2.db 0 16]
839 } {0}
840 file delete -force test.db
841 file delete -force test2.db
843 # test scenario where multiple handles are opened
844 # to a file that does not exist, where both handles
845 # use the same key
846 do_test multiple-handles-same-key-and-salt {
847   sqlite_orig db test.db
848   sqlite_orig dba test.db
850   execsql {
851     PRAGMA key = 'testkey';
852   }
853   execsql {
854     PRAGMA key = 'testkey';
855   } dba
857   execsql {
858     CREATE TABLE t1(a,b);
859     INSERT INTO t1 VALUES(1,2);
860   }
862   execsql {
863     SELECT count(*) FROM t1;
864   }
865   execsql {
866     SELECT count(*) FROM t1;
867   } dba
869 } {1}
870 db close
871 dba close
872 file delete -force test.db
874 do_test test_flags_fail_encrypt {
875   sqlite_orig db :memory:
876   execsql {
877     PRAGMA cipher_test;
878     PRAGMA cipher_test_on = fail_encrypt;
879     PRAGMA cipher_test;
880     PRAGMA cipher_test_off = fail_encrypt;
881     PRAGMA cipher_test;
882   }
883 } {0 1 0}
884 db close
886 do_test test_flags_fail_decrypt {
887   sqlite_orig db :memory:
888   execsql {
889     PRAGMA cipher_test;
890     PRAGMA cipher_test_on = fail_decrypt;
891     PRAGMA cipher_test;
892     PRAGMA cipher_test_off = fail_decrypt;
893     PRAGMA cipher_test;
894   }
895 } {0 2 0}
896 db close
898 do_test test_flags_fail_migrate {
899   sqlite_orig db :memory:
900   execsql {
901     PRAGMA cipher_test;
902     PRAGMA cipher_test_on = fail_migrate;
903     PRAGMA cipher_test;
904     PRAGMA cipher_test_off = fail_migrate;
905     PRAGMA cipher_test;
906   }
907 } {0 4 0}
908 db close
910 do_test test_flags_combo {
911   sqlite_orig db :memory:
912   execsql {
913     PRAGMA cipher_test;
914     PRAGMA cipher_test_on = fail_encrypt;
915     PRAGMA cipher_test_on = fail_migrate;
916     PRAGMA cipher_test;
917     PRAGMA cipher_test_off = fail_encrypt;
918     PRAGMA cipher_test_off = fail_migrate;
919     PRAGMA cipher_test;
920   }
921 } {0 5 0}
922 db close
924 # test empty key
925 # it should raise an error
926 do_test empty-key {
927   sqlite_orig db test.db
929   catchsql {
930     PRAGMA key = '';
931   }
933 } {1 {An error occurred with PRAGMA key or rekey. PRAGMA key requires a key of one or more characters. PRAGMA rekey can only be run on an existing encrypted database. Use sqlcipher_export() and ATTACH to convert encrypted/plaintext databases.}}
934 db close
935 file delete -force test.db
937 # configure URI filename support
938 # create a new encrypted database with the key via parameter
939 # close database
940 # open normally providing key via pragma verify
941 # correct key works
942 sqlite3_shutdown
943 sqlite3_config_uri 1
944 do_test uri-key {
945   sqlite_orig db file:test.db?a=a&key=testkey&c=c
947   execsql {
948     CREATE TABLE t1(a,b);
949     INSERT INTO t1 VALUES(1,2);
950   }
952   db close
953   sqlite_orig db test.db
955   catchsql {
956     PRAGMA key = 'testkey';
957     SELECT count(*) FROM t1;
958   }
960   db close
961   sqlite_orig db test.db
963   execsql {
964     PRAGMA key = 'testkey';
965     SELECT count(*) FROM t1;
966   }
968 } {ok 1}
969 db close
971 # verify wrong key fails
972 do_test uri-key-2 {
973   sqlite_orig db test.db
974   catchsql {
975     PRAGMA key = 'test';
976     SELECT count(*) FROM t1;
977   }
978 } {1 {file is not a database}}
979 db close
980 file delete -force test.db
981 sqlite3_shutdown
982 sqlite3_config_uri 0
984 finish_test