提示:
这些内容仅用于DESFire EV1卡片。不带EV的DESFire卡使用CRC16而非CRC32。此外,参与CRC计算的数据也不同。
在DESFire EV1卡片中,修改密钥(ChangeKey,0xC4)命令,新密钥的CRC32,是根据密钥本身计算出来的。
而Cryptogram的CRC32,是由命令(0xC4)+密钥号(Key No.)+未加密的Cryptogram本身计算出来的。
请注意:DESFire的DES密钥长度至少为16字节。如果密钥的前8字节和后8字节完全相同,则该密钥为单DES密钥(而非2K3DES密钥)。使用单DES密钥(高低8字节相同)通过认证的,过程密钥(Session Key)只使用前8字节(RndA的前4字节+RndB的前4字节)。
为了便于理解或编写代码,也可认为单DES过程密钥长度为16字节,且前后8字节是相同的。
In case of WANTED single DES operation (leading 8 bytes of the secret key are identical to the trailing 8 bytes), only the first 8 bytes of the session key (RndA1st half + RndB1st half) are used for further cryptographic operations, the trailing 8 bytes must not be used.
《MF3 IC D40 Product Specification Revision 3.1 (April 2004)》P11。
提示:以下的例子是从网上搬运来的,里面的数据仅供参考,不一定完全正确。
使用默认的2K3DES密钥#0(密钥的值全是0x00)进行认证
*** Authenticate(KeyNo= 0, Key= 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (DES)) Sending: <1A 00> Response: * RndB_enc: B8 90 04 7F 2D C8 D6 8B * RndB: 74 B8 43 5F CB A0 B6 75 * RndB_rot: B8 43 5F CB A0 B6 75 74 * RndA: 92 31 34 8B 66 35 A8 AF * RndAB: 92 31 34 8B 66 35 A8 AF B8 43 5F CB A0 B6 75 74 * RndAB_enc: 7C 84 6A 50 7B 9B 6E 68 64 BC 33 72 A3 06 A8 C1 Sending: Response: <00 B7 96 DD 3F 81 15 45 F3> * RndA_enc: B7 96 DD 3F 81 15 45 F3 * RndA_dec: 31 34 8B 66 35 A8 AF 92 * RndA_rot: 31 34 8B 66 35 A8 AF 92 * SessKey: 92 30 34 8A 74 B8 42 5E 92 30 34 8A 74 B8 42 5E (DES)
修改2K3DES密钥,密钥号#0。(用于认证的密钥编号与欲修改的密钥编号相同)
*** ChangeKey(KeyNo= 0) * SessKey: B4 28 2E FA 9E B8 2C AE B4 28 2E FA 9E B8 2C AE (DES) * SessKey IV: 00 00 00 00 00 00 00 00 * New Key: 00 10 20 31 40 50 60 70 80 90 A0 B0 B0 A0 90 80 (2K3DES) * CRC Crypto: 0x5001FFC5 * Cryptogram: 00 10 20 31 40 50 60 70 80 90 A0 B0 B0 A0 90 80 C5 FF 01 50 00 00 00 00 * CryptogrEnc: 87 99 59 11 8B D7 7C 70 10 7B CD B0 C0 9C C7 DA 82 15 04 AA 1E 36 04 9C Sending:Response: <00>
CRC32:0x5001FFC5(或C5 FF 01 50),是由C4 00 00 10 20 31 40 50 60 70 80 90 A0 B0 B0 A0 90 80计算出的。
因为欲修改的密钥与当前认证使用的密钥相同(指密钥号相同),因此后面Cryptogram最后4字节为0x00。
修改2K3DES密钥,密钥号#1。(用于认证的密钥编号与欲修改的密钥编号不同,注意是不同!)
*** ChangeKey(KeyNo= 1) * SessKey: 9C 70 56 82 5C 08 9E C8 9C 70 56 82 5C 08 9E C8 (DES) * SessKey IV: 00 00 00 00 00 00 00 00 * New Key: 00 10 20 31 40 50 60 70 80 90 A0 B0 B0 A0 90 80 (2K3DES) * Cur Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (DES) * CRC Crypto: 0xD7A73486 * CRC New Key: 0xC4EF3A3A * Cryptogram: 00 10 20 31 40 50 60 70 80 90 A0 B0 B0 A0 90 80 86 34 A7 D7 3A 3A EF C4 * CryptogrEnc: 7D 83 D3 4E FB 6C 84 98 48 E2 D6 37 AD A2 D0 87 14 36 1A E6 C4 63 14 52 Sending:Response: <00 1D 5C 27 97 10 86 30 8D> CMAC: 1D 5C 27 97 10 86 30 8D
CRC32:0xD7A73486(或86 34 A7 D7),是由C4 01 00 10 20 31 40 50 60 70 80 90 A0 B0 B0 A0 90 80计算出的。
CRC32:0xC4EF3A3A(或3A 3A EF C4),是由00 10 20 31 40 50 60 70 80 90 A0 B0 B0 A0 90 80计算出的。
AES的密钥有额外一个字节的密钥版本(KeyVersion),在修改AES密钥时,计算Cryptogram的CRC32需要包括密钥版本字节。
修改AES密钥:
*** ChangeKey(KeyNo= 1) * SessKey: 1C D3 8E BD 95 F3 1C 8A B8 7F 0A C9 C4 EB 64 C6 (AES) * SessKey IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * New Key: 00 10 20 30 40 50 60 70 80 90 A0 B0 B0 A0 90 80 (AES) * Cur Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (AES) * CRC Crypto: 0x84B47033 * CRC New Key: 0x1979E3BF * Cryptogram: 00 10 20 30 40 50 60 70 80 90 A0 B0 B0 A0 90 80 10 33 70 B4 84 BF E3 79 19 00 00 00 00 00 00 00 * CryptogrEnc: 30 23 FA 06 2D 25 0A 04 35 BA E9 45 CA BE 96 5D 62 2A 47 1D 32 5D 1D 42 EA 81 44 41 CB 1A 20 C3 Sending:Response: <00 9B 68 30 91 50 E0 72 5E> CMAC: 9B 68 30 91 50 E0 72 5E
CRC32:0x84B47033(或33 70 B4 84),是由C4 01 00 10 20 30 40 50 60 70 80 90 A0 B0 B0 A0 90 80 10计算出的。(0x10是密钥版本号)
CRC32: 0x1979E3BF(或BF E3 79 19),是由00 10 20 30 40 50 60 70 80 90 A0 B0 B0 A0 90 80计算出的。
下面,用VB .Net实现DESFire中的CRC32算法。
Public Shared Function CRC32_JAMCRC(ByVal InputBytes() As Byte) As Byte()
If InputBytes Is Nothing OrElse InputBytes.Length < 1 Then
Return Nothing
End If
Dim tmp1, tmp2 As UInteger
Dim CRC As UInteger = &HFFFFFFFFUI '用&H表示十六进制数,默认使用32位有符号整数(Integer)表示。后面加上UI,表示它是32位无符号整数(UInteger)
Dim Polynomial As UInteger = &HEDB88320UI '0x04C11DB7逆序
Dim i, j As Integer
Dim uCRC(3) As Byte
For i = 0 To InputBytes.Length - 1
tmp1 = (CRC >> 8) And &HFFFFFFUI
tmp2 = CUInt(CRC Xor InputBytes(i)) And &HFF
For j = 0 To 7
If (tmp2 And 1) = 1 Then
tmp2 = (tmp2 >> 1) Xor Polynomial
Else
tmp2 = tmp2 >> 1
End If
Next
CRC = tmp1 Xor tmp2
Next
'DESFire在APDU中的CRC,默认是低字节在前。BitConverter的输出也是低字节在前。本函数输出的字节数组,可以直接扔到APDU里使用,无需再转换。
uCRC = BitConverter.GetBytes(CRC)
Return uCRC
End Function



