Шифрование Java Triple DES с двумя разными ключами

Я пытаюсь зашифровать данные, используя тройной DES с двумя разными ключами, поэтому, учитывая два ключа k1 и k2, криптотекст будет Ek1 (Dk2 (Ek1 (plaintext))), где E - шифрование, а D - дешифрование. Я пытаюсь смоделировать это, используя алгоритм DES из java. Вот код:

public static void main(String[] args) {

    SecretKey k1 = generateDESkey();
    SecretKey k2 = generateDESkey();

    String firstEncryption = desEncryption("plaintext", k1);
    String decryption = desDecryption(firstEncryption, k2);
    String secondEncryption = desEncryption(decryption, k1);

}

public static SecretKey generateDESkey() {
    KeyGenerator keyGen = null;
    try {
        keyGen = KeyGenerator.getInstance("DES");
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    }
    keyGen.init(56); // key length 56
    SecretKey secretKey = keyGen.generateKey();
    return secretKey;
}

public static String desEncryption(String strToEncrypt, SecretKey desKey) {
    try {
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, desKey);
        String encryptedString = Base64.encode(cipher.doFinal(strToEncrypt.getBytes()));
        return encryptedString;


    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalBlockSizeException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (BadPaddingException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

public static String desDecryption(String strToDecrypt, SecretKey desKey) {
    try {
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5PADDING");
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        String decryptedString = new String(cipher.doFinal(Base64.decode(strToDecrypt)));
        return decryptedString;


    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchPaddingException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (InvalidKeyException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalBlockSizeException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (BadPaddingException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    } catch (Base64DecodingException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

У меня есть эта ошибка: javax.crypto.BadPaddingException: данный последний блок не заполнен должным образом при попытке расшифровать в этой строке кода:

String decryptedString = new String(cipher.doFinal(Base64.decode(strToDecrypt)));

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


person Jones    schedule 26.10.2013    source источник


Ответы (3)


Почему бы просто не использовать включенный алгоритм DESede?

Измените все экземпляры кода DES на DESede и измените метод генерации ключей на такой:

public static SecretKey generateDESkey() {
    KeyGenerator keyGen = null;
    try {
        keyGen = KeyGenerator.getInstance("DESede");
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
    }
    keyGen.init(112); // key length 112 for two keys, 168 for three keys
    SecretKey secretKey = keyGen.generateKey();
    return secretKey;
}

Обратите внимание, как метод getInstance () теперь поставляется с DESede, а размер ключа увеличен до 112 (168 для трех ключей).

Измените свои экземпляры Cipher с:

Cipher.getInstance("DES/ECB/PKCS5Padding");

to

Cipher.getInstance("DESede/ECB/PKCS5Padding");

И вы настроены.

person initramfs    schedule 26.10.2013

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

person jtahlborn    schedule 26.10.2013
comment
но не используйте base64, как сейчас в коде. использовать байты. используйте base64 только в конце. - person andrew cooke; 27.10.2013
comment
@andrewcooke У меня та же проблема, я не хочу использовать DESede, мой проект заключается в реализации TripleDES с использованием DES, так что вы знаете, как решить эту проблему без использования DESede? - person Firas Al Mannaa; 05.04.2015

Просто хотел указать, что DES со 112-битным ключом на самом деле является двойным DES, а не тройным DES с 168-битным ключом (3 * 56). Двойной DES никогда не следует использовать из-за атаки "встреча посередине" ( MITM) https://en.wikipedia.org/wiki/Meet-in-the-middle_attack

Таким образом, одиночный DES (56 бит), двойной DES (112 бит) и тройной DES (168 бит) больше не должны использоваться, поскольку они не обеспечивают 128 бит безопасности.

person Daniel Gartmann    schedule 27.07.2020