解密 DESFire 读取数据会话

问题描述 投票:0回答:2

我们正在努力解密 DESFire 数据。我们已成功验证并可以解密 RndA´,这与我们创建的 RndA 相同。

现在我们尝试从位置 0 读取 16 个字节的加密文件。

从一些java库中我们可以看出,我们必须使用加密的Command作为IV来解密。是这样吗?

这里是例子:

SessionKey: 0ba1caf83a26a72170149b7504895f34
ReadCommand: bd00000000100000
Crc32C for Cmd: D9CEE76B
Secret: 6a0d0f0d5c8f054b1e5914a42e49728622774c6272e5c34a69ed302251576aaf

现在我们将 ReadCommand 与 Crc32C 连接起来:

bd00000000100000D9CEE76B

然后我们将零填充到 16 字节

bd00000000100000D9CEE76B00000000

然后我们使用会话密钥和 IV 0 生成 e(cmd + crc + padding) 以获得下一个 iv 来解密响应:

77E24803B5401C61F657607923E5A318

现在我们用会话密钥和 IV:=e(cmd + crc32) 解密秘密并得到:

D1E9A4726C2A5C3FD5938E714C07524EF1F74BD9000000000000000000000000

有很多零,让我觉得我们距离答案并不遥远。 所以请有人告诉我们,出了什么问题?

我们将此库用于 Crc32C 这是我们在测试中使用的完整代码:

        [Theory]
    [InlineData("6a0d0f0d5c8f054b1e5914a42e49728622774c6272e5c34a69ed302251576aaf", "0ba1caf83a26a72170149b7504895f34", "bd00000000100000")]
    public void DecryptData_Test(string secretS, string sessionKeyS, string cmdS) 
    {
        var cryptoAlgoFactory = new Func<SymmetricAlgorithm>(() => Aes.Create());
        var keyLength = 16;

        var secret = EncriptionHelper.StringToByte(secretS);
        var sessionKey = EncriptionHelper.StringToByte(sessionKeyS);
        var cmd = EncriptionHelper.StringToByte(cmdS);

        var crytoAlgo = cryptoAlgoFactory();
        crytoAlgo.Mode = CipherMode.CBC;
        crytoAlgo.Padding = PaddingMode.None;

        var encryptor = crytoAlgo.CreateEncryptor(sessionKey, new byte[keyLength]);

        var crc32 = BitConverter.GetBytes(Crc32C.Crc32CAlgorithm.Compute(cmd));

        var padding = 0;
        if ((cmd.Length + crc32.Length) % keyLength != 0)
            padding = keyLength - ((cmd.Length + crc32.Length) % keyLength);

        var result = new byte[cmd.Length + crc32.Length + padding];

        Array.Copy(cmd, result, cmd.Length);
        Array.Copy(crc32, 0, result, cmd.Length, crc32.Length);

        var iv = encryptor.TransformFinalBlock(result, 0, result.Length);

        crytoAlgo = cryptoAlgoFactory();
        crytoAlgo.Mode = CipherMode.CBC;
        crytoAlgo.Padding = PaddingMode.None;

        var decryptor = crytoAlgo.CreateDecryptor(sessionKey, iv);

        var plain = decryptor.TransformFinalBlock(secret, 0, secret.Length);

        Assert.NotNull(plain);
    }
encryption cryptography aes mifare desfire
2个回答
0
投票

我们发现,我们必须使用 CMACing 加密命令,而不使用 CRC32C。

因此有以下解决方案:

SessionKey: 0ba1caf83a26a72170149b7504895f34
ReadCommand: bd00000000100000
Secret: 6a0d0f0d5c8f054b1e5914a42e49728622774c6272e5c34a69ed302251576aaf

首先使用CMACing加密cmd,得到以下IV,用于进一步解密(注意使用SessionKey):

A70BEC41E95A706F11F7DA3D59F2F256

然后用 IV cmac(cmd) 在 CBC 模式下解密得到结果:

01000030303030313233343536100300F1F74BD9000000000000000000000000

在 CMACing 中仍然存在问题,因此我们使用了 NuGet Packege,效果很好。


-1
投票

我正在为同样的问题而苦苦挣扎。我需要读取一个32字节的加密文件,但我无法成功解密。

这些是我到目前为止所做的步骤:

  1. 发送 RndAB_Encrypted 并从卡接收 RndA_Rotated(收到的 RndA_Rotated 与原始版本一致)

  2. 生成会话密钥

  3. 生成子项 1 和 2

  4. 填充命令来读取文件(在我的例子中

    90 BD 0000 07 01000000 020000 00 (CLA,INS,P1P2, Lc,FileID, ByteNumber, Le)
    根据您提供的CMACing链接。结果是这个命令
    90 BD 0000 07 01000000 020000 00 80 00 00

  5. 现在我将填充的命令与子密钥 2 进行异或,并使用会话密钥和 IV(16 个“00”字节)对其进行加密,然后得到我的 CMAC。

  6. 我发送命令

    90 BD 0000 07 01000000 020000 00
    并收到 48 字节响应(我假设是 32 字节文件数据 + CMAC)

  7. 然后我使用会话密钥和 CMAC 作为 IV 来解密响应(前 32 个字节),但解密的数据每次迭代都会发生变化。所以我认为这不可能是正确的。

您知道问题出在哪里吗?

© www.soinside.com 2019 - 2024. All rights reserved.