GlobalPlatform UICC SCP03 AES 卡挑战
Posted
技术标签:
【中文标题】GlobalPlatform UICC SCP03 AES 卡挑战【英文标题】:GlobalPlatform UICC SCP03 AES Card Challenge 【发布时间】:2013-08-13 15:09:54 【问题描述】:我在 GlobalPlatform UICC (2.2.1) 卡的测试工具中实现 SCP03。该工具的代码是用 C# 编写的,我正在尝试使用 dotNet AES 类。
我的问题是我的代码无法重现卡片发送的卡片挑战。我不确定这是因为我提供给 AES 加密器的数据,还是我没有正确使用 AES 加密器。
我的代码基于 GP Spec 2.2 Amendment-D,这有点模糊,至少在生成卡片挑战的过程中并且没有指定初始向量。
我创建的推导数据如下:-
00 00 00 00 00 00 00 00 00 00 00 - 11 bytes all zero
02 - card challenge identifier
00 - separator
00 40 - length
01 - counter
00 00 02 - key sequence counter (received from the card)
A0 00 00 01 51 00 00 00 - appID of the currently selected application (the ISD)
80 00 00 00 00 - padding to 32 bytes.
我已将初始向量 (IV) 设置为 16 个字节的零。
为了创建卡片挑战,我使用了静态密钥 K-ENC,它的值是:-
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
卡片返回的卡片挑战(验证为正确)是:-
83 FA 04 2C 5C 10 F7 78
我为重现卡片挑战而编写的代码是:-
public static Byte []
GenerateCardChallengeScp03
( UInt32 seqCounter,
Byte [] selectedAid,
Byte [] baseKeyEnc)
Byte [] finalDerivationData = null;
Byte [] sequenceCounter = new Byte [3];
Byte [] derivationData = new Byte [16];
for (int i = 0; i < derivationData.Length; i++)
derivationData [i] = 0x00;
sequenceCounter [0] = (Byte) (seqCounter / 0X10000);
sequenceCounter [1] = (Byte) (seqCounter / 0X100);
sequenceCounter [2] = (Byte) (seqCounter);
derivationData [11] = 0x02; // Card challenge
derivationData [12] = 0x00; // Separator
derivationData [13] = 0x00; // MSB length
derivationData [14] = 0x40; // LSB length
derivationData [15] = 0x01; // Counter
finalDerivationData = GP_Utils.ConcatenateArrays (derivationData, sequenceCounter);
finalDerivationData = GP_Utils.ConcatenateArrays (finalDerivationData, selectedAid);
Byte [] icv = new Byte [] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00;
Byte [] inputData = PadForAesEncryption_0x80 (finalDerivationData);
AesCryptoServiceProvider aes = new AesCryptoServiceProvider ();
aes.BlockSize = 128;
aes.FeedbackSize = 128;
aes.KeySize = baseKeyEnc.Length * 8;
aes.Mode = CipherMode.CBC;
aes.Key = baseKeyEnc;
aes.IV = icv;
aes.Padding = PaddingMode.None;
ICryptoTransform encryptor = aes.CreateEncryptor ();
Byte [] outputData = encryptor.TransformFinalBlock (inputData, 0, inputData.Length);
Byte [] cardChallenge = new Byte [8];
for (int i = 0; i < cardChallenge.Length; i++)
cardChallenge [i] = outputData [i];
return (cardChallenge);
那么,我没有做什么,或者做错了什么?
【问题讨论】:
【参考方案1】:不确定您是否找到了答案。如果我没记错的话,您应该通过根据 NIST 800-38B 计算 CMAC 而不仅仅是普通的 AES 加密来计算卡挑战。
【讨论】:
【参考方案2】:我可以验证您的卡片挑战。请查看crypto.c。有一个名为calculate_card_challenge_SCP03 的函数正在使用calculate_CMAC_aes。它是 C 代码,但您应该能够将其转换为 C# 代码。我正在使用 OpenSSL 的加密函数,所以 C# 应该有类似的东西。
static void test_card_challenge_SCP03()
BYTE sequenceCounter[3] = 0x00, 0x00, 0x02;
BYTE invokingAID[8] = 0xA0, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00, 0x00;
BYTE calculatedCardChallenge[8];
BYTE cardChallenge[8] = 0x83,0xFA,0x04,0x2C,0x5C,0x10,0xF7,0x78;
OPGP_ERROR_STATUS status;
status = calculate_card_challenge_SCP03((PBYTE)OPGP_VISA_DEFAULT_KEY, (PBYTE)sequenceCounter, invokingAID, sizeof(invokingAID), calculatedCardChallenge);
sput_fail_unless(OPGP_ERROR_CHECK(status) == 0, NULL);
OPGP_LOG_HEX(_T("Calculated card challenge: "), calculatedCardChallenge, 8);
OPGP_LOG_HEX(_T("Given card challenge: "), cardChallenge, 8);
sput_fail_unless(memcmp(calculatedCardChallenge, cardChallenge, 8) == 0, "Card Challenge Comparison");
您使用什么卡进行测试?我正在寻找具有已知密钥的 SCP03 支持的公共可用测试卡来实现 SCP03。我正在使用 Gemalto 商店的 Gemalto IDPrime PIV Card 2.0 卡,但这似乎使用了一些秘密的未记录密钥、未记录的密钥派生或与标准不兼容。
【讨论】:
以上是关于GlobalPlatform UICC SCP03 AES 卡挑战的主要内容,如果未能解决你的问题,请参考以下文章
UICC 之 USIM 详解全系列——UICC中的Apps与Files结构