web-dev-qa-db-fra.com

Comment chiffrer et déchiffrer un fichier sous Android?

Je veux chiffrer le fichier et le stocker sur une carte SD. Je veux décrypter ce fichier crypté et le stocker à nouveau dans la carte SD. J'ai essayé de chiffrer un fichier en l'ouvrant en tant que flux de fichiers et le chiffrer est, mais cela ne fonctionne pas. Je veux une idée sur la façon de faire cela.

64
Pratik

Utilisez un CipherOutputStream ou CipherInputStream avec un Cipher et votre FileInputStream / FileOutputStream .

Je suggérerais quelque chose comme Cipher.getInstance("AES/CBC/PKCS5Padding") pour créer la classe Cipher. Le mode CBC est sécurisé et ne comporte pas vulnérabilités du mode ECB pour les textes en clair non aléatoires . Il doit être présent dans toute bibliothèque cryptographique générique, garantissant une compatibilité élevée.

N'oubliez pas d'utiliser un vecteur d'initialisation (IV) généré par un générateur aléatoire sécurisé si vous souhaitez chiffrer plusieurs fichiers avec la même clé. Vous pouvez préfixer plain IV au début du texte chiffré. Il a toujours exactement une taille de bloc (16 octets).

Si vous souhaitez utiliser un mot de passe, veillez à utiliser un mécanisme de dérivation de clé efficace (recherchez un chiffrement basé sur mot de passe ou une dérivation de clé basée sur un mot de passe). PBKDF2 est le schéma de dérivation de clé basé sur mot de passe le plus utilisé et il est présent dans la plupart des Java runtimes , y compris Android. Notez que SHA-1 est une fonction de hachage un peu obsolète , mais cela devrait aller dans PBKDF2, et présente actuellement l’option la plus compatible.

Spécifiez toujours le codage de caractères lors du codage/décodage de chaînes, sinon vous aurez des problèmes lorsque le codage de la plate-forme diffère du précédent. En d'autres termes, n'utilisez pas String.getBytes() mais utilisez String.getBytes(StandardCharsets.UTF_8) .

Pour le rendre plus sécurisé, veuillez ajouter une intégrité et une authenticité cryptographiques en ajoutant une somme de contrôle sécurisée (MAC ou HMAC) sur le texte chiffré et IV, en utilisant de préférence une clé différente. Sans étiquette d'authentification, le texte chiffré peut être modifié de telle sorte que la modification ne puisse pas être détectée.

Soyez averti que CipherInputStream peut not report BadPaddingException, cela inclut BadPaddingException généré pour les chiffreurs authentifiés tels que GCM. Cela rendrait les flux incompatibles et non sécurisés pour ce type de chiffrement authentifié.

63
Maarten Bodewes

J'ai eu un problème similaire et pour chiffrer/déchiffrer, je suis venu avec cette 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;
}

Pour enregistrer un fichier crypté sur sd, procédez comme suit:

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();

Pour décoder un fichier, utilisez:

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

Pour lire dans un fichier sur un octet Array, il existe un moyen différent de le faire. Un exemple: http://examples.javacodegeeks.com/core-Java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/

50
ZeroTek

Vous pouvez utiliser Java-aes-crypto ou dissimulation de Facebook

Java-aes-crypto

Citant du repo

Une simple Android classe pour le cryptage et le décryptage de chaînes, visant à éviter les erreurs classiques dont souffrent la plupart de ces classes.

Facebook dissimule

Citant du repo

Dissimulation fournit des API simples Android pour effectuer un cryptage et une authentification rapides des données).

0
user158