2012-02-28 155 views
2

在我的應用程序中,我想通過加密來存儲一些安全數據。當用戶想要我通過解密將其展示給他時。 這工作正常。 但問題是我需要爲每條消息存儲加密消息和初始化向量。這個初始化向量是在加密時生成的,我必須在解密時使用它來獲取原始消息。如何在安卓初始化向量中使用AES-256加密和解密

因此,如果用戶存儲1000條消息,我需要存儲這1000條加密消息和相應的1000個初始化向量。我希望避免爲每條消息存儲初始化向量。

請告訴我通過AES初始化向量進行AES-256加密的方法。

下面是我的加密和解密

/* 
    * This method will do the AES-256 encryption. 
    */ 
    private byte[] encrypt(char[] raw, String cardno) { 
    // This raw is some unique key like password.  
     SecretKeyFactory factory = null; 
     SecretKey tmp = null; 
     Cipher cipher = null; 
     byte[] ciphertext = null; 
     AlgorithmParameters params = null; 
     try { 
      factory = SecretKeyFactory.getInstance("PBEWITHSHA-256AND256BITAES-CBC-BC"); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
     } 
     KeySpec spec = new PBEKeySpec(raw, mSalt, 1024, 256); 

     try { 
      if (factory != null) 
       tmp = factory.generateSecret(spec); 
     } catch (InvalidKeySpecException e) { 
      e.printStackTrace(); 
     } 
     if (tmp != null) 
      mSecret = new SecretKeySpec(tmp.getEncoded(), "AES"); 

     try { 
      cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      e.printStackTrace(); 
     } 
     try { 
      if (cipher != null) 
       cipher.init(Cipher.ENCRYPT_MODE, mSecret); 
     } catch (InvalidKeyException e) { 
      e.printStackTrace(); 
     } 
     if (cipher != null) 
      params = cipher.getParameters(); 
     try { 

      mIV = params.getParameterSpec(IvParameterSpec.class).getIV(); 

     } catch (InvalidParameterSpecException e) { 
      e.printStackTrace(); 
     } 
     try { 
      ciphertext = cipher.doFinal(cardno.getBytes("UTF-8")); 
     } catch (IllegalBlockSizeException e) { 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      e.printStackTrace(); 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } 
     return ciphertext; 

    } 





/* 
    * This will decrypt the encrypted data based on provided key 
    */ 
    private byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception { 
     //This raw is initialization vector generated while encrypting 
     Cipher cipher = null; 
     byte[] decrypted = null; 

     try { 
      cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      e.printStackTrace(); 
     } 
     try { 
      cipher.init(Cipher.DECRYPT_MODE, mSecret, new IvParameterSpec(raw)); 
     } catch (InvalidKeyException e) { 
      e.printStackTrace(); 
     } catch (InvalidAlgorithmParameterException e) { 
      e.printStackTrace(); 
     } 
     try { 
      decrypted = cipher.doFinal(encrypted); 
     } catch (IllegalBlockSizeException e) { 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      e.printStackTrace(); 
     } 


     return decrypted; 
    } 

回答

2

是安全的,你必須使用一個初始化向量(和唯一的)每個消息的代碼。沒有辦法繞過它。

+0

雖然可能與OP不相關,但確切地說,一個*可以*爲每個消息使用唯一的密鑰。在那種情況下,IV可以是空的而不會失去任何安全性,因爲隨機性的來源現在是關鍵本身。請參閱http://crypto.stackexchange.com/a/8601 – Raman 2014-01-07 22:36:34

+0

您可以請看看我的問題。我似乎無法使它工作。 http://stackoverflow.com/questions/34061675/convert-ios-encryption-to-android – MetaSnarf 2015-12-23 04:30:01

5

更好的方法是在保存的每條加密消息的開始處簡單添加初始化向量。由於填充已經可能會在消息中添加一些字節,所以這對於使用情況應該不重要。

不要忘了,IV對於特定的塊密碼總是有固定的大小:塊大小,可以使用Java中的cipher.getBlockSize()進行檢索。在取回IV後,您可以簡單地使用cipher.doFinal(buf, offset, length)而不是cipher.doFinal(buf)

如果你真的不想存儲IV,你可以從完整的路徑名(絕對路徑,或根據需要從一些根目錄)計算IV,並執行散列,如SHA-256它。只要路徑是唯一的,SHA-256應該相對接近已知但隨機的IV,這是最安全的。當然,如果您重命名/移動文件...

請注意,您要自己安全只有約初始化向量(1000×16,這是塊的大小)的16KB。這並不是很多。

+0

從我的答案,sankar缺少任何東西? – 2012-03-08 20:11:48

+0

你可以看看我的問題。我似乎無法使它工作。 http://stackoverflow.com/questions/34061675/convert-ios-encryption-to-android – MetaSnarf 2015-12-23 04:29:26