InvalidKeyException:密钥长度不是128/192/256位

时间:2011-07-27 08:51:55

标签: android image exception encryption

我正在尝试使用以下代码解密Android中的加密图像:

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 = "1234567890123456".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 = "1234567890123456";
        $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);

3 个答案:

答案 0 :(得分:4)

正如Alex已经提到的,基于密码的加密是您的最佳选择。 AES密钥需要长度为128,192或256位。因此,任意长度的密码都不会立即在您的情况下工作,但使用正确大小的“普通”密码也是错误的,因为这些类型的密码不包含足够的熵,并且允许攻击者对他们进行暴力破解容易因为它们不够随意。


话虽如此,让我们来看看你的实现。您不应该在PHP中使用String作为密码,而应该使用Java的“SecureRandom”类或PHP中的任何等效项生成16字节(128位)(不知道这样的东西是否可用,请记住它需要是一个加密安全的随机数)。使用Base64对其进行编码,以便获得要在Java和PHP中使用的密钥的String表示形式。

对于长度恰好为16字节的IV(始终与AES块大小相同)执行相同操作,再次将其编码为Base64。这样做不是因为它必须是秘密或复杂的,而是因为您的方法几乎肯定会导致编码问题。据我所知,PHP的默认编码是而不是 UTF-8,所以你的方法注定要失败。

使用这两个值(在使用前对它们进行Base64解码!),您就可以继续使用PHP了。在Java中,使用

获取密码
Cipher c = Cipher.getInstance("AES/CBC/PKCS5PAdding");

并使用PHP中使用的相同IV和密钥对其进行初始化(再次记住首先使用Base64-decode)。

最后注意事项:我不推荐我刚才描述的内容,因为这意味着您的密钥将被硬编码到源文件中。这实际上并不是非常安全,而且通常不赞成。如果您想使用密码进行对称加密,那么您应该使用PBE而不是将密码存储在任何地方,至少不是在客户端代码中。另一种可能性涉及非对称公钥/私钥密码术,例如,使用Diffie-Hellman密钥交换。

答案 1 :(得分:2)

您不能将AES与您选择的一些密码短语一起使用。使用自己的密码时的加密称为PBE(基于密码的加密)。必须首先生成AES密钥以符合算法规范。看一下这个article。如果需要,您可以在AES密钥之上应用PBE。

可以找到PBE教程here

答案 2 :(得分:0)

在密钥

中仅使用16个字符长度