Como encriptar e descriptografar o arquivo no Android?
5 answers
Usar um CipherOutputStream
ou CipherInputStream
com um Cipher
e o seu FileInputStream
/ FileOutputStream
.
Cipher.getInstance("AES/CBC/PKCS5Padding")
para criar a classe Cipher
. O modo CBC é seguro e não tem as vulnerabilidades do modo BCE para os plantexts não aleatórios. Deve estar presente em qualquer biblioteca criptográfica genérica, garantindo alta compatibilidade.
Não se esqueça de usar um Vector de inicialização (IV) gerado por um secure Androide. Note que o SHA-1 é uma função de hash um pouco desatualizada, mas deve estar bem no PBKDF2, e atualmente apresenta a opção mais compatível.
Indique sempre a codificação de caracteres quando codificar/descodificar textos, ou terá problemas quando a codificação da plataforma for diferente da anterior. Por outras palavras, não utilize String.getBytes()
String.getBytes(Charset.forName("UTF-8"))
.
Aviso-te que CipherInputStream
maio not report BadPaddingException
, isto inclui BadPaddingException
gerado para Cifras autenticadas!
Tive um problema semelhante e para encriptar/descriptografar arranjei esta solução:
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;
}
Para gravar um ficheiro encriptado para o sd do:
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();
Para descodificar um ficheiro usar:
byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);
Para ler em um arquivo para uma matriz de bytes lá uma maneira diferente lá fora. Um Exemplo: http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/
Use um fluxo de cifras ou Cifras com uma cifra e o seu fluxo de Ficheiros / fluxo de Ficheiros.
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;
}