Хранение секретного ключа на токене USB дает другой ключ (несколько разных байтов) при выполнении getKey () - PullRequest
0 голосов
/ 29 августа 2018

Я пытаюсь сохранить симметричный ключ (SecretKey, который является ключом Triple-DES, режим ECB) на криптографическом USB-токене. Я использую следующий код, чтобы сделать это:

private void storeSecretKey( SecretKey secretKey, String alias ) throws StoreException {
    try {
        log.info("Format: " + secretKey.getFormat());
        log.info("Alg: " + secretKey.getAlgorithm());
        log.info("STORE KEY (bytes): " + Arrays.toString( secretKey.getEncoded()));
        log.info("STORE KEY: " + ArrayUtils.convertToHexString( secretKey.getEncoded(), false, false));

        myKeyStore.setKeyEntry(alias, secretKey, tokenPIN.toCharArray(), null);

        myKeyStore.store(null);

        Key key = myKeyStore.getKey(alias, tokenPIN.toCharArray());

        log.info("Format: " + key.getFormat());
        log.info("Alg: " + key.getAlgorithm());
        log.info("FINAL KEY (bytes): " + Arrays.toString( key.getEncoded()));
        log.info("FINAL KEY: " + ArrayUtils.convertToHexString( key.getEncoded(), false, false));
    }
    catch ( KeyStoreException e ) {
        throw new StoreException( "Unable to store encryption key", e );
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnrecoverableEntryException e) {
        e.printStackTrace();
    }
}

И я получаю следующую запись:

INFO: Format: RAW
INFO: Alg: DESede
INFO: STORE KEY (bytes): [87, -81, -89, -62, 5, -116, -46, 111, -85, -52, -28, -85, -26, -57, -26, -58, -66, -52, -16, 30, 89, -45, 61, -86]
INFO: STORE KEY: 57afa7c2058cd26fabcce4abe6c7e6c6beccf01e59d33daa

INFO: Format: RAW
INFO: Alg: DESede
INFO: FINAL KEY (bytes): [87, -82, -89, -62, 4, -116, -45, 110, -85, -51, -27, -85, -26, -57, -26, -57, -65, -51, -15, 31, 88, -45, 61, -85]
INFO: FINAL KEY: 57aea7c2048cd36eabcde5abe6c7e6c7bfcdf11f58d33dab

Ключ, который хранится на токене (STORE KEY), и ключ, который я получаю с помощью getKey() (FINAL KEY), различаются. Как это может быть?

Пожалуйста, сообщите мне, если вам нужна какая-либо другая информация, которая может отсутствовать.

Спасибо.

1 Ответ

0 голосов
/ 30 августа 2018

Ваш токен USB просто регулирует четность клавиши 3DES. Каждый бит нижнего конца каждого байта является битом четности для (тройного) DES.

Его необходимо установить, если добавление 7 старших битов является четным числом, и не устанавливать, если число нечетное. В конце каждый байт должен иметь нечетную четность, если вы сложите все биты вместе. Таким образом, первый байт со значением 0x57 или 0b0101011_1 имеет 4 бита в верхних позициях, поэтому последний бит должен быть 1 - но он уже установлен, поэтому настройка не требуется. Второй байт, 0xAF или 0b1010111_1 имеет 5 битов в старшей позиции, поэтому последний бит должен быть 0. Это не так, поэтому он настроен на 0b1010111_0 или 0xAE.

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


Это создаст правильно закодированные тройные ключи DES (168-битный эффективный, 192-битный кодированный). Они также называются ключами DES ABC, поскольку все три ключа DES отличаются (с очень высокой вероятностью).

public static SecretKey generate192Bit3DESKey() {
    KeyGenerator keyGen;
    try {
        keyGen = KeyGenerator.getInstance("DESede");
    } catch (NoSuchAlgorithmException e) {
        throw new IllegalStateException("DESede functionality is required for Java, but it is missing");
    }

    // NOTE: this is the effective key size excluding parity bits
    // use 112 for two key (ABA) triple DES keys (not recommended)
    keyGen.init(168);

    // this does adjust parity
    SecretKey desABCKey = keyGen.generateKey();
    return desABCKey;
}

Если ваши данные нуждаются в корректировке впоследствии, вы можете использовать это (только с циклом for, без дополнительного ветвления):

public static byte[] adjustDESParity(final byte[] keyData) {
    for (int i = 0; i < keyData.length; i++) {
        // count the bits, and XOR with 1 if even or 0 if already odd 
        keyData[i] ^= (Integer.bitCount(keyData[i]) % 2) ^ 1;
    }
    return keyData;
}
...