繁体   English   中英

如何在Android中加密和解密文件?

[英]How to encrypt and decrypt file in Android?

我想加密文件并将其存储在 SD 卡中。 我想解密那个加密文件并再次将其存储在 SD 卡中。 我试图通过将文件作为文件流打开并加密来加密文件,但它不起作用。 我想知道如何做到这一点。

使用CipherOutputStreamCipherInputStreamCipher和您的FileInputStream / FileOutputStream

我会建议像Cipher.getInstance("AES/CBC/PKCS5Padding")来创建Cipher类。 CBC 模式是安全的,没有ECB 模式对非随机明文漏洞 它应该存在于任何通用加密库中,以确保高兼容性。

如果您想使用相同的密钥加密多个文件,请不要忘记使用由安全随机生成器生成的初始化向量(IV)。 您可以在密文开头添加普通 IV 的前缀。 它的大小总是正好是一个块(16 字节)。

如果您想使用密码,请确保您确实使用了良好的密钥派生机制(查找基于密码的加密或基于密码的密钥派生)。 PBKDF2 是最常用的基于密码的密钥派生方案,它存在于大多数 Java 运行时中,包括 Android。 请注意,SHA-1 是一个有点过时的哈希函数,但它在 PBKDF2 中应该没问题,并且目前确实提供了最兼容的选项。

在编码/解码字符串时总是指定字符编码,否则当平台编码与之前的编码不同时你会遇到麻烦。 换句话说,不要使用String.getBytes()而是使用String.getBytes(StandardCharsets.UTF_8)

为了使其更安全,请通过在密文和 IV 上添加安全校验和(MAC 或 HMAC)来添加加密完整性和真实性,最好使用不同的密钥。 如果没有身份验证标签,密文可能会以无法检测到的方式更改。

请注意, CipherInputStream可能不会报告BadPaddingException ,这包括为经过身份验证的密码(例如 GCM)生成的BadPaddingException 这将使这些类型的经过身份验证的密码的流不兼容和不安全。

我有一个类似的问题,对于加密/解密,我想出了这个解决方案:

public static byte[] generateKey(String password) throws Exception
{
    byte[] keyStart = password.getBytes("UTF-8");

    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
    sr.setSeed(keyStart);
    kgen.init(128, sr);
    SecretKey skey = kgen.generateKey();
    return skey.getEncoded();
}

public static byte[] encodeFile(byte[] key, byte[] fileData) throws Exception
{

    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(fileData);

    return encrypted;
}

public static byte[] decodeFile(byte[] key, byte[] fileData) throws Exception
{
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);

    byte[] decrypted = cipher.doFinal(fileData);

    return decrypted;
}

要将加密文件保存到 sd,请执行以下操作:

File file = new File(Environment.getExternalStorageDirectory() + File.separator + "your_folder_on_sd", "file_name");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] yourKey = generateKey("password");
byte[] filesBytes = encodeFile(yourKey, yourByteArrayContainigDataToEncrypt);
bos.write(fileBytes);
bos.flush();
bos.close();

要解码文件,请使用:

byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);

为了将文件读入字节数组,有一种不同的方式。 一个例子: http : //examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/

您可以使用java-aes-cryptoFacebook 的 Conceal

java-aes-crypto

从回购报价

一个用于加密和解密字符串的简单 Android 类,旨在避免大多数此类类所遭受的经典错误。

脸书的隐藏

从回购报价

Conceal 提供简单的 Android API 来执行数据的快速加密和身份验证

将CipherOutputStream或CipherInputStream与Cipher和FileOutputStream / FileInputStream一起使用。

我们有一个相同的问题,它由我的问题线程中的某个人解决。 您应该看看:CipherInputStream和CipherOutputStream。 它们用于加密和解密字节流。 有关详细的源代码,请查看此链接中的Kiril答案: 如何在Android中使用AES从SD卡加密文件?

我有同样的问题,我从这段代码中得到了解决方案。

private static final String ALGO = "AES";
private static final byte[] keyValue = new byte[] { 'o', 'n', 'e', 'n','e', 't', 'e','d', 'o', 'c', 'e', 'i', 'r', 's', 'r', 'p' };
    public static String decrypt(String encryptedData){
        String decryptedValue = null;
        try{
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        decryptedValue = new String(decValue);
    }catch(Exception e){
        //LOGGER.error("In TD:" + e);
        //Teneno_StartupService.loadForConnectionFailed();
    }
    return decryptedValue;
}
private static Key generateKey(){
    Key key = new SecretKeySpec(keyValue, ALGO);
    return key;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM