test for use of raw key with attached database
[sqlcipher.git] / test / crypto.test
bloba4d03cb5d30bf9eac6d6c5bf0121e7b369218831
1 # SQLCipher
2 # codec.test developed by Stephen Lombardo (Zetetic LLC) 
3 # sjlombardo at zetetic dot net
4 # http://zetetic.net
5
6 # Copyright (c) 2009, ZETETIC LLC
7 # All rights reserved.
8
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are met:
11 #     * Redistributions of source code must retain the above copyright
12 #       notice, this list of conditions and the following disclaimer.
13 #     * Redistributions in binary form must reproduce the above copyright
14 #       notice, this list of conditions and the following disclaimer in the
15 #       documentation and/or other materials provided with the distribution.
16 #     * Neither the name of the ZETETIC LLC nor the
17 #       names of its contributors may be used to endorse or promote products
18 #       derived from this software without specific prior written permission.
19
20 # THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
21 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 # DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
24 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 # This file implements regression tests for SQLite library.  The
32 # focus of this script is testing code cipher features.
34 # NOTE: tester.tcl has overridden the definition of sqlite3 to 
35 # automatically pass in a key value. Thus tests in this file
36 # should explicitly close and open db with sqlite_orig in order
37 # to bypass default key assignment.
40 file delete -force test.db
41 file delete -force test2.db
42 file delete -force test3.db
43 file delete -force test4.db
45 set testdir [file dirname $argv0]
46 source $testdir/tester.tcl
48 # If the library is not compiled with has_codec support then
49 # skip all tests in this file.
50 if {![sqlite_orig -has-codec]} {
51   finish_test
52   return
55 proc setup {file key} {
56   sqlite_orig db $file
57   execsql "PRAGMA key=$key;"
58   execsql {
59     CREATE table t1(a,b);
60     INSERT INTO t1 VALUES ('test1', 'test2'); 
61   } db
62   db close
65 # The database is initially empty.
66 # set an hex key create some basic data
67 # create table and insert operations should work
68 # close database, open it again with the same
69 # hex key. verify that the table is readable
70 # and the data just inserted is visible
71 setup test.db "\"x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'\""
72 do_test will-open-with-correct-raw-key {
73   sqlite_orig db test.db
74   execsql {
75     PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'";
76     SELECT name FROM sqlite_master WHERE type='table';
77     SELECT * from t1;
78   }
79 } {t1 test1 test2}
80 db close
81 file delete -force test.db
83 # set an encryption key (non-hex) and create some basic data
84 # create table and insert operations should work
85 # close database, open it again with the same
86 # key. verify that the table is readable
87 # and the data just inserted is visible
88 setup test.db "'testkey'"
89 do_test will-open-with-correct-derived-key {
91   sqlite_orig db test.db
92   execsql {
93     PRAGMA key = 'testkey';
94     SELECT name FROM sqlite_master WHERE type='table';
95     SELECT * from t1;
96   }
97 } {t1 test1 test2}
98 db close
99 file delete -force test.db
101 # open the database and try to read from it without
102 # providing a passphrase. verify that the 
103 # an error is returned from the library
104 setup test.db "'testkey'"
105 do_test wont-open-without-key {
106   sqlite_orig db test.db
107   catchsql {
108     SELECT name FROM sqlite_master WHERE type='table';
109   }
110 } {1 {file is encrypted or is not a database}}
111 db close
112 file delete -force test.db
114 # open the database and try to set an invalid
115 # passphrase. verify that an error is returned
116 # and that data couldn't be read
117 setup test.db "'testkey'"
118 do_test wont-open-with-invalid-derived-key {
119   sqlite_orig db test.db
120   catchsql {
121     PRAGMA key = 'testkey2';
122     SELECT name FROM sqlite_master WHERE type='table';
123   }
124 } {1 {file is encrypted or is not a database}}
125 db close
126 file delete -force test.db
128 # open the database and try to set an invalid
129 # hex key. verify that an error is returned
130 # and that data couldn't be read
131 setup test.db "'testkey'"
132 do_test wont-open-with-invalid-raw-key {
133   sqlite_orig db test.db
134   catchsql {
135     PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836480'";
136     SELECT name FROM sqlite_master WHERE type='table';
137   }
138 } {1 {file is encrypted or is not a database}}
139 db close
140 file delete -force test.db
142 # test a large number of inserts in a transaction to a memory database 
143 do_test memory-database {
144   sqlite_orig db :memory:
145   execsql {
146     PRAGMA key = 'testkey3';
147     BEGIN;
148     CREATE TABLE t2(a,b);
149   }
150   for {set i 1} {$i<=25000} {incr i} {
151     set r [expr {int(rand()*500000)}]
152     execsql "INSERT INTO t2 VALUES($i,$r);" 
153   }
154   execsql {
155     COMMIT;
156     SELECT count(*) FROM t2;
157     DELETE FROM t2;
158     SELECT count(*) FROM t2;
159   } 
160 } {25000 0}
161 db close
163 # test a large number of inserts in a transaction for multiple pages
164 do_test multi-page-database {
165   sqlite_orig db test.db
166   execsql {
167     PRAGMA key = 'testkey';
168     CREATE TABLE t2(a,b);
169     BEGIN;
170   }
171   for {set i 1} {$i<=25000} {incr i} {
172     set r [expr {int(rand()*500000)}]
173     execsql "INSERT INTO t2 VALUES($i,$r);" 
174   }
175   execsql {
176     COMMIT;
177     SELECT count(*) FROM t2;
178   } 
179 } {25000}
180 db close
181 file delete -force test.db
183 # test a rekey operation as the first op on a database
184 # then test that now the new key opens the database
185 # now close database re-open with new key
186 setup test.db "'testkey'"
187 do_test rekey-as-first-operation {
188   sqlite_orig db test.db
189   execsql {
190     PRAGMA key = 'testkey';
191     PRAGMA rekey = 'testkeynew';
192   }
193   db close
195   sqlite_orig db test.db
196   execsql {
197     PRAGMA key = 'testkeynew';
198     SELECT name FROM sqlite_master WHERE type='table';
199   }
200 } {t1}
201 db close
202 file delete -force test.db
204 # attach an encrypted database
205 # where both database have the same
206 # key
207 setup test.db "'testkey'"
208 do_test attach-database-with-same-key {
209   sqlite_orig db2 test2.db
211   execsql {
212     PRAGMA key = 'testkey';
213     CREATE TABLE t2(a,b);
214     INSERT INTO t2 VALUES ('test1', 'test2'); 
215   } db2
217   execsql {
218     SELECT count(*) FROM t2;
219     ATTACH 'test.db' AS db;
220     SELECT count(*) FROM db.t1;
221   } db2
223 } {1 1}
224 db2 close
225 file delete -force test.db
226 file delete -force test2.db
228 # attach an encrypted database
229 # where databases have different keys
230 setup test.db "'testkey'"
231 do_test attach-database-with-different-keys {
232   sqlite_orig db2 test2.db
234   execsql {
235     PRAGMA key = 'testkey2';
236     CREATE TABLE t2(a,b);
237     INSERT INTO t2 VALUES ('test1', 'test2'); 
238   } db2
239   
240   execsql {
241     ATTACH 'test.db' AS db KEY 'testkey';
242     SELECT count(*) FROM db.t1;
243     SELECT count(*) FROM t2;
244   } db2
246 } {1 1}
247 db2 close
248 file delete -force test.db
249 file delete -force test2.db
251 # test locking across multiple handles
252 setup test.db "'testkey'"
253 do_test locking-across-multiple-handles-start {
254   sqlite_orig db test.db
256   execsql {
257     PRAGMA key = 'testkey';
258     BEGIN EXCLUSIVE;
259     INSERT INTO t1 VALUES(1,2);
260   } 
261   
262   sqlite_orig dba test.db
263   catchsql {
264     PRAGMA key = 'testkey';
265       SELECT count(*) FROM t1;
266   } dba
268  } {1 {database is locked}} 
270 do_test locking-accross-multiple-handles-finish {
271  execsql {
272     COMMIT;
273   }
275   execsql {
276     SELECT count(*) FROM t1;
277   } dba
278 } {2}
279 db close
280 dba close
281 file delete -force test.db
283 # alter schema
284 setup test.db "'testkey'"
285 do_test alter-schema {
286   sqlite_orig db test.db
287   execsql {
288     PRAGMA key = 'testkey';
289     ALTER TABLE t1 ADD COLUMN c;
290     INSERT INTO t1 VALUES (1,2,3);
291     INSERT INTO t1 VALUES (1,2,4);
292     CREATE TABLE t1a (a);
293     INSERT INTO t1a VALUES ('teststring');
294   }
295   db close
297   sqlite_orig db test.db
298   execsql {
299     PRAGMA key = 'testkey';
300     SELECT count(*) FROM t1 WHERE a IS NOT NULL;
301     SELECT count(*) FROM t1 WHERE c IS NOT NULL;
302     SELECT * FROM t1a;
303   } 
305 } {3 2 teststring}
306 db close
307 file delete -force test.db
309 # test alterations of KDF iterations and ciphers
310 # rekey then add
311 setup test.db "'testkey'"
312 do_test non-standard-kdf-and-ciphers {
313   sqlite_orig db test.db
314   execsql {
315     PRAGMA key = 'testkey';
316     PRAGMA rekey_kdf_iter = 1000;
317     PRAGMA rekey_cipher = 'aes-256-cfb';
318     PRAGMA rekey = 'testkey2';
319     INSERT INTO t1 VALUES (1,2);
320   } 
321   db close
323   sqlite_orig db test.db
324   execsql {
325     PRAGMA key = 'testkey2';
326     PRAGMA kdf_iter = 1000;
327     PRAGMA cipher = 'aes-256-cfb';
328     SELECT count(*) FROM t1;
329   } 
331 } {2}
332 db close
333 file delete -force test.db
335 # test alterations of CIPHER from CBC Mode requiring
336 # IV to ECB mode that does not
337 setup test.db "'testkey'"
338 do_test rekey-from-cbc-to-ecb-no-iv {
339   sqlite_orig db test.db
340   execsql {
341     PRAGMA key = 'testkey';
342     BEGIN;
343   }
345   for {set i 1} {$i<=1000} {incr i} {
346     set r [expr {int(rand()*500000)}]
347     execsql "INSERT INTO t1 VALUES($i,$r);" 
348   }
349   
350   execsql {
351     COMMIT;
352     PRAGMA rekey_kdf_iter = 1000;
353     PRAGMA rekey_cipher = 'aes-128-ecb';
354     PRAGMA rekey = 'testkey';
355   } 
356   db close
358   sqlite_orig db test.db
359   execsql {
360     PRAGMA key = 'testkey';
361     PRAGMA kdf_iter = 1000;
362     PRAGMA cipher = 'aes-128-ecb';
363     SELECT count(*) FROM t1;
364   } 
366 } {1001}
367 db close
368 file delete -force test.db
370 # test alterations of CIPHER from ECB Mode (no IV) to CBC Mode
371 do_test rekey-from-ecb-to-cbc-with-iv {
372   sqlite_orig db test.db
373   execsql {
374     PRAGMA key = 'testkey';
375     PRAGMA cipher = 'aes-256-ecb';
376     CREATE table t1(a,b);
377     BEGIN;
378   }
380   for {set i 1} {$i<=1000} {incr i} {
381     set r [expr {int(rand()*500000)}]
382     execsql "INSERT INTO t1 VALUES($i,$r);" 
383   }
384   
385   execsql {
386     COMMIT;
387     PRAGMA rekey_cipher = 'aes-256-cbc';
388     PRAGMA rekey = 'testkey';
389   } 
390   db close
392   sqlite_orig db test.db
393   execsql {
394     PRAGMA key = 'testkey';
395     SELECT count(*) FROM t1;
396   } 
398 } {1000}
399 db close
400 file delete -force test.db
402 # create an unencrypted database, attach a new encrypted volume
403 # copy data between, verify the encypted database is good afterwards
404 do_test unencryped-attach {
405   sqlite_orig db test.db
407   execsql {
408     CREATE TABLE t1(a,b);
409     BEGIN;
410   } 
412   for {set i 1} {$i<=1000} {incr i} {
413     set r [expr {int(rand()*500000)}]
414     execsql "INSERT INTO t1 VALUES($i,$r);" 
415   }
416   
417   execsql {
418     COMMIT;
419     ATTACH DATABASE 'test2.db' AS db2 KEY 'testkey';
420     CREATE TABLE db2.t1(a,b);
421     INSERT INTO db2.t1 SELECT * FROM t1;
422     DETACH DATABASE db2;
423   }
424   
425   sqlite_orig db2 test2.db
426   execsql {
427     PRAGMA  key='testkey';
428     SELECT count(*) FROM t1;
429   } db2 
430 } {1000}
431 db2 close
432 file delete -force test.db
433 file delete -force test2.db
435 # create an unencrypted database, attach a new encrypted volume
436 # using a raw key copy data between, verify the encypted 
437 # database is good afterwards 
438 do_test unencryped-attach-raw-key {
439   sqlite_orig db test.db
441   execsql {
442     CREATE TABLE t1(a,b);
443     BEGIN;
444   } 
446   for {set i 1} {$i<=1000} {incr i} {
447     set r [expr {int(rand()*500000)}]
448     execsql "INSERT INTO t1 VALUES($i,$r);" 
449   }
450   
451   execsql {
452     COMMIT;
453     ATTACH DATABASE 'test2.db' AS db2 KEY "x'10483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'";
454     CREATE TABLE db2.t1(a,b);
455     INSERT INTO db2.t1 SELECT * FROM t1;
456     DETACH DATABASE db2;
457   }
458   
459   sqlite_orig db2 test2.db
460   execsql {
461     PRAGMA key="x'10483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'";
462     SELECT count(*) FROM t1;
463   } db2 
464 } {1000}
465 db2 close
466 file delete -force test.db
467 file delete -force test2.db
469 # create an encrypted database, attach an unencrypted volume
470 # copy data between, verify the unencypted database is good afterwards
471 do_test encryped-attach-unencrypted {
472   sqlite_orig db test.db
474   execsql {
475     CREATE TABLE t1(a,b);
476   } 
478   sqlite_orig db2 test2.db
479   execsql {
480     PRAGMA  key='testkey';
481     CREATE TABLE t1(a,b);
482     BEGIN;
483   }  db2
485   for {set i 1} {$i<=1000} {incr i} {
486     set r [expr {int(rand()*500000)}]
487     execsql "INSERT INTO t1 VALUES($i,$r);" db2 
488   }
489   
490   execsql {
491     COMMIT;
492     ATTACH DATABASE 'test.db' AS test KEY '';
493     INSERT INTO test.t1 SELECT * FROM t1;
494     DETACH DATABASE test;
495   } db2
497   execsql {
498     SELECT count(*) FROM t1;
499   } 
500 } {1000}
501 db close
502 db2 close
503 file delete -force test.db
504 file delete -force test2.db
506 # create an unencrypted database, attach an unencrypted volume
507 # copy data between, verify the unencypted database is good afterwards
508 do_test unencryped-attach-unencrypted {
509   sqlite_orig db test.db
511   execsql {
512     CREATE TABLE t1(a,b);
513   } 
515   sqlite_orig db2 test2.db
516   execsql {
517     CREATE TABLE t1(a,b);
518     BEGIN;
519   }  db2
521   for {set i 1} {$i<=1000} {incr i} {
522     set r [expr {int(rand()*500000)}]
523     execsql "INSERT INTO t1 VALUES($i,$r);" db2 
524   }
525   
526   execsql {
527     COMMIT;
528     ATTACH DATABASE 'test.db' AS test;
529     INSERT INTO test.t1 SELECT * FROM t1;
530     DETACH DATABASE test;
531   } db2
533   execsql {
534     SELECT count(*) FROM t1;
535   } 
536 } {1000}
537 db close
538 db2 close
539 file delete -force test.db
540 file delete -force test2.db
542 # 1. create a database with a custom page size, 
543 # 2. create table and insert operations should work
544 # 3. close database, open it again with the same
545 #    key and page size
546 # 4. verify that the table is readable
547 #    and the data just inserted is visible
548 do_test custom-pagesize {
549   sqlite_orig db test.db
551   execsql {
552     PRAGMA key = 'testkey';
553     PRAGMA cipher_page_size = 4096;
554     CREATE table t1(a,b);
555     BEGIN;
556   }
558   for {set i 1} {$i<=1000} {incr i} {
559     set r [expr {int(rand()*500000)}]
560     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
561   }
563   execsql {
564     COMMIT;
565   } 
567   db close
568   sqlite_orig db test.db
570   execsql {
571     PRAGMA key = 'testkey';
572     PRAGMA cipher_page_size = 4096;
573     SELECT count(*) FROM t1;
574   }
576 } {1000}
577 db close
579 # open the database with the default page size
580 ## and verfiy that it is not readable 
581 do_test custom-pagesize-must-match {
582   sqlite_orig db test.db
583   catchsql {
584     PRAGMA key = 'testkey';
585     SELECT name FROM sqlite_master WHERE type='table';
586   }
587 } {1 {file is encrypted or is not a database}}
588 db close
589 file delete -force test.db
591 # 1. create a database and insert a bunch of data, close the database
592 # 2. seek to the middle of a database page and write some junk
593 # 3. Open the database and verify that the database is no longer readable
594 do_test hmac-tamper-resistence {
595   sqlite_orig db test.db
597   execsql {
598     PRAGMA key = 'testkey';
599     CREATE table t1(a,b);
600     BEGIN;
601   }
603   for {set i 1} {$i<=1000} {incr i} {
604     set r [expr {int(rand()*500000)}]
605     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
606   }
608   execsql {
609     COMMIT;
610   } 
612   db close
614   # write some junk into the middle of the page
615   hexio_write test.db 2560 00
617   sqlite_orig db test.db
619   catchsql {
620     PRAGMA key = 'testkey';
621     SELECT count(*) FROM t1;
622   }
624 } {1 {database disk image is malformed}}
625 db close
626 file delete -force test.db
628 # 1. create a database and insert a bunch of data, close the database
629 # 2. seek to the middle of a database page and write some junk
630 # 3. Open the database and verify that the database is still readable
631 do_test nohmac-not-tamper-resistent {
632   sqlite_orig db test.db
634   execsql {
635     PRAGMA key = 'testkey';
636     PRAGMA cipher_use_hmac = OFF;
637     PRAGMA cipher_page_size = 1024;
638     CREATE table t1(a,b);
639     BEGIN;
640   }
642   for {set i 1} {$i<=1000} {incr i} {
643     set r [expr {int(rand()*500000)}]
644     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
645   }
647   execsql {
648     COMMIT;
649   } 
651   db close
653   # write some junk into the middle of the page
654   hexio_write test.db 2560 00
656   sqlite_orig db test.db
658   execsql {
659     PRAGMA key = 'testkey';
660     PRAGMA cipher_use_hmac = OFF;
661     PRAGMA cipher_page_size = 1024;
662     SELECT count(*) FROM t1;
663   }
665 } {1000}
666 db close
667 file delete -force test.db
669 # open a 1.1.8 database using the new code, HMAC disabled
670 do_test open-1.1.8-database {
671   sqlite_orig db sqlcipher-1.1.8-testkey.db
672   execsql {
673     PRAGMA key = 'testkey';
674     PRAGMA cipher_use_hmac = OFF;
675     SELECT count(*) FROM t1;
676     SELECT * FROM t1;
677   } 
678 } {4 1 1 one one 1 2 one two}
679 db close
682 # open a 1.1.8 database without hmac, then copy the data
683 do_test attach-and-copy-1.1.8 {
684   sqlite_orig db sqlcipher-1.1.8-testkey.db
686   execsql {
687     PRAGMA key = 'testkey';
688     PRAGMA cipher_use_hmac = OFF;
689     ATTACH DATABASE 'test.db' AS db2 KEY 'testkey-hmac'; 
690     CREATE TABLE db2.t1(a,b);
691     INSERT INTO db2.t1 SELECT * FROM main.t1;
692     DETACH DATABASE db2;
693   }
694   db close
696   sqlite_orig db test.db
697   execsql {
698     PRAGMA key = 'testkey-hmac';
699     SELECT count(*) FROM t1;
700     SELECT * FROM t1;
701   }
702 } {4 1 1 one one 1 2 one two}
703 db close
704 file delete -force test.db
706 # open a standard database, then attach a new 
707 # database with completely different options. 
708 # copy data between them, and verify that the
709 # new database can be opened with the proper data
710 do_test attached-database-pragmas {
711   sqlite_orig db test.db
713   execsql {
714     PRAGMA key = 'testkey';
715     CREATE TABLE t1(a,b);
716     BEGIN;
717   }
719   for {set i 1} {$i<=1000} {incr i} {
720     set r [expr {int(rand()*500000)}]
721     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
722   } 
724   execsql {
725     COMMIT;
726     ATTACH DATABASE 'test2.db' AS db2 KEY 'testkey2'; 
727     PRAGMA db2.cipher_page_size = 4096;
728     PRAGMA db2.cipher = 'aes-128-cbc';
729     PRAGMA db2.kdf_iter = 1000;
730     PRAGMA db2.cipher_use_hmac = OFF;
731     CREATE TABLE db2.t1(a,b);
732     INSERT INTO db2.t1 SELECT * FROM main.t1;
733     DETACH DATABASE db2;
734   }
735   db close
737   sqlite_orig db test2.db
738   execsql {
739     PRAGMA key = 'testkey2';
740     PRAGMA cipher_page_size = 4096;
741     PRAGMA cipher = 'aes-128-cbc';
742     PRAGMA kdf_iter = 1000;
743     PRAGMA cipher_use_hmac = OFF;
744     SELECT count(*) FROM t1;
745   }
746 } {1000}
747 db close
748 file delete -force test.db
749 file delete -force test2.db
751 # use the sqlcipher_export function
752 # on a non-existent database. Verify 
753 # the error gets through.
754 do_test export-error {
755   sqlite_orig db test.db
757   catchsql {
758     PRAGMA key = 'testkey';
759     CREATE TABLE t1(a,b);
760     SELECT sqlcipher_export('nodb');
761   } 
762 } {1 {unknown database nodb}}
763 db close
764 file delete -force test.db
766 # use the sqlcipher_export function
767 # to copy a complicated database. 
768 # tests autoincrement fields,
769 # indexes, views, and triggers,
770 # tables and virtual tables
771 do_test export-database {
772   sqlite_orig db test.db
774   execsql {
775     PRAGMA key = 'testkey';
776     CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
777     CREATE UNIQUE INDEX b_idx ON t1(b);
778     CREATE INDEX c_idx ON t1(c);
780     CREATE TABLE t2(b,c);
781     CREATE TRIGGER t2_after_insert AFTER INSERT ON t2
782     BEGIN 
783       INSERT INTO t1(b,c) VALUES (new.b, new.c);
784     END;
786     CREATE VIEW v1 AS
787       SELECT c FROM t1;
789     CREATE VIRTUAL TABLE fts USING fts3(a,b); 
791     BEGIN;
792     -- start with one known value
793     INSERT INTO t2 VALUES(1000000,'value 1000000');
794   }
796   for {set i 1} {$i<=999} {incr i} {
797     set r [expr {int(rand()*500000)}]
798     execsql "INSERT INTO t2 VALUES($i,'value $r');" 
799   } 
801   execsql {
802     INSERT INTO fts SELECT b,c FROM t1;
803     COMMIT;
805     ATTACH DATABASE 'test2.db' AS db2 KEY 'testkey2'; 
806     PRAGMA db2.cipher_page_size = 4096;
808     SELECT sqlcipher_export('db2');
810     DETACH DATABASE db2;
811   }
812   db close
814   sqlite_orig db test2.db
815   execsql {
816     PRAGMA key = 'testkey2';
817     PRAGMA cipher_page_size = 4096;
818     SELECT count(*) FROM t1;
819     SELECT count(*) FROM v1;
820     SELECT count(*) FROM sqlite_sequence;
821     SELECT seq FROM sqlite_sequence WHERE name = 't1';
822     INSERT INTO t2 VALUES(10001, 'value 938383');
823     SELECT count(*) FROM t1; -- verify the trigger worked
824     SELECT seq FROM sqlite_sequence WHERE name = 't1'; -- verify that autoincrement worked
825     SELECT a FROM fts WHERE b MATCH '1000000';  
826   }
827 } {1000 1000 1 1000 1001 1001 1000000}
828 db close
829 file copy -force test.db test-debug.db
830 file copy -force test2.db test2-debug.db
831 file delete -force test.db
832 file delete -force test2.db
834 # 1. create a database with WAL journal mode
835 # 2. create table and insert operations should work
836 # 3. close database, open it again
837 # 4. verify that the table is present, readable, and that
838 #    the journal mode is WAL
839 do_test journal-mode-wal {
840   sqlite_orig db test.db
842   execsql {
843     PRAGMA key = 'testkey';
844     PRAGMA journal_mode = WAL;
845     CREATE table t1(a,b);
846     BEGIN;
847   }
849   for {set i 1} {$i<=1000} {incr i} {
850     set r [expr {int(rand()*500000)}]
851     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
852   }
854   execsql {
855     COMMIT;
856   } 
858   db close
859   sqlite_orig db test.db
861   execsql {
862     PRAGMA key = 'testkey';
863     SELECT count(*) FROM t1;
864     PRAGMA journal_mode;
865   }
867 } {1000 wal}
868 db close
869 file delete -force test.db
871 # Test rekey as first operation on an empty database. should be a no-op
872 do_test rekey-as-first-op {
873   sqlite_orig db test.db
875   execsql {
876     PRAGMA rekey = 'testkey';
877     CREATE table t1(a,b);
878     BEGIN;
879   }
881   for {set i 1} {$i<=100} {incr i} {
882     set r [expr {int(rand()*500000)}]
883     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
884   }
886   execsql {
887     COMMIT;
888   } 
890   db close
891   sqlite_orig db test.db
893   execsql {
894     PRAGMA rekey = 'testkey';
895     SELECT count(*) FROM t1;
896   }
898 } {100}
899 db close
900 file delete -force test.db
902 # Test rekey as first operation follwed by key
903 do_test rekey-then-key-as-first-ops {
904   sqlite_orig db test.db
906   execsql {
907     PRAGMA rekey = '1234';
908     PRAGMA key = 'testkey';
909     CREATE table t1(a,b);
910     BEGIN;
911   }
913   for {set i 1} {$i<=100} {incr i} {
914     set r [expr {int(rand()*500000)}]
915     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
916   }
918   execsql {
919     COMMIT;
920   } 
922   db close
923   sqlite_orig db test.db
925   execsql {
926     PRAGMA rekey = '4321';
927     PRAGMA key = 'testkey';
928     SELECT count(*) FROM t1;
929   }
931 } {100}
932 db close
933 file delete -force test.db
935 setup test.db "'testkey'"
936 do_test multiple-key-calls-safe-1 {
937   sqlite_orig db test.db
938   execsql {
939     PRAGMA key = 'testkey';
940     PRAGMA cache_size = 0; 
941     SELECT name FROM sqlite_master WHERE type='table';
942   }
943 } {t1} 
945 do_test multiple-key-calls-safe-2 {
946   catchsql {
947     PRAGMA key = 'wrong key'; 
948     SELECT name FROM sqlite_master WHERE type='table';
949   }
950 } {1 {file is encrypted or is not a database}}
952 do_test multiple-key-calls-safe-3 {
953   execsql {
954     PRAGMA key = 'testkey'; 
955     SELECT name FROM sqlite_master WHERE type='table';
956   }
957 } {t1} 
959 db close
960 file delete -force test.db
962 # 1. create a database with a custom hmac kdf iteration count, 
963 # 2. create table and insert operations should work
964 # 3. close database, open it again with the same
965 #    key and  hmac kdf iteration count
966 # 4. verify that the table is readable
967 #    and the data just inserted is visible
968 do_test custom-hmac-kdf-iter {
969   sqlite_orig db test.db
971   execsql {
972     PRAGMA key = 'testkey';
973     PRAGMA fast_kdf_iter = 10;
974     CREATE table t1(a,b);
975     BEGIN;
976   }
978   for {set i 1} {$i<=1000} {incr i} {
979     set r [expr {int(rand()*500000)}]
980     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
981   }
983   execsql {
984     COMMIT;
985   } 
987   db close
988   sqlite_orig db test.db
990   execsql {
991     PRAGMA key = 'testkey';
992     PRAGMA fast_kdf_iter = 10;
993     SELECT count(*) FROM t1;
994   }
996 } {1000}
997 db close
999 # open the database with the default hmac
1000 # kdf iteration count
1001 # to verify that it is not readable 
1002 do_test custom-hmac-kdf-iter-must-match {
1003   sqlite_orig db test.db
1004   catchsql {
1005     PRAGMA key = 'testkey';
1006     SELECT name FROM sqlite_master WHERE type='table';
1007   }
1008 } {1 {file is encrypted or is not a database}}
1009 db close
1010 file delete -force test.db
1012 # open the database and turn on auto_vacuum
1013 # then insert a bunch of data, delete it 
1014 # and verify that the file has become smaller
1015 # but can still be opened with the proper
1016 # key
1017 do_test auto-vacuum {
1018   sqlite_orig db test.db
1019   set rc {}
1021   execsql {
1022     PRAGMA key = 'testkey';
1023     PRAGMA auto_vacuum=FULL;
1024     CREATE table t1(a,b);
1025     BEGIN;
1026   }
1028   for {set i 1} {$i<=10000} {incr i} {
1029     set r [expr {int(rand()*500000)}]
1030     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
1031   }
1033   lappend rc [execsql {
1034     COMMIT;
1035     SELECT count(*) FROM t1;
1036   }]
1038   # grab current size of file
1039   set sz [file size test.db]
1040   
1041   # delete some records, and verify
1042   # autovacuum removes them
1043   execsql {
1044     DELETE FROM t1 WHERE rowid > 5000;
1045   } 
1047   db close
1049   # grab new file size, post
1050   # autovacuum
1051   set sz2 [file size test.db]
1053   # verify that the new size is 
1054   # smaller than the old size
1055   if {$sz > $sz2} { lappend rc true }
1057   sqlite_orig db test.db
1059   lappend rc [execsql {
1060     PRAGMA key = 'testkey';
1061     SELECT count(*) FROM t1;
1062   }]
1064 } {10000 true 5000}
1065 db close
1066 file delete -force test.db
1068 # open the database then insert a bunch of data.
1069 # then delete it and run a manual vacuum
1070 # verify that the file has become smaller
1071 # but can still be opened with the proper
1072 # key
1073 do_test vacuum {
1074   sqlite_orig db test.db
1075   set rc {}
1077   execsql {
1078     PRAGMA key = 'testkey';
1079     CREATE table t1(a,b);
1080     BEGIN;
1081   }
1083   for {set i 1} {$i<=10000} {incr i} {
1084     set r [expr {int(rand()*500000)}]
1085     execsql "INSERT INTO t1 VALUES($i,'value $r');" 
1086   }
1088   lappend rc [execsql {
1089     COMMIT;
1090     SELECT count(*) FROM t1;
1091   }]
1093   # grab current size of file
1094   set sz [file size test.db]
1096   execsql {
1097     DELETE FROM t1 WHERE rowid > 5000;
1098     VACUUM;
1099   } 
1100   db close
1102   # grab new file size, post
1103   # autovacuum
1104   set sz2 [file size test.db]
1106   # verify that the new size is 
1107   # smaller than the old size
1108   if {$sz > $sz2} { lappend rc true }
1110   sqlite_orig db test.db
1111   lappend rc [execsql {
1112     PRAGMA key = 'testkey';
1113     SELECT count(*) FROM t1;
1114   }]
1116 } {10000 true 5000}
1117 db close
1119 finish_test