使用 Jetpack EncryptedFile 安全性进行图像加密
image encryption with jetpack EncryptedFile security
google介绍security-crypto jetpack library
我想用这个库加密图片文件,在库的文档中没有加密图片文件的示例。
我将图像转换为位图 - 位图到字节数组 - 然后使用库 如文档中所述
finaly文件是加密的,但是文件解码的时候出现黑图
我没有得到任何异常问题出在哪里?
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView =findViewById(R.id.image);
// get image from asset and convert to bitmap
Bitmap bitmap = getBitmapFromAsset(this,"temp.jpg");
byte[] bytesOfBitmap= BitmapToByteArray(bitmap);
// encrypt
File pathForSaveEncryptedFile=new File(getFilesDir().getAbsolutePath() + File.separator+"encrypted.me");
try {
encryptToFile(this,pathForSaveEncryptedFile,bytesOfBitmap);
} catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
}
// decrypt and show to image view
try {
byte[] decryptedFile = decryptFile(this,pathForSaveEncryptedFile);
imageView.setImageBitmap(ByteArrayToBitmap(decryptedFile));
} catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
}
}
private void encryptToFile(Context context,File pathToSave,byte[] contents) throws GeneralSecurityException, IOException {
MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
EncryptedFile encryptedFile = new EncryptedFile.Builder(context,
pathToSave,
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();
OutputStream outputStream = encryptedFile.openFileOutput();
outputStream.write(contents);
outputStream.flush();
outputStream.close();
}
private byte[] decryptFile(Context context ,File target) throws GeneralSecurityException, IOException {
MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
EncryptedFile encryptedFile = new EncryptedFile.Builder(context,
target,
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();
InputStream inputStream = encryptedFile.openFileInput();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int nextByte = inputStream.read();
while (nextByte != -1) {
byteArrayOutputStream.write(nextByte);
nextByte = inputStream.read();
}
return byteArrayOutputStream.toByteArray();
}
private byte[] BitmapToByteArray(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
private Bitmap ByteArrayToBitmap(byte[] bytes){
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
private Bitmap getBitmapFromAsset(Context context, String fileName) {
AssetManager assetManager = context.getAssets();
InputStream istr;
Bitmap bitmap = null;
try {
istr = assetManager.open(fileName);
bitmap = BitmapFactory.decodeStream(istr);
} catch (IOException e) {
// handle exception
}
return bitmap;
}
}
我也将图像转换为 base64(String) 并使用了该库但不起作用。
您有两种加密/解密位图的方法。
解决方案 1
使用 EncryptedFile 提供的流。根本不需要使用 Base64 encoding/decoding。
加密:
private void encrypt(final Context context, final File target, final Bitmap bitmap) throws GeneralSecurityException, IOException {
final MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
final EncryptedFile file = new EncryptedFile.Builder(context,
target, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB)
.build();
final OutputStream stream = file.openFileOutput();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
stream.flush();
stream.close();
}
解密:
private Bitmap decrypt(final Context context, final File target) throws GeneralSecurityException, IOException {
final MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
final EncryptedFile file = new EncryptedFile.Builder(context,
target, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB)
.build();
final InputStream stream = file.openFileInput();
return BitmapFactory.decodeStream(stream);
}
解决方案 2
- 加密前,将位图字节编码为base64。
- 解密后,从 base64 解码,然后再转换回位图。
对于您的特定代码示例,请执行以下操作:
private byte[] bitmapToByteArray(final Bitmap bitmap) {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
final String data = Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT);
return data.getBytes();
}
private Bitmap byteArrayToBitmap(final byte[] bytes) {
final byte[] data = Base64.decode(bytes, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(data, 0, data.length);
}
google介绍security-crypto jetpack library
我想用这个库加密图片文件,在库的文档中没有加密图片文件的示例。
我将图像转换为位图 - 位图到字节数组 - 然后使用库 如文档中所述 finaly文件是加密的,但是文件解码的时候出现黑图 我没有得到任何异常问题出在哪里?
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView =findViewById(R.id.image);
// get image from asset and convert to bitmap
Bitmap bitmap = getBitmapFromAsset(this,"temp.jpg");
byte[] bytesOfBitmap= BitmapToByteArray(bitmap);
// encrypt
File pathForSaveEncryptedFile=new File(getFilesDir().getAbsolutePath() + File.separator+"encrypted.me");
try {
encryptToFile(this,pathForSaveEncryptedFile,bytesOfBitmap);
} catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
}
// decrypt and show to image view
try {
byte[] decryptedFile = decryptFile(this,pathForSaveEncryptedFile);
imageView.setImageBitmap(ByteArrayToBitmap(decryptedFile));
} catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
}
}
private void encryptToFile(Context context,File pathToSave,byte[] contents) throws GeneralSecurityException, IOException {
MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
EncryptedFile encryptedFile = new EncryptedFile.Builder(context,
pathToSave,
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();
OutputStream outputStream = encryptedFile.openFileOutput();
outputStream.write(contents);
outputStream.flush();
outputStream.close();
}
private byte[] decryptFile(Context context ,File target) throws GeneralSecurityException, IOException {
MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
EncryptedFile encryptedFile = new EncryptedFile.Builder(context,
target,
mainKey,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();
InputStream inputStream = encryptedFile.openFileInput();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int nextByte = inputStream.read();
while (nextByte != -1) {
byteArrayOutputStream.write(nextByte);
nextByte = inputStream.read();
}
return byteArrayOutputStream.toByteArray();
}
private byte[] BitmapToByteArray(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
private Bitmap ByteArrayToBitmap(byte[] bytes){
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
private Bitmap getBitmapFromAsset(Context context, String fileName) {
AssetManager assetManager = context.getAssets();
InputStream istr;
Bitmap bitmap = null;
try {
istr = assetManager.open(fileName);
bitmap = BitmapFactory.decodeStream(istr);
} catch (IOException e) {
// handle exception
}
return bitmap;
}
}
我也将图像转换为 base64(String) 并使用了该库但不起作用。
您有两种加密/解密位图的方法。
解决方案 1
使用 EncryptedFile 提供的流。根本不需要使用 Base64 encoding/decoding。
加密:
private void encrypt(final Context context, final File target, final Bitmap bitmap) throws GeneralSecurityException, IOException {
final MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
final EncryptedFile file = new EncryptedFile.Builder(context,
target, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB)
.build();
final OutputStream stream = file.openFileOutput();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
stream.flush();
stream.close();
}
解密:
private Bitmap decrypt(final Context context, final File target) throws GeneralSecurityException, IOException {
final MasterKey mainKey = new MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
final EncryptedFile file = new EncryptedFile.Builder(context,
target, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB)
.build();
final InputStream stream = file.openFileInput();
return BitmapFactory.decodeStream(stream);
}
解决方案 2
- 加密前,将位图字节编码为base64。
- 解密后,从 base64 解码,然后再转换回位图。
对于您的特定代码示例,请执行以下操作:
private byte[] bitmapToByteArray(final Bitmap bitmap) {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
final String data = Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT);
return data.getBytes();
}
private Bitmap byteArrayToBitmap(final byte[] bytes) {
final byte[] data = Base64.decode(bytes, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(data, 0, data.length);
}