2011-07-27 496 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个字符长度? –

相关问题