Java Blowfish расшифровывает не возвращая оригинальную строку - PullRequest
0 голосов
/ 12 марта 2012

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

Ниже представлен отдельный класс, демонстрирующий проблему. Я получаю следующий вывод:

'Aaaaaaa7' encrypted: 'r?—èLèdÓ,·Ã¸ÍÒ'*
'Aaaaaaa7' decrypted: 'ñü=€¼(T'*

Любая идея, что мне нужно сделать, чтобы гарантировать, что она всегда правильно расшифровывается.

(Использование jce.jar в JDK 1.6.0_26)

Спасибо

David

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class BlowfishTwoWayHashImpl {

    static {
        test();
    }

    public static void test() {
        String key = "wibble";

        String passwordToEnrypt = "Aaaaaaa7";

        String enc = BlowfishTwoWayHashImpl.encryptBlowfish(passwordToEnrypt, key);
        System.out.println("'" + passwordToEnrypt + "' encrypted: '" + enc + "'");

        String dec = BlowfishTwoWayHashImpl.decryptBlowfish(enc, key);
        System.out.println("'" + passwordToEnrypt + "' decrypted: '" + dec + "'");
    }


    private static final String CIPHER_NAME = "Blowfish";

    public static String encryptBlowfish(String toEncrypt, String key) {
        return processString(toEncrypt, key, Cipher.ENCRYPT_MODE);
    }

    public static String decryptBlowfish(String toDecrypt, String key) {
        return processString(toDecrypt, key, Cipher.DECRYPT_MODE);
    }

    private static String processString(String toEncrypt, String key, int encryptDecryptMode) {

        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), CIPHER_NAME);

        Cipher cipher;
        try {
            cipher = Cipher.getInstance(CIPHER_NAME);
            cipher.init(encryptDecryptMode, secretKeySpec);
            return new String(cipher.doFinal(toEncrypt.getBytes()));
        }
        catch (Exception e) {
            throw new RuntimeException(e.toString());
        }
    }

}

1 Ответ

4 голосов
/ 12 марта 2012

Не делай этого:

return new String(cipher.doFinal(toEncrypt.getBytes()));

Вы используете кодировку платформы по умолчанию повсюду в вашем коде. Не делай этого. Это потеряет данные.

Когда вы конвертируете подлинный текст в байты (например, при шифровании), используйте специальную кодировку - UTF-8 - хороший выбор. Используйте ту же кодировку для декодирования из «закодированного текста» в String.

Когда вы конвертируете произвольные двоичные данные в текст, используйте кодировку base64, например, через эту общедоступную библиотеку кодирования Base64 .

По сути, когда вы создаете новую строку с конструкторами String(byte[]) или String(byte[], String), вы говорите: «Это подлинные текстовые данные - пожалуйста, просто декодируйте их как строку». Когда данные фактически являются результатом шифрования, это , а не текстовые данные ... это произвольная группа байтов.

...