Je veux crypter le fichier et le stocker dans la carte SD. Je veux décrypter ce fichier crypté et le stocker dans la carte SD à nouveau. J'ai essayé de crypter le fichier en l'ouvrant comme un flux de fichier et crypter est mais cela ne fonctionne pas. Je veux une idée sur la façon de le faire.Comment crypter et décrypter un fichier sous Android?
Répondre
Utilisez un CipherOutputStream
ou CipherInputStream
avec un Cipher
et votre FileInputStream
/FileOutputStream
. Je voudrais suggérer quelque chose comme Cipher.getInstance("AES/CBC/PKCS5Padding")
pour créer la classe Cipher
Le mode CBC est sécurisé et n'a pas le vulnerabilities of ECB mode for non-random plaintexts. Il devrait être présent dans toute bibliothèque cryptographique générique, assurant une compatibilité élevée. N'oubliez pas d'utiliser un Initialization Vector (IV) généré par un secure random generator si vous souhaitez chiffrer plusieurs fichiers avec la même clé. Vous pouvez préfixer le IV simple au début du texte chiffré. C'est toujours exactement un bloc (16 octets) de taille. Si vous souhaitez utiliser un mot de passe, assurez-vous que vous utilisez un bon mécanisme de dérivation de clé (recherche de cryptage par mot de passe ou dérivation de clé par mot de passe). PBKDF2 est le schéma de dérivation de clé basé sur un mot de passe le plus couramment utilisé et il est present in most Java runtimes, y compris Android. Notez que SHA-1 est une fonction de hachage un peu obsolète, mais cela devrait être bon dans PBKDF2, et présente actuellement l'option la plus compatible.
Spécifiez toujours le codage de caractères lors du codage/décodage des chaînes, ou vous rencontrerez des problèmes lorsque le codage de la plateforme diffère du précédent. En d'autres termes, n'utilisez pas String.getBytes()
mais utilisez String.getBytes(Charset.forName("UTF-8"))
. Pour plus de sécurité, ajoutez l'intégrité cryptographique et l'authenticité en ajoutant une somme de contrôle sécurisée (MAC ou HMAC) sur le texte chiffré et IV, de préférence en utilisant une clé différente. Sans une étiquette d'authentification, le texte chiffré peut être modifié de telle sorte que la modification ne puisse pas être détectée.
averti que CipherInputStream
peutpas rapport BadPaddingException
, cela inclut BadPaddingException
généré pour chiffrements authentifiées!
Nous avons un même problème, et son résolu par quelqu'un dans mon fil de question. Vous devriez jeter un oeil à: CipherInputStream et CipherOutputStream. Ils sont utilisés pour crypter et décrypter les flux d'octets. pour la vérification détaillée du code source sur Kiril réponse dans ce lien: How to encrypt file from SD card using AES in Android?
@ user142173 pouvez-vous répondre comment résoudre votre problème le code dans votre lien ne fonctionne pas – Erum
Utilisez un CipherOutputStream ou CipherInputStream avec un Cipher et votre FileOutputStream/FileInputStream.
J'ai eu un problème similaire et pour Crypter/Décrypter 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é à SD faire:
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 une utilisation du fichier:
byte[] yourKey = generateKey("password");
byte[] decodedData = decodeFile(yourKey, bytesOfYourFile);
Pour lire un fichier dans un tableau d'octets, il existe un moyen différent. Un exemple: http://examples.javacodegeeks.com/core-java/io/fileinputstream/read-file-in-byte-array-with-fileinputstream/
J'ai essayé d'utiliser cette solution, mais si je crypte le fichier de l'appareil Android, je suis incapable de déchiffrer le fichier de mon ordinateur. Il semble que la clé générée n'est pas cohérente. Connaissez-vous une solution à cela? – minhaz1
J'ai déjà expérimenté quelque chose avec cette solution moi-même. Il semble que différents appareils, versions Android (et un ordinateur bien sûr) créent des clés différentes en raison de différentes versions de l'algorithme sous-jacent. Ma solution était d'ajouter le jeu de caractères et le fournisseur pour SecureRandom. Cela a résolu mes problèmes et devrait maintenant fonctionner sur tous les appareils. J'ai édité ma réponse. – ZeroTek
Plus de lecture sur 'SecureRandom' ne fonctionne pas entre différents dispositifs: http://stackoverflow.com/questions/13433529/android-4-2-broke-my-encrypt-decrypt-code-and-the-provided-solutions-dont -work – Piovezan
J'ai eu le même problème, j'ai obtenu la solution de ce 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;
}
Les réponses sur ce site ne devraient pas seulement consister en du code source, expliquez pourquoi c'est une bonne solution (-1 parce que ce n'est pas le cas, il utilise l'encodage ECB pour les débutants). –
+1 pour "Toujours spécifier le codage de caractères lorsque l'encodage/décodage des chaînes de" :) – iabhi
@abhy de Java 7, vous pouvez utiliser en avant la [ 'StandardCharsets'] (http://docs.oracle.com/ javase/7/docs/API/java/nio/charset/StandardCharsets.html) pour votre confort. De toute évidence, une importation statique de 'StandardCharsets' peut également être utile. –
Merci pour la mise à jour. J'apprécie beaucoup. – iabhi