2 # codec.test developed by Stephen Lombardo (Zetetic LLC)
3 # sjlombardo at zetetic dot 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 # Test rekey as first operation on an empty database
42 # it should raise an error
43 do_test rekey-as-first-op-on-empty {
44 sqlite_orig db test.db
47 PRAGMA rekey = 'testkey';
50 } {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.}}
52 file delete -force test.db
54 # test a rekey operation as the first op on an existing database
55 # then test that now the new key opens the database
56 # now close database re-open with new key
57 setup test.db "'testkey'"
58 do_test rekey-as-first-operation {
59 sqlite_orig db test.db
61 PRAGMA key = 'testkey';
62 PRAGMA rekey = 'testkeynew';
66 sqlite_orig db test.db
68 PRAGMA key = 'testkeynew';
69 SELECT name FROM sqlite_schema WHERE type='table';
73 file delete -force test.db
75 # create a new database, insert some data
76 # then rekey it with the same password
77 do_test rekey-same-passkey {
78 sqlite_orig db test.db
81 PRAGMA key = 'test123';
86 for {set i 1} {$i<=1000} {incr i} {
87 set r [expr {int(rand()*500000)}]
88 execsql "INSERT INTO t1 VALUES($i,'value $r');"
93 SELECT count(*) FROM t1;
94 PRAGMA rekey = 'test123';
95 SELECT count(*) FROM t1;
99 file delete -force test.db
101 # create a new database, insert some data
102 # then rekey it. Make sure it is immediately
103 # readable. Then close it and make sure it can be
105 do_test rekey-and-query-1 {
106 sqlite_orig db test.db
109 PRAGMA key = 'test123';
110 CREATE TABLE t1(a,b);
114 for {set i 1} {$i<=1000} {incr i} {
115 set r [expr {int(rand()*500000)}]
116 execsql "INSERT INTO t1 VALUES($i,'value $r');"
121 SELECT count(*) FROM t1;
122 PRAGMA rekey = 'test321';
123 SELECT count(*) FROM t1;
129 do_test rekey-and-query-2 {
130 sqlite_orig db test.db
132 PRAGMA key = 'test321';
133 SELECT count(*) FROM t1;
137 file delete -force test.db
139 # create a new database, insert some data
140 # delete about 50% of the data
141 # write some new data
143 # then rekey it. Make sure it is immediately
144 # readable. Then close it and make sure it can be
145 # read back. This test will ensure that Secure Delete
146 # is enabled and all pages are being written and are not
147 # being optimized out by sqlite3PagerDontWrite
148 do_test rekey-delete-and-query-1 {
149 sqlite_orig db test.db
152 PRAGMA key = 'test123';
153 CREATE TABLE t1(a,b);
154 CREATE INDEX ta_a ON t1(a);
158 for {set i 1} {$i<1000} {incr i} {
159 set r1 [expr {int(rand()*32767)}]
160 execsql "INSERT INTO t1 VALUES($i,$r1);"
163 execsql "DELETE FROM t1 WHERE a < 500;"
165 set r1 [expr {int(rand()*32767)}]
166 execsql "UPDATE t1 SET b = $r1 WHERE a < 750;"
168 execsql "DELETE FROM t1 WHERE a > 750;"
172 SELECT (count(*) > 0) FROM t1;
177 do_test rekey-delete-and-query-2 {
178 sqlite_orig db test.db
180 PRAGMA key = 'test123';
181 PRAGMA rekey = 'test321';
182 SELECT count(*) > 1 FROM t1;
183 PRAGMA integrity_check;
188 do_test rekey-delete-and-query-3 {
189 sqlite_orig db test.db
191 PRAGMA key = 'test321';
192 SELECT count(*) > 1 FROM t1;
196 file delete -force test.db
199 # same as previous test, but use WAL
200 do_test rekey-delete-and-query-wal-1 {
201 sqlite_orig db test.db
204 PRAGMA key = 'test123';
205 PRAGMA journal_mode = WAL;
206 CREATE TABLE t1(a,b);
207 CREATE INDEX ta_a ON t1(a);
211 for {set i 1} {$i<1000} {incr i} {
212 set r1 [expr {int(rand()*32767)}]
213 execsql "INSERT INTO t1 VALUES($i,$r1);"
216 execsql "DELETE FROM t1 WHERE a < 500;"
218 set r1 [expr {int(rand()*32767)}]
219 execsql "UPDATE t1 SET b = $r1 WHERE a < 750;"
221 execsql "DELETE FROM t1 WHERE a > 750;"
225 SELECT (count(*) > 0) FROM t1;
230 do_test rekey-delete-and-query-wal-2 {
231 sqlite_orig db test.db
233 PRAGMA key = 'test123';
234 PRAGMA journal_mode = WAL;
235 PRAGMA rekey = 'test321';
236 SELECT count(*) > 1 FROM t1;
237 PRAGMA integrity_check;
242 do_test rekey-delete-and-query-wal-3 {
243 sqlite_orig db test.db
245 PRAGMA key = 'test321';
246 PRAGMA journal_mode = WAL;
247 SELECT count(*) > 1 FROM t1;
251 file delete -force test.db
253 do_test rekey-database-by-name {
254 sqlite_orig db test.db
256 attach database 'new.db' as new;
257 pragma new.key = 'foo';
258 create table new.t1(a,b);
259 insert into new.t1(a,b) values('foo', 'bar');
260 pragma new.rekey = 'bar';
265 sqlite_orig db new.db
272 file delete -force test.db
273 file delete -force new.db