2012-05-20 157 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 –