[英]How to encrypt and decrypt file in Android?
我想加密文件並將其存儲在 SD 卡中。 我想解密那個加密文件並再次將其存儲在 SD 卡中。 我試圖通過將文件作為文件流打開並加密來加密文件,但它不起作用。 我想知道如何做到這一點。
使用CipherOutputStream
或CipherInputStream
與Cipher
和您的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-crypto或Facebook 的 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.