Случайное IllegalBlockSizeException при расшифровке - PullRequest
0 голосов
/ 05 ноября 2018

У меня проблемы с расшифровкой текста:

Мой бэкэнд часто выдает исключение IllegalBlockSizeException во время расшифровки:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

Когда я пытаюсь снова (1-3 раза), наконец, он может успешно расшифровать тот же текст и отправить ответ в FE.

Как я заметил, это обычно происходит, когда я пытаюсь расшифровать много (около 100) строк за короткое время (2 запроса поступают от FE, 15 записей запрашиваются из db / request, 2 зашифрованных поля / запись)

Мой сервер работает на Raspberry Pi B + с Raspbian. Проблема отсутствует на "нормальном" ПК.

Класс шифрования:

package bookmarks.common.encryption.base;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.net.util.Base64;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DefaultEncryptor {
    private static final int SIZE = 16;
    private static final String ALGORITHM = "AES";

    private static final Base64 BASE_64 = new Base64();

    private final Key key;
    private final Cipher cipher;

    public DefaultEncryptor(String password) {
        byte[] key = createKey(password);
        this.key = new SecretKeySpec(key, ALGORITHM);
        try {
            cipher = Cipher.getInstance(ALGORITHM);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            log.error("Error creating encryptor.", e);
            throw new RuntimeException(e);
        }
    }

    private byte[] createKey(String password) {
        if (password.length() < SIZE) {
            int missingLength = SIZE - password.length();
            StringBuilder passwordBuilder = new StringBuilder(password);
            for (int i = 0; i < missingLength; i++) {
                passwordBuilder.append(" ");
            }
            password = passwordBuilder.toString();
        }
        return password.substring(0, SIZE).getBytes(StandardCharsets.UTF_8);
    }

    public String encrypt(String text) {
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encrypted = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
            byte[] base64 = BASE_64.encode(encrypted);
            return new String(base64, StandardCharsets.UTF_8);
        } catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
            log.error("Error encryping value.", e);
            throw new RuntimeException(e);
        }

    }

    public String decrypt(String text) {
        try {
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] base64 = BASE_64.decode(text.getBytes(StandardCharsets.UTF_8));
            byte[] decrypted = cipher.doFinal(base64);
            return new String(decrypted, StandardCharsets.UTF_8);
        } catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
            log.error("Error decrypting value.", e);
            throw new RuntimeException(e);
        }
    }
}

Есть идеи, что может вызвать проблему?

1 Ответ

0 голосов
/ 06 ноября 2018

Использование только шифра AES без IV подразумевает использование AES/ECB/PKCS5Padding. Этот шифр и режим требуют, чтобы входные данные расшифровывались кратно размеру блока (128 бит)

  Input length must be multiple of 16 when decrypting with padded cipher

Шифр ​​жалуется, что ввод не кратен 16

Как я заметил, это обычно происходит, когда я пытаюсь расшифровать много (около 100) строк за короткое время

То, что пришло мне в голову (как прокомментировал Джеймс, это мое образованное предположение), объект шифрования не является потокобезопасным. С высокой уверенностью я бы сказал либо

  • входные данные передаются как незавершенные (вы можете записать длину входного байтового массива)
  • есть несколько потоков, повторно использующих один и тот же объект шифра
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...