Расшифруйте данные с помощью 3DES-128-битного режима CBC (с нулевым заполнением), используя Java

В процессе расшифровки зашифрованных данных у меня возникла небольшая проблема с этим. Я буду очень рад, если кто-нибудь сможет помочь мне.

Несмотря на то, что я уже изучил алгоритм при выполнении этой операции, так как я должен получить свои данные от устройства, у которого уже есть свой Базовый ключ деривации (BDK), первоначально загруженный серийный номер ключа и первоначально загруженный ключ устройства ввода пин-кода.

В предоставленной документации у нас есть серийный номер изначально загруженного ключа, вариант ключа шифрования данных и дорожка 2 "Данные" (которая находится в незашифрованном виде).

В этом примере я узнал, что они на самом деле использовали метод CBC Mode в 3DES-128 битах (с нулевым заполнением).

мой вопрос теперь, как открытый текст был получен из зашифрованных данных. Я буду очень рад, если кто-нибудь сможет мне помочь (с указанием потока или алгоритма, который нужно использовать для расшифровки этих данных).

Будет очень ценить ваше время.

2 ответа

Решение

Так как вы хотите попробовать выполнить метод CBC Mode в 3DES-128 битах (заполнение нулями), попробуйте этот git https://github.com/meshileya/dukpt чтобы использовать его для получения открытого текста из зашифрованного текста.

Поскольку у вас уже есть ваши BDK и KSN, просто попробуйте запустить метод ниже.

 public static void main(String[] args) {
     try {
        String theksn = "This should be your KSN";
        String encrypted = "This should be the encrypted data";
        String BDK = "The BDK you mentioned up there";

            tracking= DukptDecrypt.decrypt(theksn, BDK, encrypted);

            System.out.print("PlainText"+ tracking);
        }catch (Exception e){System.out.print(e);}

    }

Одна из самых глупых вещей в реализации Oracle заключается в том, что SecretKeyFactory не поддерживает ключи DES ABA, также известные как ключи DES с двумя ключами.

Эти ключи для операции тройного DES состоят из одного ключа DES A, за которым следует один ключ DES B. Ключ A используется как для первой, так и для последней итерации DES в DES EDE (Encrypt-Decrypt-Encrypt).

Если вы остаетесь в программном обеспечении, вы можете создать метод для создания таких ключей. Проблема заключается в том, что результирующие ключи на самом деле имеют 192 бита, что просто неверно - из-за этого невозможно различить размеры ключей.

В любом случае, для генерации ключей DES ABA можно использовать следующий код:

private static final int DES_KEY_SIZE_BYTES = 64 / Byte.SIZE;
private static final int DES_ABA_KEY_SIZE_BYTES = 2 * DES_KEY_SIZE_BYTES;
private static final int DES_ABC_KEY_SIZE_BYTES = 3 * DES_KEY_SIZE_BYTES;

public static SecretKey createDES_ABAKey(byte[] key) {
    if (key.length != DES_ABA_KEY_SIZE_BYTES) {
        throw new IllegalArgumentException("128 bit key argument with size expected (including parity bits.)");
    }
    try {
        byte[] desABCKey = new byte[DES_ABC_KEY_SIZE_BYTES];
        System.arraycopy(key, 0, desABCKey, 0, DES_ABA_KEY_SIZE_BYTES);
        System.arraycopy(key, 0, desABCKey, DES_ABA_KEY_SIZE_BYTES, DES_KEY_SIZE_BYTES);
        SecretKeySpec spec = new SecretKeySpec(desABCKey, "DESede");
        SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
        SecretKey desKey = factory.generateSecret(spec);
        return desKey;
    } catch (GeneralSecurityException e) {
        throw new RuntimeException("DES-EDE ABC key factory not functioning correctly", e);
    }
}

ОК, так что у нас остается шифрование CBC (без заполнения и ноль IV):

private static final byte[] ENCRYPTION_KEY = Hex.decode("448D3F076D8304036A55A3D7E0055A78");
private static final byte[] PLAINTEXT = Hex.decode("1234567890ABCDEFFEDCBA0987654321");

public static void main(String[] args) throws Exception {
    SecretKey desABAKey = createDES_ABAKey(ENCRYPTION_KEY);
    Cipher desEDE = Cipher.getInstance("DESede/CBC/NoPadding");
    IvParameterSpec zeroIV = new IvParameterSpec(new byte[desEDE.getBlockSize()]);
    desEDE.init(Cipher.ENCRYPT_MODE, desABAKey, zeroIV);
    byte[] ciphertext = desEDE.doFinal(PLAINTEXT);
    System.out.println(Hex.toHexString(ciphertext));
}

Я использовал шестнадцатеричный кодек Bouncy Castle, но можно использовать и другие шестнадцатеричные кодеки.

Другие вопросы по тегам