android - 使用 Jetpack EncryptedFile 安全性进行图像加密

标签 android encryption cryptography android-jetpack android-jetpack-security

谷歌介绍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) 并使用了库但不起作用。

最佳答案

您有两种加密/解密位图的方法。

方案一

使用 EncryptedFile 提供的流。完全不需要使用 Base64 编码/解码。

加密:

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

  1. 在加密之前,将位图字节编码为base64。
  2. 解密后,从 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);
}

关于android - 使用 Jetpack EncryptedFile 安全性进行图像加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64329635/

相关文章:

java - 错误的 AES 加密

c++ - 此示例中指定的 128 位 AES key 是什么格式?

android - Android 设备中的 Cordova Http 请求问题

android - 在谷歌地图 v2 上绘制虚线而不是实线

c++ - .NET 2.0 + C++ 的加密算法/库

python - 解密单字节 XOR 编码文件

Android FrameLayout 和软键盘问题

android - 具有自定义布局的 AlertDialog

encryption - Windows 10 和 Linux 的 TPM 所有者密码和锁定密码

c# - .NET 加密问题