Получение исключения дополнения в javax.crypto - PullRequest
0 голосов
/ 08 июля 2011

Я пытаюсь закодировать тестовый класс crypto java, который шифрует и дешифрует пароль String с помощью BouncyCastle. main() очень прост, я делаю encryptPass(), а затем decryptPass() и наблюдаю за трассировкой консоли.

Проблема в том, что когда он пытается расшифровать, я получил исключение заполнения:

javax.crypto.BadPaddingException: pad block corrupted
    at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(Unknown Source)
    at javax.crypto.Cipher.doFinal(DashoA13*..)
    at com.kiengi.crypto.Crypto.decryptPass(Crypto.java:79)

Мой код следующий для класса Crypto:

// password to be crypted
public String pass = "password_go_here";

// key for encrypt pass
public String passKey = generateRandomKey(); // generation clef 16 caractere [a-zA-Z0-9]

// Encrypted pass
public String cryptedPass;

public final Logger logger = Logger.getLogger(this.getClass());

private final static byte[] IV_BYTES = new byte[] { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
        0x00, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };

public Crypto() {
    super();
}

public void encryptPass(){

    Security.addProvider(new BouncyCastleProvider());
    IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES);

    try{
        KeyGenerator _keygen = KeyGenerator.getInstance("AES");
        _keygen.init(new SecureRandom(passKey.getBytes()));
        SecretKey _key = _keygen.generateKey();
        logger.trace("Secret key generated");

        Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
        _cipher.init(Cipher.ENCRYPT_MODE, _key, _ivSpec);

        cryptedPass = asHex(_cipher.doFinal(pass.getBytes("UTF-8")));


        logger.trace("Encrypted pass : "+cryptedPass);


    }catch (Exception e) {
        logger.warn("encrypt failed");
        e.printStackTrace();
    }
}

public void decryptPass() {
    byte[] _passKey = passKey.getBytes();
    byte[] _cryptedPass = hexFromString(cryptedPass);

    Security.addProvider(new BouncyCastleProvider());   
    IvParameterSpec _ivSpec = new IvParameterSpec(IV_BYTES);

    try {           
        KeyGenerator _keygen = KeyGenerator.getInstance("AES");
        _keygen.init(new SecureRandom(_passKey));
        SecretKey _key = _keygen.generateKey();
        logger.trace("Secret key generated");

        Cipher _cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
        _cipher.init(Cipher.DECRYPT_MODE, _key, _ivSpec);

        String _pass = new String(_cipher.doFinal(_cryptedPass), "UTF-8");

        logger.trace("Decrypted pass : "+_pass);

    } catch (Exception e) {
        logger.warn("decrypt failed");
        e.printStackTrace();
    }

}

private int fromDigit(char ch) {
    if ((ch >= '0') && (ch <= '9')) {
        return ch - '0';
    } else if ((ch >= 'A') && (ch <= 'F')) {
        return ch + 10 - 'A';
    } else if ((ch >= 'a') && (ch <= 'f')) {
        return ch + 10 - 'a';
    } else {
        throw new IllegalArgumentException(String.format(
                "Invalid hex character 0x%04x", 0xff & ch));
    }
}

private byte[] hexFromString(String hex) {
    final byte[] buf = new byte[hex.length() / 2];
    for (int i = 0, j = 0; i < hex.length(); i += 2) {
        buf[j++] = (byte) (fromDigit(hex.charAt(i)) << 4 | fromDigit(hex
                .charAt(i + 1)));
    }
    return buf;
}

private static String asHex(byte buf[]) {
    final Formatter formatter = new Formatter(new StringBuffer());
    for (int i = 0; i < buf.length; i++) {
        formatter.format("%02x", 0xff & buf[i]);
    }
    return formatter.toString();
}

private String generateRandomKey() {
    String _chars = "abcdefABCDEF1234567890";
    StringBuffer _pass = new StringBuffer();
    for (int x = 0; x < 32; x++) {
        int i = (int) Math.floor(Math.random() * (_chars.length() - 1));
        _pass.append(_chars.charAt(i));
    }
    return _pass.toString();
}

Кто-нибудь знает, что означает это исключение?

Ответы [ 2 ]

0 голосов
/ 10 июля 2011

Это исключение означает, что блок заполнения поврежден. Вы используете заполнение PKCS # 7 с 16B блоками. В этом примере ваш вывод тоже 16B. Поэтому всегда следует добавлять блок с 16 байтами значения 0x10.
Заполнение повреждено из-за повреждения дешифрования. Ваша реализация SecureRandom добавляет собственную энтропию и генерирует неправильный ключ дешифрования. Этот конструктор SecureRandom использует первый алгоритм PRNG первого провайдера, который зарегистрировал реализацию SecureRandom.

0 голосов
/ 09 июля 2011

В этом коде есть ошибка. Предполагается, что new SecureRandom(passKey.getBytes()) инициализирует экземпляр SecureRandom только с байтами, предоставленными в конструкторе. Это не верно. Данные в конструкторе будут дополнять независимо от того, какие источники энтропии использует SecureRandom, не заменяет их.

Вам необходимо использовать правильную схему шифрования на основе пароля (PBE).

...