认证问题与MiFare Ultralight C

时间:2013-09-20 03:04:52

标签: c# nfc rfid mifare 3des

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

DO 在Ultralight-C上拥有完整的数据表(在NDA下)。理解它们不是我的问题(我不认为) - 我只是没有得到我对加密函数的期望。我需要对标签的细节保持一点谨慎,但我不认为标签是我的问题。

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

标签正在踢它并不奇怪,因为我的代码在使用Googling找到的唯一测试向量时没有产生我的期望。

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

鉴于ek(数据)是63FC19906A77D13F k是49454D4B41455242214E4143554F5946 dk(数据)应为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);

此时我希望结果包含测试数据的结果: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'?我不知道我是否忽略了恩智浦正在做的事情,或者我是否成为某种特殊的MS-tastic方式的受害者3DES是在.NET中实现的。我的直觉告诉我某处存在一些字符串问题,但除了我尝试过之外,我不知道在哪里或该怎么办。

老实说,我很乐意得到一些已知良好的测试向量(A,B,K,ek(xx + xx)),这样我就可以在我将代码添加到混合之前使代码工作。我已经向NXP询问了这个问题,但他们提前了8个小时,所以还没有回复,无论如何,我不知道他们的正常反应是多久以及他们是否能够提供帮助 - 我想这取决于它是否被排除对合适的人。

在替代方案中,如果有人知道我可以通过DocStore请求的逐步身份验证应用程序说明,​​那也会有所帮助。我再次使用Ultralight-C和DESFire的NDA,所以我相信如果我知道要求什么,他们会提供它。

谢谢!

1 个答案:

答案 0 :(得分: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;