Как работает диверсификация ключей 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.