I want to encrypt file and store it in SD card. I want to decrypt that encrypted file and store it in SD card again. I have tried to encrypt file by opening as file stream and encrypt is but it is not working. I want some idea on how to do this.
我想加密文件并将其存储在SD卡中。我想解密该加密文件并再次将其存储在SD卡中。我试图通过打开文件流加密文件并加密,但它不起作用。我想知道如何做到这一点。
5 个解决方案
#1
54
Use a CipherOutputStream
or CipherInputStream
with a Cipher
and your FileInputStream
/ FileOutputStream
.
将CipherOutputStream或CipherInputStream与Cipher和FileInputStream / FileOutputStream一起使用。
I would suggest something like Cipher.getInstance("AES/CBC/PKCS5Padding")
for creating the Cipher
class. CBC mode is secure and does not have the vulnerabilities of ECB mode for non-random plaintexts. It should be present in any generic cryptographic library, ensuring high compatibility.
我建议使用Cipher.getInstance(“AES / CBC / PKCS5Padding”)来创建Cipher类。 CBC模式是安全的,并且没有针对非随机明文的ECB模式的漏洞。它应该存在于任何通用加密库中,以确保高兼容性。
Don't forget to use a Initialization Vector (IV) generated by a secure random generator if you want to encrypt multiple files with the same key. You can prefix the plain IV at the start of the ciphertext. It is always exactly one block (16 bytes) in size.
如果要使用相同的密钥加密多个文件,请不要忘记使用由安全随机生成器生成的初始化向量(IV)。您可以在密文的开头加上普通IV的前缀。它总是正好一个块(16字节)。
If you want to use a password, please make sure you do use a good key derivation mechanism (look up password based encryption or password based key derivation). PBKDF2 is the most commonly used Password Based Key Derivation scheme and it is present in most Java runtimes, including Android. Note that SHA-1 is a bit outdated hash function, but it should be fine in PBKDF2, and does currently present the most compatible option.
如果要使用密码,请确保使用良好的密钥派生机制(查找基于密码的加密或基于密码的密钥派生)。 PBKDF2是最常用的基于密码的密钥派生方案,它存在于大多数Java运行时,包括Android。请注意,SHA-1是一个有点过时的哈希函数,但它在PBKDF2中应该没问题,并且目前提供最兼容的选项。
Always specify the character encoding when encoding/decoding strings, or you'll be in trouble when the platform encoding differs from the previous one. In other words, don't use String.getBytes()
but use String.getBytes(Charset.forName("UTF-8"))
.
在编码/解码字符串时始终指定字符编码,否则当平台编码与前一个编码不同时,您将遇到麻烦。换句话说,不要使用String.getBytes(),而是使用String.getBytes(Charset.forName(“UTF-8”))。
To make it more secure, please add cryptographic integrity and authenticity by adding a secure checksum (MAC or HMAC) over the ciphertext and IV, preferably using a different key. Without an authentication tag the ciphertext may be changed in such a way that the change cannot be detected.
为了使其更安全,请通过在密文和IV上添加安全校验和(MAC或HMAC)来添加加密完整性和真实性,最好使用不同的密钥。在没有认证标签的情况下,可以以不能检测到改变的方式改变密文。
Be warned that CipherInputStream
may not report BadPaddingException
, this includes BadPaddingException
generated for authenticated ciphers!
请注意,CipherInputStream可能不会报告BadPaddingException,这包括为经过身份验证的密码生成的BadPaddingException!
#2
42
I had a similar problem and for encrypt/decrypt i came up with this solution:
我有一个类似的问题,加密/解密我提出了这个解决方案:
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;
}
To save a encrypted file to sd do:
要将加密文件保存到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();
To decode a file use:
要解码文件,请使用:
byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);
For reading in a file to a byte Array there a different way out there. A Example: http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/
为了将文件读入字节数组,有不同的方法。例如:http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/
#3
-4
Use a CipherOutputStream or CipherInputStream with a Cipher and your FileOutputStream / FileInputStream.
将CipherOutputStream或CipherInputStream与Cipher和FileOutputStream / FileInputStream一起使用。
#4
-5
We have a same problem, and its solved by someone in my question thread. You should just take a look at: CipherInputStream and CipherOutputStream. They are used to encrypt and decrypt byte streams. for the detailed source code check out Kiril answer in this link : How to encrypt file from SD card using AES in Android?
我们遇到了同样的问题,并且我的问题线程中的某个人解决了它。您应该看看:CipherInputStream和CipherOutputStream。它们用于加密和解密字节流。详细源代码查看Kiril在此链接中的答案:如何在Android中使用AES加密SD卡中的文件?
#5
-5
I had the same problem, i got the solution from this code.
我遇到了同样的问题,我从这段代码中得到了解决方案。
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;
}
#1
54
Use a CipherOutputStream
or CipherInputStream
with a Cipher
and your FileInputStream
/ FileOutputStream
.
将CipherOutputStream或CipherInputStream与Cipher和FileInputStream / FileOutputStream一起使用。
I would suggest something like Cipher.getInstance("AES/CBC/PKCS5Padding")
for creating the Cipher
class. CBC mode is secure and does not have the vulnerabilities of ECB mode for non-random plaintexts. It should be present in any generic cryptographic library, ensuring high compatibility.
我建议使用Cipher.getInstance(“AES / CBC / PKCS5Padding”)来创建Cipher类。 CBC模式是安全的,并且没有针对非随机明文的ECB模式的漏洞。它应该存在于任何通用加密库中,以确保高兼容性。
Don't forget to use a Initialization Vector (IV) generated by a secure random generator if you want to encrypt multiple files with the same key. You can prefix the plain IV at the start of the ciphertext. It is always exactly one block (16 bytes) in size.
如果要使用相同的密钥加密多个文件,请不要忘记使用由安全随机生成器生成的初始化向量(IV)。您可以在密文的开头加上普通IV的前缀。它总是正好一个块(16字节)。
If you want to use a password, please make sure you do use a good key derivation mechanism (look up password based encryption or password based key derivation). PBKDF2 is the most commonly used Password Based Key Derivation scheme and it is present in most Java runtimes, including Android. Note that SHA-1 is a bit outdated hash function, but it should be fine in PBKDF2, and does currently present the most compatible option.
如果要使用密码,请确保使用良好的密钥派生机制(查找基于密码的加密或基于密码的密钥派生)。 PBKDF2是最常用的基于密码的密钥派生方案,它存在于大多数Java运行时,包括Android。请注意,SHA-1是一个有点过时的哈希函数,但它在PBKDF2中应该没问题,并且目前提供最兼容的选项。
Always specify the character encoding when encoding/decoding strings, or you'll be in trouble when the platform encoding differs from the previous one. In other words, don't use String.getBytes()
but use String.getBytes(Charset.forName("UTF-8"))
.
在编码/解码字符串时始终指定字符编码,否则当平台编码与前一个编码不同时,您将遇到麻烦。换句话说,不要使用String.getBytes(),而是使用String.getBytes(Charset.forName(“UTF-8”))。
To make it more secure, please add cryptographic integrity and authenticity by adding a secure checksum (MAC or HMAC) over the ciphertext and IV, preferably using a different key. Without an authentication tag the ciphertext may be changed in such a way that the change cannot be detected.
为了使其更安全,请通过在密文和IV上添加安全校验和(MAC或HMAC)来添加加密完整性和真实性,最好使用不同的密钥。在没有认证标签的情况下,可以以不能检测到改变的方式改变密文。
Be warned that CipherInputStream
may not report BadPaddingException
, this includes BadPaddingException
generated for authenticated ciphers!
请注意,CipherInputStream可能不会报告BadPaddingException,这包括为经过身份验证的密码生成的BadPaddingException!
#2
42
I had a similar problem and for encrypt/decrypt i came up with this solution:
我有一个类似的问题,加密/解密我提出了这个解决方案:
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;
}
To save a encrypted file to sd do:
要将加密文件保存到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();
To decode a file use:
要解码文件,请使用:
byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);
For reading in a file to a byte Array there a different way out there. A Example: http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/
为了将文件读入字节数组,有不同的方法。例如:http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/
#3
-4
Use a CipherOutputStream or CipherInputStream with a Cipher and your FileOutputStream / FileInputStream.
将CipherOutputStream或CipherInputStream与Cipher和FileOutputStream / FileInputStream一起使用。
#4
-5
We have a same problem, and its solved by someone in my question thread. You should just take a look at: CipherInputStream and CipherOutputStream. They are used to encrypt and decrypt byte streams. for the detailed source code check out Kiril answer in this link : How to encrypt file from SD card using AES in Android?
我们遇到了同样的问题,并且我的问题线程中的某个人解决了它。您应该看看:CipherInputStream和CipherOutputStream。它们用于加密和解密字节流。详细源代码查看Kiril在此链接中的答案:如何在Android中使用AES加密SD卡中的文件?
#5
-5
I had the same problem, i got the solution from this code.
我遇到了同样的问题,我从这段代码中得到了解决方案。
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;
}