2011-07-27 491 views
4

我想使用此代碼在Android中解密的加密圖像:InvalidKeyException異常:密鑰長度不128/192/256位

public class SimpleCryptoActivity extends Activity { 
    private static final int IO_BUFFER_SIZE = 4 * 1024; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     try { 
      AssetManager am = this.getAssets(); 
      // get the encrypted image from assets folder 
      InputStream is = am.open("2000_1.jpg_encrypted"); 

      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      byte[] b = new byte[IO_BUFFER_SIZE]; 

      int read; 
      //convert inputstream to bytearrayoutputstream 
      while ((read = is.read(b)) != -1) { 
       baos.write(b, 0, read); 
      } 
      byte[] key = "MARTIN_123_MARTIN_123".getBytes("UTF-8"); 
      byte[] iv = "123456789".getBytes("UTF-8"); 

      long start = System.currentTimeMillis()/1000L; // start 
      byte[] decryptedData = decrypt(key, iv, b); 

      //END 
      long end = System.currentTimeMillis()/1000L; // end 
      Log.d("TEST","Time start "+ String.valueOf(start)); 
      Log.d("TEST","Time end "+ String.valueOf(end)); 

      //decoding bytearrayoutputstream to bitmap 
      Bitmap bitmap = 
       BitmapFactory.decodeByteArray(decryptedData, 
               0, 
               decryptedData.length);  

      int i = bitmap.getRowBytes() * bitmap.getHeight() ; 

      TextView txt = (TextView) findViewById(R.id.text); 
      txt.setText(String.valueOf(i)); 
      is.close(); // close the inputstream 
      baos.close(); // close the bytearrayoutputstream 
     } catch (Exception e) { 
      e.fillInStackTrace(); 
      Log.e("error","err",e); 
     } 
    } 

    //decrypt 
    private byte[] decrypt(byte[] raw, byte[] iv, byte[] encrypted) 
      throws Exception { 

     SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     IvParameterSpec ivspec = new IvParameterSpec(iv);   
     cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec); 
     byte[] decrypted = cipher.doFinal(encrypted); 

     return decrypted; 
    } 
} 

和例外是:

07-27 09:01:53.162: ERROR/error(3104): err 
07-27 09:01:53.162: ERROR/error(3104): java.security.InvalidKeyException: Key length not 128/192/256 bits. 
07-27 09:01:53.162: ERROR/error(3104):  at com.cryptooo.lol.SimpleCryptoActivity.onCreate(SimpleCryptoActivity.java:62) 
07-27 09:01:53.162: ERROR/error(3104):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
07-27 09:01:53.162: ERROR/error(3104):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459) 
07-27 09:01:53.162: ERROR/error(3104):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512) 
07-27 09:01:53.162: ERROR/error(3104):  at android.app.ActivityThread.access$2200(ActivityThread.java:119) 
07-27 09:01:53.162: ERROR/error(3104):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863) 
07-27 09:01:53.162: ERROR/error(3104):  at android.os.Handler.dispatchMessage(Handler.java:99) 
07-27 09:01:53.162: ERROR/error(3104):  at android.os.Looper.loop(Looper.java:123) 
07-27 09:01:53.162: ERROR/error(3104):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
07-27 09:01:53.162: ERROR/error(3104):  at java.lang.reflect.Method.invokeNative(Native Method) 
07-27 09:01:53.162: ERROR/error(3104):  at java.lang.reflect.Method.invoke(Method.java:521) 
07-27 09:01:53.162: ERROR/error(3104):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
07-27 09:01:53.162: ERROR/error(3104):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
07-27 09:01:53.162: ERROR/error(3104):  at dalvik.system.NativeStart.main(Native Method) 

任何建議如何解決這個問題?

PHP代碼:

$files = array(
     '007FRAMESUPERIOR.jpg', 
     '2000_1.jpg', 
     'APLICACIONdescargaliga.jpg', 
     'APPCOMMENTS.pdf', 
     'AUDIOVISUALFOTO02.jpg' 
     ); 
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); 
     $iv = "123456789"; 
     $key = "MARTIN_123_MARTIN_123"; 
foreach($files as $file) 
{ 
      $input_file = $folder . $file; 
$text = file_get_contents($input_file); 
      //$text = "Meet me at 11 o'clock behind the monument."; 
      echo strlen($text) . "\n"; 
function addpadding($string, $blocksize = 16){ 
    $len = strlen($string); 
    $pad = $blocksize - ($len % $blocksize); 
    $string .= str_repeat(chr($pad), $pad); 
    return $string; 
} 


$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, addpadding($text), MCRYPT_MODE_CBC, $iv); 
+0

的文檔只有16個字符長度'mcrypt_encrypt'說什麼會做短鍵,而不是什麼與超長的人一樣。我懷疑它只是截斷了它們。PHP代碼也有點缺陷,因爲它測量的是「MCRYPT_RIJNDAEL_256」的IV大小,但後來使用了「MCRYPT_RIJNDAEL_128」(在這種情況下它並不重要,因爲它們長度相同,但對於密碼套件) –

+0

這是我在PHP代碼sry中的錯誤。事實上,代碼不適用於應用程序。它僅用於測試AES加密/解密,以便在真實設備上加密/解密映像所需的時間。這就是爲什麼我需要完成這個。它讓我瘋狂兩天了,因爲我真的是Android編程和ecnryption /解密方法的新手。 – hardartcore

+0

@hardartcore你能更新你的固定代碼嗎? PHP和Java? –

回答

4

正如亞歷克斯已經提到的,基於密碼的加密是爲你走的路。 AES密鑰的長度必須是128位,192位或256位。因此,任意長度的密碼不會立即適用於您的情況,但使用正確大小的「正常」密碼也是錯誤的,因爲這些密碼不包含足夠的熵,並且會使攻擊者更加強悍地使用它們很容易,因爲它們不夠隨意。


就這樣說吧,讓我們來看看你的實現。不要在PHP中使用String作爲密碼,而應該使用Java的`SecureRandom'類或PHP中的任何等效內容生成16個字節(128位)(不知道這樣的事情是否可用,請記住它需要是一個密碼安全的隨機數)。使用Base64對其進行編碼,以便獲得在Java和PHP中使用的密鑰的字符串表示形式。

對於長度恰好爲16個字節(總是與AES塊大小相同)的IV,執行同樣的操作,將其再次編碼爲Base64。你這樣做並不是因爲它必須是祕密或複雜的,而是因爲你的方法幾乎肯定會導致編碼問題。據我所知PHP的默認編碼是而不是 UTF-8,所以你的方法註定要失敗。

使用這兩個值(Base64-在使用之前對它們進行解碼!),您已準備好進入PHP端。在Java中,使用

Cipher c = Cipher.getInstance("AES/CBC/PKCS5PAdding"); 

獲取您的密碼,並在PHP中使用相同的IV和密鑰初始化(再次記住Base64編碼解碼第一)。

最後說明:我不推薦我剛剛描述的內容,因爲這意味着您的密鑰將被硬編碼到您的源文件中。這實際上並不安全,並且通常不被接受。如果你想使用密碼進行對稱加密,那麼你應該使用PBE,而不是將密碼存儲在任何地方,至少不要在客戶端代碼中。另一種可能性是涉及不對稱公鑰/私鑰密碼,例如使用Diffie-Hellman密鑰交換。

+0

所以基本上如果我想使用AES加密/解密,我不能這樣做:byte [] keys =「MARTIN_123_MARTIN_123」.getBytes(「UTF-8」); ?我需要設置密鑰,正如你所說的128,192,256位。那麼,如何修改我的代碼以使用圖像的AES解密?任何想法 – hardartcore

+0

我添加了一個代碼示例。當然這種方法也適用於你也進行加密的情況。否則,您需要準確找出用於加密圖像的方法。 – emboss

+0

我知道圖像是如何加密的,我將用php代碼編輯問題 – hardartcore

2

你不能用你選擇一些密碼短語使用AES。使用自己的密碼時加密稱爲PBE(基於密碼的加密)。必須首先生成AES密鑰才能符合算法規格。看看這個article。如果需要,您可以在AES密鑰的頂部應用PBE。

PBE教程可以找到here

+0

其實我的第一個版本的代碼是這樣的:http://pastebin.com/Kd48f2bV我只需要找到一種方法使用以下密鑰解密圖像:MARTIN_123_MARTIN_123但是當我使用該代碼時,它會遇到一個例外情況:http://pastebin.com/QgLrGgtx – hardartcore

+0

因此,您使用推測的密碼爲您的隨機播種。它只會使隨機生成器生成特定的序列。但是在這個問題中,您只是將您的密鑰作爲AES密鑰的原始值發送。不工作。看看PBE,我認爲這就是你需要的:http://www.java2s.com/Tutorial/Java/0490__Security/PBEFileEncrypt.htm –

0

使用在關鍵

+0

怎麼樣?我們用了16個字符長度? –

相關問題