Skip to content

Commit 4731d94

Browse files
Merge support API into master
2 parents 30508c4 + 5d3945f commit 4731d94

File tree

10 files changed

+492
-77
lines changed

10 files changed

+492
-77
lines changed

.gitignore

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ android-database-sqlcipher/.externalNativeBuild/
88
android-database-sqlcipher/src/main/libs*
99
android-database-sqlcipher/src/main/obj
1010
android-database-sqlcipher/src/main/external/openssl-*/
11-
12-
local.properties
11+
.idea/
1312
*.iml
14-
.idea
13+
local.properties

README.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
### Download Source and Binaries
2+
3+
The latest AAR binary package information can be [here](https://www.zetetic.net/sqlcipher/open-source), the source can be found [here](https://github.com/sqlcipher/android-database-sqlcipher).
4+
<p><a title="Latest version from Maven Central" href="https://maven-badges.herokuapp.com/maven-central/net.zetetic/android-database-sqlcipher"><img src="https://maven-badges.herokuapp.com/maven-central/net.zetetic/android-database-sqlcipher/badge.svg"></a></p>
5+
6+
### Compatibility
7+
8+
SQLCipher for Android runs on Android 4–Android 9, for `armeabi`, `armeabi-v7a`, `x86`, `x86_64`, and `arm64_v8a` architectures.
9+
10+
### Contributions
11+
12+
We welcome contributions, to contribute to SQLCipher for Android, a [contributor agreement](https://www.zetetic.net/contributions/) needs to be submitted. All submissions should be based on the `master` branch.
13+
14+
### An Illustrative Terminal Listing
15+
16+
A typical SQLite database in unencrypted, and visually parseable even as encoded text. The following example shows the difference between hexdumps of a standard SQLite database and one implementing SQLCipher.
17+
18+
```
19+
~ sjlombardo$ hexdump -C sqlite.db
20+
00000000 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 |SQLite format 3.|
21+
22+
000003c0 65 74 32 74 32 03 43 52 45 41 54 45 20 54 41 42 |et2t2.CREATE TAB|
23+
000003d0 4c 45 20 74 32 28 61 2c 62 29 24 01 06 17 11 11 |LE t2(a,b)$…..|
24+
25+
000007e0 20 74 68 65 20 73 68 6f 77 15 01 03 01 2f 01 6f | the show…./.o|
26+
000007f0 6e 65 20 66 6f 72 20 74 68 65 20 6d 6f 6e 65 79 |ne for the money|
27+
28+
~ $ sqlite3 sqlcipher.db
29+
sqlite> PRAGMA KEY=’test123′;
30+
sqlite> CREATE TABLE t1(a,b);
31+
sqlite> INSERT INTO t1(a,b) VALUES (‘one for the money’, ‘two for the show’);
32+
sqlite> .quit
33+
34+
~ $ hexdump -C sqlcipher.db
35+
00000000 84 d1 36 18 eb b5 82 90 c4 70 0d ee 43 cb 61 87 |.?6.?..?p.?C?a.|
36+
00000010 91 42 3c cd 55 24 ab c6 c4 1d c6 67 b4 e3 96 bb |.B?..?|
37+
00000bf0 8e 99 ee 28 23 43 ab a4 97 cd 63 42 8a 8e 7c c6 |..?(#C??.?cB..|?|
38+
39+
~ $ sqlite3 sqlcipher.db
40+
sqlite> SELECT * FROM t1;
41+
Error: file is encrypted or is not a database
42+
```
43+
(example courtesy of SQLCipher)
44+
45+
### Application Integration
46+
47+
You have a two main options for using SQLCipher for Android in your app:
48+
49+
- Using it with Room or other consumers of the `androidx.sqlite` API
50+
51+
- Using the native SQLCipher for Android classes
52+
53+
In both cases, you will need to add a dependency on `net.zetetic:android-database-sqlcipher`,
54+
such as having the following line in your module's `build.gradle` `dependencies`
55+
closure:
56+
57+
```gradle
58+
implementation 'net.zetetic:android-database-sqlcipher:4.2.0'
59+
```
60+
61+
(replacing `4.2.0` with the version you want)
62+
63+
<a title="Latest version from Maven Central" href="https://maven-badges.herokuapp.com/maven-central/net.zetetic/android-database-sqlcipher"><img src="https://maven-badges.herokuapp.com/maven-central/net.zetetic/android-database-sqlcipher/badge.svg"></a>
64+
65+
#### Using SQLCipher for Android With Room
66+
67+
SQLCipher for Android has a `SupportFactory` class in the `net.sqlcipher.database` package
68+
that can be used to configure Room to use SQLCipher for Android.
69+
70+
There are two `SupportFactory` constructors:
71+
72+
- Both take a `byte[]` to use as the passphrase (if you have a `char[]`, use
73+
`SQLiteDatabase.getBytes()` to get a suitable `byte[]` to use)
74+
75+
- One constructor has a second parameter: a `SQLiteDatabaseHook` that you can use
76+
for executing SQL statements before or after the passphrase is used to decrypt
77+
the database
78+
79+
Then, pass your `SupportFactory` to `openHelperFactory()` on your `RoomDatabase.Builder`:
80+
81+
```java
82+
final byte[] passphrase = SQLiteDatabase.getBytes(userEnteredPassphrase);
83+
final SupportFactory factory = new SupportFactory(passphrase);
84+
final SomeDatabase room = Room.databaseBuilder(activity, SomeDatabase.class, DB_NAME)
85+
.openHelperFactory(factory)
86+
.build();
87+
```
88+
89+
Now, Room will make all of its database requests using SQLCipher for Android instead
90+
of the framework copy of SQLCipher.
91+
92+
Note that `SupportFactory` should work with other consumers of the `androidx.sqlite` API;
93+
Room is merely a prominent example.
94+
95+
#### Using SQLCipher for Android's Native API
96+
97+
If you have existing SQLite code using classes like `SQLiteDatabase` and `SQLiteOpenHelper`,
98+
converting your code to use SQLCipher for Android mostly is a three-step process:
99+
100+
1. Replace all `android.database.sqlite.*` `import` statements with ones that
101+
use `net.sqlcipher.database.*` (e.g., convert `android.database.sqlite.SQLiteDatabase`
102+
to `net.sqlcipher.database.SQLiteDatabase`)
103+
104+
2. Before attempting to open a database, call `SQLiteDatabase.loadLibs()`, passing
105+
in a `Context` (e.g., add this to `onCreate()` of your `Application` subclass, using
106+
the `Application` itself as the `Context`)
107+
108+
3. When opening a database (e.g., `SQLiteDatabase.openOrCreateDatabase()`), pass
109+
in the passphrase as a `char[]` or `byte[]`
110+
111+
The rest of your code may not need any changes.
112+
113+
An article covering both integration of SQLCipher into an Android application as well as building the source can be found [here](https://www.zetetic.net/sqlcipher/sqlcipher-for-android/).
114+
115+
### Building
116+
117+
In order to build `android-database-sqlcipher` from source you will need both the Android SDK, Gradle, and the Android NDK. We currently recommend using Android NDK version `r15c`, however we plan to update to a newer NDK release when possible. To complete the `make` command, the `ANDROID_NDK_ROOT` environment variable must be defined which should point to your NDK root. Once you have cloned the repo, change directory into the root of the repository and run the following commands:
118+
119+
```
120+
# this only needs to be done once
121+
make init
122+
123+
# to build the source for debug:
124+
make build-debug
125+
# or for a release build:
126+
make build-release
127+
```
128+
129+
### License
130+
131+
The Android support libraries are licensed under Apache 2.0, in line with the Android OS code on which they are based. The SQLCipher code itself is licensed under a BSD-style license from Zetetic LLC. Finally, the original SQLite code itself is in the public domain.

README.org

Lines changed: 0 additions & 70 deletions
This file was deleted.

android-database-sqlcipher/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ android {
3636
}
3737
}
3838

39+
dependencies {
40+
implementation "androidx.sqlite:sqlite:2.0.1"
41+
}
42+
3943
clean.dependsOn cleanNative
4044
check.dependsOn editorconfigCheck
4145
buildNative.mustRunAfter buildAmalgamation
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (C) 2019 Mark L. Murphy
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.sqlcipher.database;
18+
19+
import android.util.SparseArray;
20+
import androidx.sqlite.db.SupportSQLiteProgram;
21+
22+
/*
23+
This class is a concrete implementation of SupportSQLiteProgram,
24+
for use in supporting bind arguments for the SQLiteDatabase query()
25+
methods that take a SupportSQLiteQuery parameter.
26+
27+
In Google's FrameworkSQLiteDatabase implementation of those query()
28+
methods, it uses FrameworkSQLiteProgram, which has the same basic implementation
29+
as does BindingsRecorder.
30+
*/
31+
class BindingsRecorder implements SupportSQLiteProgram {
32+
private SparseArray<Object> bindings=new SparseArray<>();
33+
34+
@Override
35+
public void bindNull(int index) {
36+
bindings.put(index, null);
37+
}
38+
39+
@Override
40+
public void bindLong(int index, long value) {
41+
bindings.put(index, value);
42+
}
43+
44+
@Override
45+
public void bindDouble(int index, double value) {
46+
bindings.put(index, value);
47+
}
48+
49+
@Override
50+
public void bindString(int index, String value) {
51+
bindings.put(index, value);
52+
}
53+
54+
@Override
55+
public void bindBlob(int index, byte[] value) {
56+
bindings.put(index, value);
57+
}
58+
59+
@Override
60+
public void clearBindings() {
61+
bindings.clear();
62+
}
63+
64+
@Override
65+
public void close() {
66+
clearBindings();
67+
}
68+
69+
String[] getBindings() {
70+
final String[] result=new String[bindings.size()];
71+
72+
for (int i=0;i<bindings.size();i++) {
73+
int key=bindings.keyAt(i);
74+
Object binding=bindings.get(key);
75+
76+
if (binding!=null) {
77+
result[i]=bindings.get(key).toString();
78+
}
79+
else {
80+
result[i]=""; // SQLCipher does not like null binding values
81+
}
82+
}
83+
84+
return result;
85+
}
86+
}

0 commit comments

Comments
 (0)