InvalidKeyException: длина ключа не 128/192/256 бит - PullRequest
4 голосов
/ 27 июля 2011

Я пытаюсь расшифровать зашифрованное изображение в 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 ]

4 голосов
/ 27 июля 2011

Как уже упоминал Алекс, шифрование на основе пароля - это то, что вам нужно.Ключи AES должны иметь длину 128, 192 или 256 бит.Таким образом, пароли произвольной длины не будут работать в вашей ситуации сразу, но использование «нормального» пароля правильного размера также неверно, потому что пароли такого типа не содержат достаточной энтропии и позволят злоумышленникам перебирать их больше.легко, потому что они не достаточно случайны.


С учетом вышесказанного, давайте посмотрим на вашу реализацию.Вместо того, чтобы принимать строку в качестве пароля в PHP, вам, вероятно, следует сгенерировать 16 байтов (128 бит) с классом Java «SecureRandom» или что-нибудь эквивалентное в PHP (не знаю, доступна ли такая вещь, помните, что это нужнобыть криптографически безопасным случайным числом).Закодируйте его с помощью Base64, чтобы получить строковое представление ключа, который будет использоваться как в Java, так и в PHP.

Сделайте то же самое для IV, длина которого равна 16 байтам (всегда соответствует размеру блока AES), снова закодируйте его в Base64.Вы делаете это не по той причине, что это должно быть секретно или сложно, а из-за проблем с кодированием, которые ваш подход почти наверняка вызовет.Насколько я знаю, кодировка PHP по умолчанию , а не UTF-8, поэтому ваш подход обречен на провал.

Используя эти два значения (Base64-декодировать их перед использованием!), Выготов перейти на сторону PHP.В Java получите ваш Cipher, используя

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

и инициализируйте его тем же IV и ключом, которые использовались в PHP (снова не забудьте сначала декодировать Base64).

Заключительное примечание: Я не рекомендую то, что я только что описал, потому что это означает, что ваши ключи будут жестко закодированы в ваши исходные файлы.Это на самом деле не совсем безопасно и обычно осуждается.Если вы хотите сделать симметричное шифрование с паролями, то вам следует использовать PBE и нигде не хранить пароли, по крайней мере, не в коде клиента.Другая возможность заключается в использовании асимметричной криптографии с открытым / закрытым ключом, например, с использованием обмена ключами Диффи-Хеллмана.

2 голосов
/ 27 июля 2011

Вы не можете использовать AES с какой-то парольной фразой по вашему выбору.Шифрование, когда вы используете свой собственный пароль, называется PBE (шифрование на основе пароля).Ключ AES должен быть сгенерирован изначально, чтобы соответствовать спецификациям алгоритма.Взгляните на эту статью .При необходимости вы можете применить PBE поверх ключа AES.

Учебник PBE можно найти здесь .

0 голосов
/ 14 июня 2013

Использовать только 16 символов в ключе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...