2012-05-20 261 views
1

我想加密/解密文件(大小合理)。我使用AES/CBC/PKCS5Padding更正了我的代碼。問題是加密大文件需要很長時間。所以現在我打算使用openSSL。android:使用openSSL的AES加密/解密

有沒有解釋如何從java應用程序使用openssl的鏈接?我如何將它集成到我的Java應用程序?

非常感謝在這方面的任何鏈接/點。 感謝您使用BC您的幫助和時間

我的代碼:

public class BouncyCastleProvider_AES_CBC { 
    public Cipher encryptcipher, decryptCipher; 
    String TAG = "DataEncryptDecrypt"; 
    private static final String RANDOM_ALGORITHM = "SHA1PRNG"; 

    // The default block size 
    public static int blockSize = 16; 


    // Buffer used to transport the bytes from one stream to another 
    byte[] buf = new byte[blockSize];  //input buffer 
    byte[] obuf = new byte[512];   //output buffer 

    // The key 
    byte[] key = null; 
    // The initialization vector needed by the CBC mode 
    byte[] IV = null; 

    public BouncyCastleProvider_AES_CBC(String passwd){ 
     //for a 192 key you must install the unrestricted policy files 
     // from the JCE/JDK downloads page 
     key =passwd.getBytes(); 
     key = "SECRETSECRET_1SE".getBytes(); 
     Log.i("SECRETSECRET_1SECRET_2", "length"+ key.length); 
     //default IV value initialized with 0 
     IV = new byte[blockSize]; 
     InitCiphers(); 

    } 

    public BouncyCastleProvider_AES_CBC(String pass, byte[] iv){ 
     //get the key and the IV 

     IV = new byte[blockSize]; 
     System.arraycopy(iv, 0 , IV, 0, iv.length); 
    } 
    public BouncyCastleProvider_AES_CBC(byte[] pass, byte[]iv){ 
     //get the key and the IV 
     key = new byte[pass.length]; 
     System.arraycopy(pass, 0 , key, 0, pass.length); 
     IV = new byte[blockSize]; 
     System.arraycopy(iv, 0 , IV, 0, iv.length); 
    } 

    public void InitCiphers() 
      { 
     try { 
     //1. create the cipher using Bouncy Castle Provider 
     encryptcipher = 
       Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); 
     //2. create the key 
     SecretKey keyValue = new SecretKeySpec(key,"AES"); 
     //3. create the IV 
     AlgorithmParameterSpec IVspec = new IvParameterSpec(IV); 
     //4. init the cipher 
     encryptcipher.init(Cipher.ENCRYPT_MODE, keyValue, IVspec); 
     encryptcipher.getOutputSize(100); 

     //1 create the cipher 
     decryptCipher = 
       Cipher.getInstance("AES/CBC/PKCS5Padding", "BC"); 
     //2. the key is already created 
     //3. the IV is already created 
     //4. init the cipher 
     decryptCipher.init(Cipher.DECRYPT_MODE, keyValue, IVspec); 
     } 
     catch(Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 




    public String encryptData(String inputFileName) { 
     String outFilename = null; 
     File inputFile = new File(inputFileName); 
     try { 

      // step 3 - not needed, as we have all the blocks on hand 

      // step 4 - call doFinal() 

      outFilename = ".".concat(CommonUtils.getHash(inputFile.getName())); 
      InputStream fis; 
      OutputStream fos; 
      fis = new BufferedInputStream(new FileInputStream(inputFileName)); 

      fos = new BufferedOutputStream(new FileOutputStream(
        inputFile.getParent() + "/" + outFilename)); 
      Log.i(TAG, "Output path:" + inputFile.getParent() + "/" + outFilename); 
      int bufferLength = (inputFile.length()>10000000?10000000:1000); 
      byte[] buffer = new byte[bufferLength]; 
      int noBytes = 0; 
      byte[] cipherBlock = new byte[encryptcipher 
        .getOutputSize(buffer.length)]; 
      int cipherBytes; 
      while ((noBytes = fis.read(buffer)) != -1) { 
       cipherBytes = encryptcipher.update(buffer, 0, noBytes, 
         cipherBlock); 
       fos.write(cipherBlock, 0, cipherBytes); 
      } 
      // always call doFinal 
      cipherBytes = encryptcipher.doFinal(cipherBlock, 0); 
      fos.write(cipherBlock, 0, cipherBytes); 

      // close the files 
      fos.close(); 
      fis.close(); 
      Log.i("encrpty", "done"); 
      inputFile.delete(); 
     } 

     catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
     return inputFile.getParent() + "/" + outFilename; 
    } 

    public void decryptData(String inputFileName, String outputFileName) { 
     InputStream fis; 
     OutputStream fos; 
     try { 
      fis = new BufferedInputStream(new FileInputStream(
        inputFileName)); 
      fos = new BufferedOutputStream(new FileOutputStream(
        outputFileName)); 
      byte[] buffer = new byte[blockSize*100]; 
      int noBytes = 0; 
      byte[] cipherBlock = new byte[decryptCipher 
        .getOutputSize(buffer.length)]; 
      int cipherBytes; 
      while ((noBytes = fis.read(buffer)) != -1) { 
       cipherBytes = decryptCipher.update(buffer, 0, noBytes, 
         cipherBlock); 
       fos.write(cipherBlock, 0, cipherBytes); 
      } 
      // allways call doFinal 
      cipherBytes = decryptCipher.doFinal(cipherBlock, 0); 
      fos.write(cipherBlock, 0, cipherBytes); 

      // close the files 
      fos.close(); 
      fis.close(); 
      new File(inputFileName).delete(); 

      Log.i("decrypt", "done"); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 

    } 

    public byte[] generateSalt() { 
     byte[] salt = new byte[16]; 

     try { 
     SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM); 
     random.nextBytes(salt); 
     } 
     catch(Exception ex) { 
      ex.printStackTrace(); 
     } 
     return salt; 

    } 



} 
+0

你試過[BouncyCastle的(http://bouncycastle.org/)密碼庫? – JimmyB

回答

5

衛報項目已建立的文件爲Android。一旦構建完成,您需要編寫一個簡單的JNI包裝器,使用OpenSSL API(EVP等)進行加密/解密,然後從您的應用程序調用此包裝器。你需要在應用中包含openssl和你的JNI包裝,並在啓動時使用System.loadLibrary()加載它們。

https://github.com/guardianproject/openssl-android

此外:

  • 不直接產生一個字符串的密碼,請使用正確的派生算法。
  • 不使用固定的IV,特別是全零
+0

非常感謝您的回覆。我會照顧提到的兩點,我試圖讓算法準備好,然後更改這些部分。關於JNI包裝,你知道任何示例項目。我從來沒有與NDK合作或編寫JNI包裝。任何鏈接都會非常有幫助。你也可以確認這一點,我們可以使用像openSSL這樣的本地代碼更快地獲得大文件的性能嗎?你有其他建議嗎?非常感謝您的答覆。 – png

+2

那麼,NDK只是一種編譯原生(C/C++)代碼的方法,所以如果你對C感到滿意,你不應該有任何問題。至於JNI,你只需要兩個或三個方法(初始化,加密,解密),所以它應該是一個非常薄的包裝。至於實際的加密部分,大多數OpenSSL教程應該教你如何做到這一點。我不能保證它會更快,更快:)您可能需要在不同的設備上進行實驗和基準測試。鏈接:JNI書(帶示例代碼):http://java.sun.com/docs/books/jni/ NDK:http://developer.android.com/sdk/ndk/index.html –