Как сделать шифрование и дешифрование AES-256 без вектора инициализации в Android - PullRequest
2 голосов
/ 28 февраля 2012

В моем приложении я хочу сохранить некоторые защищенные данные, зашифровав их. Когда пользователь хочет, я должен показать его ему, расшифровав. Это работает нормально. Но проблема в том, что мне нужно хранить как зашифрованное сообщение, так и вектор инициализации для каждого сообщения. Этот вектор инициализации генерируется при шифровании, и я должен использовать его при расшифровке, чтобы получить исходное сообщение.

Таким образом, если пользователь хранит 1000 сообщений, мне нужно хранить эти 1000 зашифрованных сообщений и соответствующие 1000 векторов инициализации. Я хочу избежать сохранения вектора инициализации для каждого сообщения.

Пожалуйста, скажите мне путь к шифрованию AES-256 без вектора инициализации.

Ниже приведен мой код для шифрования и дешифрования

/*
     * This method will do the AES-256 encryption.
     */
    private byte[] encrypt(char[] raw, String cardno) {
     //  This raw is some unique key like password.      
        SecretKeyFactory factory = null;
        SecretKey tmp = null;
        Cipher cipher = null;
        byte[] ciphertext = null;
        AlgorithmParameters params = null;
        try {
            factory = SecretKeyFactory.getInstance("PBEWITHSHA-256AND256BITAES-CBC-BC");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        KeySpec spec = new PBEKeySpec(raw, mSalt, 1024, 256);

        try {
            if (factory != null)
                tmp = factory.generateSecret(spec);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        if (tmp != null)
            mSecret = new SecretKeySpec(tmp.getEncoded(), "AES");

        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        try {
            if (cipher != null)
                cipher.init(Cipher.ENCRYPT_MODE, mSecret);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        if (cipher != null)
            params = cipher.getParameters();
        try {

            mIV = params.getParameterSpec(IvParameterSpec.class).getIV();

        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        }
        try {
            ciphertext = cipher.doFinal(cardno.getBytes("UTF-8"));
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ciphertext;

    }





/*
     * This will decrypt the encrypted data based on provided key
     */
    private byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
        //This raw is initialization vector generated while encrypting 
        Cipher cipher = null;
        byte[] decrypted = null;

        try {
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        }
        try {
            cipher.init(Cipher.DECRYPT_MODE, mSecret, new IvParameterSpec(raw));
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
        try {
            decrypted = cipher.doFinal(encrypted);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }


        return decrypted;
    }

Ответы [ 2 ]

5 голосов
/ 28 февраля 2012

Лучший способ - просто добавить вектор инициализации в начале каждого зашифрованного сообщения, которое вы сохраняете.Поскольку заполнение уже может добавить несколько байтов к сообщению, это не должно иметь большого значения в случае использования.

Не забывайте, что IV всегда имеет фиксированный размер для конкретного блочного шифра: размер блока,который вы можете получить, используя cipher.getBlockSize() в Java.Вы можете просто использовать cipher.doFinal(buf, offset, length) вместо cipher.doFinal(buf) после получения IV.

Если вы действительно не хотите хранить IV, вы можете рассчитать IV по полному имени пути (абсолютный путь,или из какого-либо корня, если необходимо), и выполните над ним хеш, такой как SHA-256.Пока путь уникален, SHA-256 должен быть относительно близок к известному, но случайному IV, что является наиболее безопасным.Конечно, если вы переименуете / переместите файл ...

Обратите внимание, что вы пытаетесь обезопасить себя только от 16 КБ вектора инициализации (1000 x 16, что является размером блока).Это не много.

2 голосов
/ 28 февраля 2012

Чтобы быть в безопасности, вы должны использовать вектор инициализации (и уникальный) для каждого сообщения. Обойти это невозможно.

...