Алгоритм AES возвращает ненужные символы в середине моей строки данных - PullRequest
0 голосов
/ 07 ноября 2018

Я беру строку данных = "AkhilRanjanBiharabcdefghijklmnopMovedtoChennai18", сначала шифрую, а затем дешифрую. Строка, которую я получаю при расшифровке, - это «AkhilRanjanBiharÙ † + ™ ¸„ À – ýæó @ Movedtoñhennai18 », которая почти подходит для первых 16 и последних 16 символов, но 16 символов в середине - абсолютный мусор. Что может быть не так?

Мой код шифрования: -

public String encrypt(String value) {
    log.info("This method is not going to be used");
    String key = "theabcd@heymaths";
    initVector = "{{{{{{{{{{{{{{{{";
    String encryptedStr="";
    byte[] encrBytes =null;
    try {
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes());
        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        encrBytes = cipher.doFinal(value.getBytes());
        encryptedStr = new String(encrBytes);
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    String strToBeEncoded = encryptedStr +"::"+initVector;
    encrBytes = strToBeEncoded.getBytes();
    //String encoded = Base64.encodeBase64String(encrBytes);
    String encoded = Base64.getEncoder().encodeToString(encrBytes);
    String urlEncoded = null;
    try {
        urlEncoded = java.net.URLEncoder.encode(encoded, CHARSET);
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return urlEncoded;
}

Код расшифровки: -

public String decrypt(String encrypted) {
    String decryptedStr = null;
    byte[] base64Bytes = null;
    String urlDecoded = null;
    String key = HmCommonProperty.getProperty("abcd_crypt_key");
    if(key == null || key.isEmpty()) {
        key = securityKey;
    }
    String encryptionMech = HmCommonProperty.getProperty("abcd_crypt_algo");
    if(encryptionMech == null || encryptionMech.isEmpty()) {
        encryptionMech = CRYPT_MECHANISM;
    }
    try {
        //Url and Base64 decoding
        urlDecoded = java.net.URLDecoder.decode(encrypted, CHARSET);
        //base64Bytes = Base64.decodeBase64(urlDecoded);
        base64Bytes = Base64.getDecoder().decode(urlDecoded);
        //Generating IV
        String str = new String(base64Bytes);
        String[] bodyIVArr = str.split("::");
        initVector = bodyIVArr[1];
        String bodyStr = bodyIVArr[0];

        //AES Decryption
        Cipher cipher = Cipher.getInstance(encryptionMech);
        IvParameterSpec iv = new IvParameterSpec(initVector.getBytes());

        System.out.println("initVector Length ->  "
                +iv.getIV().length);
        System.out.println("input length ->  "
                +bodyStr.getBytes().length);

        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] decryptedBytes = cipher.doFinal(bodyStr.getBytes());
        decryptedStr =  new String(decryptedBytes);
    } catch (Exception ex) {
        ex.printStackTrace();
        log.error("Error occurred while decryption abcd data",ex);
    }

    return decryptedStr;
}

Ответы [ 2 ]

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

Ваши зашифрованные данные представляют собой последовательность байтов. Если вам нужно закодировать его как строку, вы должны использовать base64 или аналогичную кодировку, предназначенную для кодирования произвольных байтовых массивов. Притворение, что ваш произвольный байтовый массив является допустимой кодировкой строки, может вызвать проблемы, даже если вы используете ISO_8859_1.

Заменить

encryptedStr = new String(encrBytes)

с

encryptedStr = Base64.getEncoder().encodeToString(encrBytes)

и заменить

bodyStr.getBytes()

с

Base64.getDecoder().decode(bodyStr)

См. Также: Как правильно и последовательно получить байты из строки для шифрования AES?

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

Ваша ошибка лежит здесь:

encryptedStr = new String(encrBytes);
strToBeEncoded.getBytes();

В этих методах используется набор символов по умолчанию для платформы, и при преобразовании из byte[] в String и обратно в byte[] в общем случае с потерями . Единственный способ избежать потерь - это использовать набор символов по умолчанию для платформы "ISO_8859_1".

Я изменил все 11 таких вызовов на:

encryptedStr = new String(encrBytes, StandardCharsets.ISO_8859_1);
strToBeEncoded.getBytes(StandardCharsets.ISO_8859_1);

(я не изменился CHARSET). Вывод, который я получаю сейчас:

длина initVector -> 16
длина ввода -> 48
AkhilRanjanBiharabcdefghijklmnopMovedtoChennai18

Предупреждение о бонусе 1: в шифровании используется жестко закодированный "AES/CBC/NoPadding", но дешифрование является динамическим (оно, конечно, также должно использовать "AES/CBC/NoPadding").

Предупреждение о бонусе 2: Вероятность невелика, но вполне возможно, что "::" появится внутри encrBytes, что испортит ваш str.split("::");. Одним из решений является поиск последнего вхождения "::" и разбитого только на этом.

...