2016-04-17 4 views
1

J'utilise un simple CipherInput/OutputStream pour essayer de crypter/décrypter des fichiers dans Android. Le problème que j'ai est qu'il semble corrompre les premiers octets du fichier mais pas le reste. Voici un exemple d'une sortie d'un simple fichier texte:CipherOutputStream en-têtes corrompus dans Android

Texte original:

"Test for Android cipher. The quick brown fox jumps over the lazy dog." 

fait un cycle par cryptage et décryptage:

@ÍØJ­b¢çc°ÌHOšpher. The quick brown fox jumps over the the lazy dog. 

Voici mon code:

public static SecretKey generateKey(Context c, char[] passphraseOrPin) throws NoSuchAlgorithmException, InvalidKeySpecException { 
    // Number of PBKDF2 hardening rounds to use. Larger values increase 
    // computation time. You should select a value that causes computation 
    // to take >100ms. 
    byte[] salt = Settings.Secure.getString(c.getContentResolver(), 
      Settings.Secure.ANDROID_ID).getBytes(); 

    final int iterations = 1000; 

    final int outputKeyLength = 128; 

    SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength); 
    SecretKey secretKey = secretKeyFactory.generateSecret(keySpec); 
    Log.d("HIDEMYPICS","Secret Key: " + toHex(secretKey.getEncoded())); 
    return secretKey; 
} 

public static boolean decryptFileFromUri(Context context, Uri file, String keyphrase) { 
    try { 
     File f = new File(getRealPathFromURI(context, file)); 
     FileInputStream fis = new FileInputStream(f); 

     File ef = new File(f.toString().replace(".epf", "")); 
     FileOutputStream fos = new FileOutputStream(ef); 

     Log.d("HIDEMYPICS","Decrypting: " + f.toString()); 

     SecretKey key = generateKey(context, keyphrase.toCharArray()); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, key); 
     // Wrap the output stream 
     CipherOutputStream cos = new CipherOutputStream(fos, cipher); 
     // Write bytes 
     int b; 
     byte[] d = new byte[8]; 
     while ((b = fis.read(d)) != -1) { 
      cos.write(d, 0, b); 
     } 
     // Flush and close streams. 
     cos.flush(); 
     cos.close(); 
     fis.close(); 

     Log.d("HIDEMYPICS","Decrypted to: " + ef.toString()); 
     return true; 
    } catch (IOException e){ 
     e.printStackTrace(); 
    } catch (NoSuchPaddingException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeySpecException e) { 
     e.printStackTrace(); 
    } 
    return false; 
} 

public static boolean encryptFileFromUri(Context context, Uri file, String keyphrase) { 
    try { 
     File f = new File(getRealPathFromURI(context, file)); 
     FileInputStream fis = new FileInputStream(f); 

     File ef = new File(f.toString() + ".epf"); 
     FileOutputStream fos = new FileOutputStream(ef); 

     Log.d("HIDEMYPICS","Encrypting: " + f.toString()); 

     SecretKey key = generateKey(context, keyphrase.toCharArray()); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, key); 
     // Wrap the output stream 
     CipherOutputStream cos = new CipherOutputStream(fos, cipher); 
     // Write bytes 
     int b; 
     byte[] d = new byte[8]; 
     while ((b = fis.read(d)) != -1) { 
      cos.write(d, 0, b); 
     } 
     // Flush and close streams. 
     cos.flush(); 
     cos.close(); 
     fis.close(); 
     Log.d("HIDEMYPICS","Encrypted to: " + ef.toString()); 
     return true; 
    } catch (IOException e){ 
     e.printStackTrace(); 
    } catch (NoSuchPaddingException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeySpecException e) { 
     e.printStackTrace(); 
    } 
    return false; 
} 

MISE À JOUR:

a été conseillé d'ajouter explicitement une IV aléatoire à la configuration de chiffrement et ajouté/modifié les lignes de code ci-dessous pour le faciliter:

SecureRandom r = new SecureRandom(); 
     byte[] ivBytes = new byte[16]; 
     r.nextBytes(ivBytes); 

     SecretKey key = generateKey(context, keyphrase.toCharArray()); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes)); 

se sont retrouvés avec le même résultat. Les premiers octets du fichier texte étaient toujours corrompus.

réponse finale:

Je ne sais pas ce que je faisais, mais par des suggestions ci-dessous j'avais essayé statique IV et il avait toujours montré le même comportement, mais je déplacé la déclaration et quelque chose est arrivé; probablement eu une faute de frappe quelque part. Le problème est maintenant résolu et voici le code de travail final. Merci à tous ceux qui ont aidé!

private static final byte[] ivBytes = {109,15,57,79,75,112,50,91,18,18,107,127,65,68,12,69}; 

public static SecretKey generateKey(Context c, char[] passphraseOrPin) throws NoSuchAlgorithmException, InvalidKeySpecException { 
    // Number of PBKDF2 hardening rounds to use. Larger values increase 
    // computation time. You should select a value that causes computation 
    // to take >100ms. 
    byte[] salt = Settings.Secure.getString(c.getContentResolver(), 
      Settings.Secure.ANDROID_ID).getBytes(); 

    final int iterations = 1000; 

    final int outputKeyLength = 128; 

    SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength); 
    SecretKey secretKey = secretKeyFactory.generateSecret(keySpec); 
    return secretKey; 
} 

public static boolean decryptFileFromUri(Context context, Uri file, String keyphrase) { 
    try { 
     File f = new File(getRealPathFromURI(context, file)); 
     FileInputStream fis = new FileInputStream(f); 

     File ef = new File(f.toString().replace(".epf", "")); 
     FileOutputStream fos = new FileOutputStream(ef); 

     SecretKey key = generateKey(context, keyphrase.toCharArray()); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

     cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivBytes)); 
     // Wrap the output stream 
     CipherInputStream cis = new CipherInputStream(fis, cipher); 
     // Write bytes 
     int b; 
     byte[] d = new byte[8]; 
     while ((b = cis.read(d)) != -1) { 
      fos.write(d, 0, b); 
      fos.flush(); 
     } 
     // Flush and close streams. 
     fos.close(); 
     cis.close(); 

     f.delete(); 
     return true; 
    } catch (IOException e){ 
     e.printStackTrace(); 
    } catch (NoSuchPaddingException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeySpecException e) { 
     e.printStackTrace(); 
    } catch (InvalidAlgorithmParameterException e) { 
     e.printStackTrace(); 
    } 
    return false; 
} 

public static boolean encryptFileFromUri(Context context, Uri file, String keyphrase) { 
    try { 
     File f = new File(getRealPathFromURI(context, file)); 
     FileInputStream fis = new FileInputStream(f); 

     File ef = new File(f.toString() + ".epf"); 
     FileOutputStream fos = new FileOutputStream(ef); 

     SecretKey key = generateKey(context, keyphrase.toCharArray()); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes)); 
     // Wrap the output stream 
     CipherOutputStream cos = new CipherOutputStream(fos, cipher); 
     // Write bytes 
     int b; 
     byte[] d = new byte[8]; 
     while ((b = fis.read(d)) != -1) { 
      cos.write(d, 0, b); 
      cos.flush(); 
     } 
     // Flush and close streams. 
     cos.close(); 
     fis.close(); 
     f.delete(); 
     return true; 
    } catch (IOException e){ 
     e.printStackTrace(); 
    } catch (NoSuchPaddingException e) { 
     e.printStackTrace(); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeySpecException e) { 
     e.printStackTrace(); 
    } catch (InvalidAlgorithmParameterException e) { 
     e.printStackTrace(); 
    } 
    return false; 
} 

Répondre

1

Définissez explicitement un IV aléatoire et incluez-le avec votre texte chiffré.

+0

Essayé cela, et malheureusement n'a pas fonctionné: /. Même résultat Les premiers octets du fichier sont corrompus. Ajout d'une mise à jour ci-dessus à ce sujet. – Nuvious

+0

C'est une phrase avec environ 11 mots, et vous réussissez toujours à lire seulement la première partie. L'IV doit être la même pendant le cryptage et le décryptage. –

+0

Je vais essayer d'obtenir un exemple de texte chiffré, mais il crypte le message entier d'avant en arrière; ce que vous voyez est le message déchiffré. J'ai également essayé d'utiliser un vice statique 128 bits IV l'installation aléatoire ci-dessus et toujours pas de joie. – Nuvious