Как работает диверсификация ключей Visa2 на картах Gemalto и в инструменте GPP?

У меня есть несколько Java-карт Gemalto, и, как вы видите ниже, я согласен с процессом взаимной аутентификации с использованием GlobalPlatformPro:

C:\globalPlatformPro> gp -visa2 -key 47454d5850524553534f53414d504c45 -list -debug -verbose -info

Reader: ACS ACR1281 1S Dual Reader ICC 0
ATR: 3B7D96000080318065B0831111E583009000

A>> 00A40400 00
A<< 6F198408A000000018434D00A50D9F6E061291921101009F6501FF 9000

***** Card info:
A>> 80CA9F7F 00
A<< 9F7F2A4090612812919211010041849D08192420C3033241840333418403344184000003250000000000000000 9000

***** KEY INFO
A>> 80CA00E0 00
A<< E012C00401FF8010C00402FF8010C00403FF8010 9000
VER:255 ID:1 TYPE:DES3 LEN:16
VER:255 ID:2 TYPE:DES3 LEN:16
VER:255 ID:3 TYPE:DES3 LEN:16
Key version suggests factory keys

A>> 80500000 08 2CA286A611F6CAFD 00
A<< 4D0041849D08192420C3FF0131D644E9913234DDE1F0A6A462C71805 9000
A>> 84820100 10 CC2D0CC35F6BD64F816A774D3ADB18F2
A<< 9000

//Useless lines for censored!

C:\globalPlatformPro>

Поскольку документы VISA не являются общедоступными, я взглянул на исходный код GlobalPlatformPro, чтобы узнать, как происходит диверсификация ключей для visa2и я нашел эти методы там:

public static GPKeySet diversify(GPKeySet keys, byte[] diversification_data, Diversification mode, int scp) throws GPException {
    try {
        GPKeySet result = new GPKeySet();
        Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
        for (KeyType v : KeyType.values()) {
            if (v == KeyType.RMAC)
                continue;
            byte [] kv = null;
            // shift around and fill initialize update data as required.
            if (mode == Diversification.VISA2) {
                kv = fillVisa(diversification_data, v);
            } else if (mode == Diversification.EMV) {
                kv = fillEmv(diversification_data, v);
            }

            // Encrypt with current master key
            cipher.init(Cipher.ENCRYPT_MODE, keys.getKey(v).getKey(Type.DES3));

            byte [] keybytes = cipher.doFinal(kv);
            // Replace the key, possibly changing type. G&D SCE 6.0 uses EMV 3DES and resulting keys
            // must be interpreted as AES-128
            GPKey nk = new GPKey(keybytes, scp == 3 ? Type.AES : Type.DES3);
            result.setKey(v, nk);
        }
        return result;
    } catch (BadPaddingException |InvalidKeyException | IllegalBlockSizeException e) {
        throw new GPException("Diversification failed.", e);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        throw new RuntimeException("Diversification failed.", e);
    }
}

public static byte[] fillVisa(byte[] init_update_response, KeyType key) {
    byte[] data = new byte[16];
    System.arraycopy(init_update_response, 0, data, 0, 2);
    System.arraycopy(init_update_response, 4, data, 2, 4);
    data[6] = (byte) 0xF0;
    data[7] = key.getValue();
    System.arraycopy(init_update_response, 0, data, 8, 2);
    System.arraycopy(init_update_response, 4, data, 10, 4);
    data[14] = (byte) 0x0F;
    data[15] = key.getValue();
    return data;
}

Поэтому я попытался повторить генерацию криптограммы хоста для вышеупомянутой связи. Я имею:

Мастер Ключ = 47454d5850524553534f53414d504c45

На основе спецификации карты GlobalPlatform v 2.3:

Host_Challenge = 2CA286A611F6CAFD

ПЕРВОНАЧАЛЬНОЕ ОБНОВЛЕНИЕ ответ: 4D0041849D08192420C3 FF01 31D644E9913234DD E1F0A6A462C71805

  • Ключевые данные диверсификации = 4D0041849D08192420C3
  • Основная информация = FF01: Таким образом, SCP01 используется.
  • Card Challenge = 31D644E9913234DD
  • Криптограмма карты = E1F0A6A462C71805

Итак, на основе исходного кода GPP выше:

  • Diversification_Data = 4D00 9D081924 F001 4D00 9D081924 0F01

И тогда Статический Ключ ENC:

Static_ENC = Encrypt(MasterKey, Diversification_Data )

Итак, используя этот онлайн-инструмент, я имею:

Это значит:

Static_ENC_KEY =84f2a84ecdade8cacc9e7e07faebe4e6

Для вычисления ключа сеанса ENC я снова использовал спецификацию GlobalPlatform:

Так что я:

  • Derivation_Data = 913234DD 2CA286A6 31D644E9 11F6CAFD

И так ENC_Session_Key является:

ENC_Session_Key =b1ed5ea3f69978274d2ffe0de467ec1c

Наконец, генерация и проверка криптограммы хоста выполняется путем объединения 8-байтового запроса карты и 8-байтового запроса хоста, что приводит к 16-байтовому блоку и конкатенации этого 16-байтового массива с 80 00 00 00 00 00 00 00, Затем подпишите это с помощью ключа сеанса ENC в режиме CBC с нулевым ICV:

Data2Encrypt = 31D644E9913234DD 2CA286A611F6CAFD 8000000000000000

И я имею:

2 ответа

Решение

Ну, я дважды попробовал описанные выше шаги, и каждый раз в конце я сталкивался с неправильным значением host_cryptogram! Но когда я повторяю шаги и записываю их построчно в своем вопросе, я, наконец, замечаю, что конечный результат, который у меня есть, равен результату GPP в первом из моих вопросов! Поэтому вместо того, чтобы удалить мой вопрос, я предпочел оставить его здесь для будущих зрителей.

Итак, к выводу:

Наличие ключевых схем диверсификации в смарт-карте добавляет один шаг к тем шагам, которые упомянуты в Спецификации карты GlobalPlatform для расчета криптограммы карты и значений MAC. И этот шаг вычисляет статические ключи.

Diversification_Data для расчета статических ключей ( источник):

введите описание изображения здесь

Первые два байта данных ответа INITAL UPDATE совпадают xxh xxh и байты [4:8] этого IC Serial Number,

Шифрование данных диверсификации с использованием алгоритма Triple DES в режиме ECB с мастер-ключом возвращает статические ключи.

Для проверки криптограммы карты необходимо объединить 8 байтов запроса хоста и 8 байтов запроса карты и «8000000000000000». после создания строки, затем подписывая это с помощью сеансового ключа ENC в режиме CBC с нулевым ICV.

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