【问题标题】:image encryption with jetpack EncryptedFile security使用 jetpack EncryptedFile 安全性进行图像加密
【发布时间】:2021-01-27 11:05:46
【问题描述】:

谷歌介绍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(字符串)并使用该库但不起作用。

【问题讨论】:

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


    【解决方案1】:

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

    解决方案 1

    使用 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);
    }
    

    【讨论】:

    • Base64 编码数据之前加密通常没有意义。
    • @President James K. Polk。在这种情况下是必要的,因为 Bitmap.compress 方法将图像转换为 Jpeg 格式,而不是 base64。 jetpack 安全加密/解密无法处理。如果您尝试问题源,您将看到它在没有 base64 编码/解码的情况下失败。
    • 但是为什么呢?我可能遗漏了一些东西,但我在代码中看不到任何可以通过 base64 编码明文来修复的内容。
    • 看起来decryptFile()中的方法inputStream.read()(即EncryptedFile$EncryptedFileInputStream#read())为0xFF返回了一个0xFFFFFFFF(-1),这是为EOF保留的>。因此,通常会返回太短/损坏的明文(可以使用包含0xFF 的短明文轻松验证)。因此,Base64 编码是一种可能的(但不是有效的)解决方案,因为它消除了0xFF 值。另一种选择是不使用上述read() 重载,而是使用read(byte[] buffer),或者答案中的解决方案1。
    • @Topaco:如果属实,这似乎是一个巨大的错误。
    猜你喜欢
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 2012-11-30
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 2013-08-23
    相关资源
    最近更新 更多