我在我的应用程序中使用了一个已经存在的数据库(另见1)。我使用 Java 应用程序加密了数据库。在我的应用程序中,我尝试使用以下代码读取 encrypted_database,但出现SQLiteException: file is encrypted or is not a database:
SQLiteDatabase.loadLibs(mContext);
SQLiteDatabase dataBase = SQLiteDatabase.openDatabase(mPath, mPassword, null, SQLiteDatabase.OPEN_READONLY);
String query = "Select distinct _id from TABLE";
Cursor cursor = dataBase.rawQuery(query, null);
return cursor;
我已经用 SQLCipher 加密了我的数据库,我也可以读取数据,所以一切正常。
SQLCipher 和现有数据库的问题是我必须将完整的 unencrypted_database 复制到 encrypted_database。当我在手机上执行此操作时,这需要很长时间。
我的想法是:用java编写一个加密数据库的应用程序,并在你的应用程序中使用这个 encrypted_database。结果是我只需要在我的应用程序中打开已经存在的 encrypted_database 并且不需要复制。
现在我写了一个 Java 应用程序(基于2 , 3)但是仍然有一些与 SQLCipher 及其设计相关的问题(4):
- 如何在数据库页面中划分我的数据库?在4中,数据库页面仅由其大小(1024 字节)定义。但是我必须在我的 encrypted_database 文件中写入“数据库页面开始”或“数据库页面结束”
盐和随机初始化向量 (iv) 是 1024 字节的一部分吗?
public static void main(String[] args) throws Exception{ outFile_enc = new FileOutputStream(mFileNameEncrypted); outFile_dec = new FileOutputStream(mFileNameDecrypted); int keyLength = 256; // salt salt = new byte[16]; Random rnd = new Random(); rnd.nextBytes(salt); int iterations = 4000; SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec keySpec = new PBEKeySpec(mPassWord.toCharArray(), salt, iterations, keyLength); SecretKey passwordKey = keyFactory.generateSecret(keySpec); key = new SecretKeySpec(passwordKey.getEncoded(), "AES"); // creates a cipher and init it for encryption Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); AlgorithmParameters params = cipher.getParameters(); iv = params.getParameterSpec(IvParameterSpec.class).getIV(); encryptData(cipher); } public static void encryptData(Cipher cipher) throws Exception{ // File to encrypt inFile = new FileInputStream(mFileName); // unique random salt in the first 16 bytes of the file outFile_enc.write(salt); // Read file and encrypt its bytes byte[] input = new byte[64]; int bytesRead; while((bytesRead = inFile.read(input)) != -1){ byte[] output = cipher.update(input, 0, bytesRead); if(output != null) outFile_enc.write(output); } byte[] output = cipher.doFinal(); if(output != null) outFile_enc.write(output); // random initialization vector is stored at the end of a page outFile_enc.write(iv); inFile.close(); outFile_enc.flush(); outFile_enc.close(); }
我感谢每一个帮助/想法/评论:)