为了保护应用程序存储的安全,我使用
EncryptedStorage
加密了存储,如此处所述。也就是说,
EncryptedStorage.install("your-pass-encryption-key")
我创建了一个文本文件,供另一台设备中的同一应用程序共享和打开/使用。
问题是该文件无法在其他设备中打开/使用。它说这个文件已加密。
如何解密它以便能够在另一设备的同一应用程序中打开或使用它?
编辑
我执行了以下操作来创建要共享的文件作为 .txt 文件,以便能够使用
plain/text
mime 类型来共享它。
String databasePath = Display.getInstance().getDatabasePath("TestDB.db");
String mimeType = "application/vnd.sqlite3";
mimeType = "application/x-sqlite3";
mimeType = "plain/text";
try {
FileSystemStorage fss = FileSystemStorage.getInstance();
InputStream is = fss.openInputStream(databasePath);
//Copy from FSS to Storage
Util.copy(is, Storage.getInstance().createOutputStream("TestDB.txt"));
String fileToSharePath = FileSystemStorage.getInstance().getAppHomePath() + "TestDB.txt";
Log.p("FileToSharePath " + fileToSharePath);
Display.getInstance().share(fileToSharePath, null, mimeType);
} catch (IOException e) {
Log.p("Share error: " + e);
}
我执行了以下操作,在另一台设备中使用
FileChooser
浏览共享文件,并将其另存为应用程序数据库目录中的 .db 文件。
FileChooser.showOpenDialog("txt", ev -> {
if (ev == null) {
Log.p("no file selected");
} else {
String filePath = (String) ev.getSource();
Log.p("FilePath " + filePath);
try {
FileSystemStorage fss = FileSystemStorage.getInstance();
InputStream is = fss.openInputStream(filePath);
String databasePath = Display.getInstance().getDatabasePath("TestDB.db");
OutputStream os = FileSystemStorage.getInstance().openOutputStream(databasePath);
Util.copy(is, os);
} catch (IOException e) {
Log.p("Create DB error: " + e);
}
}
});
您在这一行中使用
Storage
而不是 FileSystemStorage
:
Util.copy(is, Storage.getInstance().createOutputStream("TestDB.txt"));
这会加密文件,请注意,这无论如何都不能在设备上一致地工作...但是然后您再次使用
FileSystemStorage
来读取数据(已加密)。
String fileToSharePath = FileSystemStorage.getInstance().getAppHomePath() + "TestDB.txt";
解决方案是使用
FileSystemStorage
来分享您想要分享的所有内容。用这种方式加密数据库文件无论如何是行不通的。
以下内容将创建一个加密的
SampleText.txt
到应用程序存储,在文本编辑器中打开时无法读取。它只能由应用程序读取。
EncryptedStorage.install("your-pass-encryption-key")
private void writeAndReadCipherFile() {
try {
//write encrypted file to the app storage
try (Writer w = new OutputStreamWriter(Storage.getInstance().createOutputStream("SampleText.txt"))) {
w.write("Hey there big brother");
} catch (Exception e) {
Log.p("Error " + e);
}
//read encrypted file from the app storage
InputStream is = Storage.getInstance().createInputStream("SampleText.txt");
int nextChar = is.read();
StringBuilder sb = new StringBuilder();
while (nextChar > -1) {
sb.append((char) nextChar);
nextChar = is.read();
}
Log.p("FileContent " + sb.toString());
} catch (Exception e) {
Log.p("Error " + e);
}
}
以下使用
BouncyCastle
读取并加密数据库文件内容,并将加密后的数据库文件保存在应用程序主路径目录中home/.cn1
它还读取加密的文件内容,解密并将解密的文件保存在home/.cn1
中。
ISO-8859-1
中需要进行编码,以确保按预期读取文件字节中的所有字符。
OutputStreamWriter
编码也尝试,但一些十六进制被读为Windows-1252
。?
以下
private void encryptDatabaseFile() {
try {
String filePath = Display.getInstance().getDatabasePath("TestDB.db");
FileSystemStorage fss = FileSystemStorage.getInstance();
InputStream is = fss.openInputStream(filePath);
byte[] plainBytes = Util.readInputStream(is);
//encrypt database file content
byte[] cipherByteArray = FilesCipher.encryptFile(plainBytes);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cipherByteArray);
String encryptedFilePath = fss.getAppHomePath() + "EncryptedDB.db";
try (Writer w = new OutputStreamWriter(fss.openOutputStream(encryptedFilePath), "ISO-8859-1")) {//ISO-8859-1 Windows-1252 UTF-8
int nextChar = byteArrayInputStream.read();
while (nextChar > -1) {
char[] charArray = {(char) nextChar};
w.write(charArray);
nextChar = byteArrayInputStream.read();
}
} catch (Exception e) {
Log.p("Error " + e);
}
//decrypt database file content
InputStream decryptInputStream = fss.openInputStream(encryptedFilePath);
byte[] cipherBytes = Util.readInputStream(decryptInputStream);
byte[] plainByteArray = FilesCipher.decryptFile(cipherBytes);
ByteArrayInputStream decryptedInputStream = new ByteArrayInputStream(plainByteArray);
String decryptedFilePath = fss.getAppHomePath() + "DecryptedDB.db";
try (Writer w = new OutputStreamWriter(fss.openOutputStream(decryptedFilePath), "ISO-8859-1")) {//ISO-8859-1 Windows-1252 UTF-8
int nextChar = decryptedInputStream.read();
while (nextChar > -1) {
char[] charArray = {(char) nextChar};
w.write(charArray);
nextChar = decryptedInputStream.read();
}
} catch (Exception e) {
Log.p("Error " + e);
}
} catch (Exception e) {
Log.p("Error " + e);
}
}
类处理加密和解密
FilesCipher
这也使得数据库加密成为可能。也就是说,创建数据库后,可以使用
import com.codename1.io.Log;
import java.io.UnsupportedEncodingException;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.encoders.Base64;
public class FilesCipher {
private static PaddedBufferedBlockCipher cipher;
private static final String SECRET_KEY = "Your 16 Character Secret Key";
private static final String I_VECTOR = "Your 16 Character initialization vector";
public static byte[] encryptFile(byte[] plainBytes) {
byte[] byteArray = null;
try {
cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
byte sKey[] = SECRET_KEY.getBytes("UTF-8");
byte[] iv = I_VECTOR.getBytes("UTF-8");
KeyParameter keyParam = new KeyParameter(sKey);
CipherParameters ivAndKey = new ParametersWithIV(keyParam, iv);
cipher.init(true, ivAndKey);
byte[] cipherBytes = cipherData(plainBytes);
byteArray = Base64.encode(cipherBytes);
} catch (UnsupportedEncodingException | IllegalArgumentException
| CryptoException e) {
Log.p("Error " + e);
}
return byteArray;
}
public static byte[] decryptFile(byte[] cipherBytes) {
byte[] byteArray = null;
try {
cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
byte sKey[] = SECRET_KEY.getBytes("UTF-8");
byte[] iv = I_VECTOR.getBytes("UTF-8");
KeyParameter keyParam = new KeyParameter(sKey);
byte[] cipherData = Base64.decode(cipherBytes);
CipherParameters ivAndKey = new ParametersWithIV(keyParam, iv);
cipher.init(false, ivAndKey);
byteArray = cipherData(cipherData);
} catch (UnsupportedEncodingException | IllegalArgumentException
| CryptoException e) {
Log.p("Error " + e);
}
return byteArray;
}
private static byte[] cipherData(byte[] data) throws CryptoException {
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int len1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int len2 = cipher.doFinal(outBuf, len1);
int actualLen = len1 + len2;
byte[] result = new byte[actualLen];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
}
加密该数据库文件,然后将其另存为数据库。
在执行FilesCipher.encryptFile()
查询之前,使用
Create, Read, Update & Delete
解密数据库文件。执行查询后,使用 FilesCipher.decryptFile()
再次加密数据库