2011-07-26 46 views
0

我是對的還是有錯?我仍然試圖實現的測試程序正在運行,沒有任何異常或錯誤。但它沒有做它必須做的事情,我找不到問題。用PHP mcrypt加密,用Android解密。這個解密是否正確?

下面是Android的代碼,試圖解密:

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(); 
       InputStream is = am.open("2000_1.jpg_encrypted"); // get the encrypted image from assets folder 

       ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
       byte[] b = new byte[IO_BUFFER_SIZE]; 
       int read; 
       while ((read = is.read(b)) != -1) { //convert inputstream to bytearrayoutputstream 
        baos.write(b, 0, read); 
       }       
       //START 
       long start = System.currentTimeMillis()/1000L; // start 

       //byte[] keyStart = "MARTIN_123_MARTIN_123".getBytes(); // specific key value 
       KeyGenerator kgen = KeyGenerator.getInstance("AES/CBC/PKCS5Padding"); //aes 
       SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
       //sr.setSeed(keyStart); 
       kgen.init(128, sr); 
       //SecretKey skey = kgen.generateKey(); 
       //byte[] key = skey.getEncoded();  

       byte[] key = "MARTIN_123_MARTIN_123".getBytes("UTF-8"); 
       byte[] iv = "123456789".getBytes("UTF-8"); 
       byte[] decryptedData = decrypt(key, iv, b); 


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

       Bitmap bitmap = BitmapFactory.decodeByteArray(decryptedData , 0, decryptedData .length); //decoding bytearrayoutputstream to bitmap 
       //String filepath = Environment.getExternalStorageDirectory()+"bitmap"; 
       FileOutputStream fos = new FileOutputStream("sdcard/DCIM/100ANDRO"); 
       fos.write(decryptedData); 
       fos.close(); 

       is.close(); // close the inputstream 
       baos.close(); // close the bytearrayoutputstream 
      } 
      catch(Exception e){ 
       e.fillInStackTrace(); 
      } 
     } 

     //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; 
    } 

這裏是PHP代碼加密:

$folder = $this->getConfiguration()->getAppRootDir() . '/temp_encryption_testing/'; 

$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 = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
     $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"; 
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv); 
      echo strlen($crypttext) . "\n"; 
      file_put_contents($input_file . '_encrypted', $crypttext); 
     } 

任何幫助將不勝感激:)

+0

我提出這個問題有點更容易找到。希望對你有好處。 –

回答

3

您正在嘗試用隨機生成的密鑰解密(將種子添加到SecureRandom僅補充隨機狀態)。這肯定會失敗。

如果"MARTIN_123_MARTIN_123".getBytes()是你的鑰匙(或者更確切地說:前16個字節的話),你應該通過直接到你解密 - 方法:

byte[] decryptedData = decrypt(keyStart,b); 

好的,從您的意見,我可以看到您使用PHP進行加密:使用AES-256/ECB/ZeroBytePadding的mcrypt(零密碼填充對mcrypt隱含)。

首先:ECB不是一種安全模式 - especially for images(雖然JPG可能不像BMP那麼糟糕)。如果您決定更改爲CBC,請記住您需要傳輸IV,f.x.通過將其預先加入到加密數據中。但是如果你想解密CBC,你需要在你的Cipher.getInstance()-call(你目前使用AES/CBC/PKCS5Padding)中註明它。

除非您知道數據的長度,否則零字節填充不是真正可移除的。因此,您必須傳輸該長度或在加密數據之前添加PKCS#7填充。

最後:你使用AES-256進行加密。這使用一個32字節的密鑰。根據mcrypt-documentation,如果密鑰太短,它會添加\ 0,所以您必須使用實際的32字節密鑰或將\ 0s添加到Android端。

你的代碼更改爲這對Android的一面:

byte[] key = "MARTIN_123456789".getBytes("UTF-8"); 
byte[] iv = "123456789".getBytes("UTF-8"); 
byte[] decryptedData = decrypt(key, iv, b); 

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; 
} 

而在PHP端:

function addpadding($string, $blocksize = 16){ 
    $len = strlen($string); 
    $pad = $blocksize - ($len % $blocksize); 
    $string .= str_repeat(chr($pad), $pad); 
    return $string; 
} 

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

我的鑰匙只是「MARTIN_123_MARTIN_123」。那麼我需要添加它嗎?你能幫我嗎? – Android

+0

@Android:小更新。如果這不起作用,請添加一些關於數據如何加密的信息。 –

+0

該文件使用PHP加密:http://pastebin.com/n2F1xm5q – Android