无法使用 SessionKey 解密 3DES

unable to decrypt 3DES with SessionKey

我正在为 read/write Desfire 非接触式卡开发 C 项目。 现在我实现了身份验证,我可以从卡中读取数据,但它是用 3DES 加密的。

我想解密下一条消息:

EB 54 DF DD 07 6D 7C 0F BD D6 D1 D1 90 C6 C7 80 92 F3 89 4D 6F 16 7C BF AA 3E 7C 48 A8 71 CF A2 BD D0 43 07 1D 65 B8 7F

我的会话密钥(在身份验证步骤中生成)是:

44 E6 30 21 4A 89 57 38 61 7A B8 7C A9 91 B2 C0

我知道 IV={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }

有了这些信息,我可以去 here 并选择 3DES、CBC 模式,我可以解密消息并且我有办法知道它是正确的。 应该是,解密:

10 1a 01 31 32 ae 03 de 39 b0 00 97 7f 65 e9 43 93 89 53 5c 9e 04 a9 3f 95 71 24 0f 0a 9b f7 ee d4 5b 1b c6 78 7a f4 36

无论如何,我尝试使用OpenSSL des库实现C代码,但我发现了下一个难点:

I need 3 Keys of 8 bytes each, but I have 1 SessionKey of 16 bytes long.

我尝试将 SessionKey 拆分为 Key1/Key2/Key1 但没有成功。 我已经阅读了很多相关内容,我发现的唯一线索是我必须从我的 16 字节 SessionKey 生成这 3 个密钥(将其作为密码),但我觉得它对我来说太先进了。 如果这是唯一的方法,有没有关于ossl密钥推导的教程(evp_bytestokey)?还有其他办法吗?

谢谢

编辑: 所以,现在我处在一个非常奇怪的地方。正如你们中的许多人所指出的,我已经从会话密钥中取出前 8 个字节作为密钥 3(这就是我在 Key1/Key2/Key1 中提到的)。无论如何它似乎不起作用,但它确实起作用了,这让我感到困惑。 我得到:

Decrypted : 11 1B 00 30 33 AF 02 DF DE 01 00 00 00 01 01 00 14 C1 26 8F 03 20 20 41 00 30 39 01 00 00 00 00 00 00 00 00 00 00 75 B1

什么时候

Expected : 10 1a 01 31 32 ae 03 de de 01 00 00 00 01 01 00 14 c1 26 8f 03 20 20 41 00 30 39 01 00 00 00 00 00 00 00 00 00 00 75 b1

所以我得到了预期的结果,将前 8 个字节与 01 进行异或运算。这有意义吗?正如 OSSL 文档中所说:请注意,libcrypto 中同时存在 DES_cbc_encrypt() 和 DES_ncbc_encrypt()。我建议您只使用 ncbc 版本(n 代表新)。请参阅 OpenSSL DES 联机帮助页的 BUGS 部分和这些函数的源代码。 但是我只能访问旧版本...这可能是问题所在吗??

有可能你不需要3个32bits的key,只需要一个3*32bits的key,字节顺序要好 最好的问候

也许加密是双密钥 3DES,在这种情况下重复前 8 个字节,字节 0-7 为字节 16-23:44 E6 30 21 4A 89 57 38 61 7A B8 7C A9 91 B2 C0 44 E6 30 21 4A 89 57 38.

有些 3DES 实现会自动执行此操作,有些则必须您自己执行。

如果这不起作用,您需要在问题中提供更多信息。

会话密钥的大小

由于您引用的是 MIFARE DESFire 并且您使用的是 16 字节会话密钥,因此您可能使用 2 密钥三重 DES。这意味着 16 字节的会话密钥实际上是两个密钥(8 字节,或者实际上是 56 位,每个都有 8 个未使用的 "parity" 位)。

为了将其映射到具有 3 个密钥的 3DES,您只需将前 8 个字节附加到会话密钥的末尾,这样您就可以得到

                     +-------------------------+-------------------------+
16 byte session key: | 8 bytes                 | 8 bytes                 |
                     | 44 E6 30 21 4A 89 57 38 | 61 7A B8 7C A9 91 B2 C0 |
                     +-------------------------+-------------------------+-------------------------+
24 byte 3DES key:    | 8 bytes                 | 8 bytes                 | 8 bytes                 |
                     | 44 E6 30 21 4A 89 57 38 | 61 7A B8 7C A9 91 B2 C0 | 44 E6 30 21 4A 89 57 38 |
                     +-------------------------+-------------------------+-------------------------+

第一个解密明文块

如果解密后的明文的前 8 个字节与预期值不同,但其余字节匹配,则明确表明您为 CBC 模式使用了不正确的初始化向量。

看看 CBC 模式是如何工作的:

所以对于第一个块,明文计算为

P0 = DecK(C0) XOR IV

对于剩余的块,明文计算为

Pn = DecK(Cn) XOR Cn-1

这意味着只有第一个块的解密依赖IV。剩余块的解密依赖于前面的密文。

由于您假设 IV 全部为零,因此 XOR 运算不执行任何操作。因此,在您的情况下,第一个块的明文计算为

P0 = DecK(C0) XOR {0} = DecK(C0) = '10 1A 01 31 32 AE 03 DE'

因为这个预期值与您得到的实际值有偏差 ('11 1B 00 30 33 AF 02 DF')。这很可能意味着您使用了不正确的 IV 进行解密:

P0  = DecK(C0)        = '10 1A 01 31 32 AE 03 DE'
P'0 = DecK(C0) XOR IV = '11 1B 00 30 33 AF 02 DF'

您可以通过对两个值进行异或运算来计算您使用的 IV:

P'0 = P0 XOR IV
P'0 XOR P0 = IV

IV = '11 1B 00 30 33 AF 02 DF' XOR '10 1A 01 31 32 AE 03 DE'
   = '01 01 01 01 01 01 01 01'

由于这个IV的不同之处在于每个字节的LSB被设置为1,我想知道你是否不小心在IV上使用了DES_set_odd_parity()的方法。这可以解释为什么更改了 LSB(即奇偶校验位,如果该值是 DES 密钥)。