1

我正在尝试使用 NXP MiFare Ultralight C 进行身份验证。我的 NFC 标签阅读器是 Android 手机(Samsung Galaxy Express),但我正在使用 C# 和 System.Security 中的功能在 Windows 7 机器上进行所有加密.Cryptography 命名空间。

确实有关于 Ultralight-C 的完整数据表(根据 NDA)。理解它们不是我的问题(我不这么认为)——我只是没有从我的加密函数中得到我所期望的。我需要对标签的细节有所谨慎,但我不认为标签是我的问题。

基本上发生的事情是我启动身份验证并从标签中获取预期数据。我在我这边做 [the stuff] 并在 Android 上使用 Nfca.Transceive() 向标签发送响应。该函数立即引发“收发失败”异常,我认为这意味着标签告诉我飞跃。其他使用 Transceive() 的尝试都是成功的(写入、启动身份验证等)。

标签将其踢回来并不奇怪,因为我的代码在使用我可以通过谷歌搜索找到的唯一测试向量时没有产生我期望的结果。

因为 NDA 可能最好只坚持使用 3DES 方面的东西,因为这已经不是什么秘密了......这些来自我在网上找到的测试数据:

给定 ek(Data) 是 63FC19906A77D13F 并且 k 是 49454D4B41455242214E4143554F5946 dk(Data) 应该是 c00c24ed61ea0f3e

这不是我从我的代码中得到的,它看起来基本上是这样的:

byte[] key = new byte[16] 
                {                 
                    0x49, 0x45, 0x4D, 0x4B, 
                    0x41, 0x45, 0x52, 0x42, 
                    0x21, 0x4E, 0x41, 0x43, 
                    0x55, 0x4F, 0x59, 0x46
                };

byte[] initVector = new byte[8];

byte[] encrypted =  new byte[8] 
                {
                    0x63, 0xFC, 0x19, 0x90,
                    0x6A, 0x77, 0xD1, 0x3F
                }

byte[] result = DecryptSingleBlock(encrypted, key, ref initVector);

在这一点上,我希望 result 包含来自测试数据的结果: c00c24ed61ea0f3e 但它没有。其值为: 5bdd317111226152

我的解密功能:

public byte[] DecryptSingleBlock(byte[] input, byte[] key, ref byte[] initVector)
{


    using (var des = new TripleDESCryptoServiceProvider  
                         {
                             IV = initVector,   // all zeros this time
                             BlockSize = 64,
                             KeySize = 128,
                             Mode = CipherMode.CBC,
                             Padding = PaddingMode.None,
                             Key = key,
                         })
        {
            byte[] output = des.CreateDecryptor().TransformFinalBlock(input, 0, 8);

            return output;
        }
    }

我有:

  • 颠倒了加密数据中字节的顺序;
  • 将密钥的前 8 个字节与后 8 个字节交换;
  • 玩弄 FeedbackSize(虽然我不清楚 NXP 的预期,或者这是否适用于 CBC 模式(它本身不应该适用于这个单块解密);
  • 使用 CreateEncryptor 而不是 CreateDecryptor。
  • 试图理解 LibFreeFare 代码,尽管它涵盖了更多内容——我只是想通过这一步。

我不知所措。有谁知道我需要对上面的函数做什么才能使其返回给定输入和键的“c00c24ed61ea0f3e”?我不知道我是否忽略了 NXP 正在做的事情,或者我是否成为在 .NET 中实现 3DES 的一些特殊的 MS-tastic 方式的牺牲品。我的直觉告诉我某处存在一些字节序问题,但除了我尝试过的之外,我不知道在哪里或做什么。

老实说,我很乐意获得一些已知良好的测试向量(A、B、K、ek(xx+xx)),这样我就可以在将标签加入混合之前让我的代码正常工作。我已经问过恩智浦,但他们提前了 8 小时,所以还没有回复给正确的人。

或者,如果有人知道我可以通过 DocStore 请求的分步身份验证应用说明,那也会很有帮助。再一次,我在 Ultralight-C 和 DESFire 的 NDA 下,所以如果我知道要什么,我相信他们会提供它。

谢谢!

4

1 回答 1

3

好的,我通过阅读一些关于有人在尝试使用纯托管代码重新创建 openSSL.NET 功能时遇到的问题来解决这个问题。

创建 TripleDESCryptoServiceProvider 时,不要像我上面那样在类初始化程序中包含密钥或 IV。在模式、块大小、密钥大小等被初始化之前设置密钥或 IV 将导致密钥、IV 或两者都被破坏或截断或其他东西,导致我看到的不稳定行为。我还没有进一步实验,看看什么被破坏了以及如何破坏。

很高兴它是固定的,但它花了我大约 8 个小时......

这是执行此操作的方法。为了清楚起见,我省略了其他代码。

var des = new TripleDESCryptoServiceProvider  
{
    BlockSize = 64,
    KeySize = 128,
    Mode = CipherMode.CBC,
    Padding = PaddingMode.None,
};

// the important bit is that these properties are 
// being set last
des.IV = initVector;
des.Key = key;
于 2013-09-20T18:54:19.427 回答