|
1 | | -/* |
| 1 | + /* |
2 | 2 | * Copyright (C) 2019 Mark L. Murphy |
3 | 3 | * |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
16 | 16 |
|
17 | 17 | package net.sqlcipher.database; |
18 | 18 |
|
| 19 | +import net.sqlcipher.database.SQLiteException; |
19 | 20 | import androidx.sqlite.db.SupportSQLiteDatabase; |
20 | 21 | import androidx.sqlite.db.SupportSQLiteOpenHelper; |
21 | 22 |
|
22 | 23 | public class SupportHelper implements SupportSQLiteOpenHelper { |
23 | 24 | private SQLiteOpenHelper standardHelper; |
24 | 25 | private byte[] passphrase; |
| 26 | + private final boolean clearPassphrase; |
25 | 27 |
|
26 | 28 | SupportHelper(final SupportSQLiteOpenHelper.Configuration configuration, |
27 | | - byte[] passphrase, final SQLiteDatabaseHook hook) { |
| 29 | + byte[] passphrase, final SQLiteDatabaseHook hook, |
| 30 | + boolean clearPassphrase) { |
28 | 31 | SQLiteDatabase.loadLibs(configuration.context); |
29 | 32 | this.passphrase = passphrase; |
| 33 | + this.clearPassphrase = clearPassphrase; |
30 | 34 |
|
31 | 35 | standardHelper = |
32 | 36 | new SQLiteOpenHelper(configuration.context, configuration.name, |
@@ -74,8 +78,27 @@ public void setWriteAheadLoggingEnabled(boolean enabled) { |
74 | 78 |
|
75 | 79 | @Override |
76 | 80 | public SupportSQLiteDatabase getWritableDatabase() { |
77 | | - SQLiteDatabase result = standardHelper.getWritableDatabase(passphrase); |
78 | | - if(passphrase != null) { |
| 81 | + SQLiteDatabase result; |
| 82 | + try { |
| 83 | + result = standardHelper.getWritableDatabase(passphrase); |
| 84 | + } catch (SQLiteException ex){ |
| 85 | + if(passphrase != null){ |
| 86 | + boolean isCleared = true; |
| 87 | + for(byte b : passphrase){ |
| 88 | + isCleared = isCleared && (b == (byte)0); |
| 89 | + } |
| 90 | + if (isCleared) { |
| 91 | + throw new IllegalStateException("The passphrase appears to be cleared. This happens by" + |
| 92 | + "default the first time you use the factory to open a database, so we can remove the" + |
| 93 | + "cleartext passphrase from memory. If you close the database yourself, please use a" + |
| 94 | + "fresh SupportFactory to reopen it. If something else (e.g., Room) closed the" + |
| 95 | + "database, and you cannot control that, use SupportFactory boolean constructor option " + |
| 96 | + "to opt out of the automatic password clearing step. See the project README for more information.", ex); |
| 97 | + } |
| 98 | + } |
| 99 | + throw ex; |
| 100 | + } |
| 101 | + if(clearPassphrase && passphrase != null) { |
79 | 102 | for (int i = 0; i < passphrase.length; i++) { |
80 | 103 | passphrase[i] = (byte)0; |
81 | 104 | } |
|
0 commit comments