解密 DESFire 读取数据会话
Decrypt DESFire ReadData Session
我们正在努力解密 DESFire 数据。我们已经成功验证并且可以解密与我们创建的 RndA 相同的 RndA。
现在我们尝试从位置 0 读取 16 个字节的加密文件。
从一些 java 库中我们可以看出,我们必须使用加密命令作为 IV 进行解密。是吗?
示例如下:
SessionKey: 0ba1caf83a26a72170149b7504895f34
ReadCommand: bd00000000100000
Crc32C for Cmd: D9CEE76B
Secret: 6a0d0f0d5c8f054b1e5914a42e49728622774c6272e5c34a69ed302251576aaf
现在我们用 Crc32C 连接 ReadCommand:
bd00000000100000D9CEE76B
然后我们将零填充到 16 个字节
bd00000000100000D9CEE76B00000000
然后我们用会话密钥和IV 0生成e(cmd + crc + padding)以获得下一个iv用于解密resposne:
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);
}
我们发现,我们必须使用 CMACing 而不是 CRC32C 来加密命令。
因此解决方案如下:
SessionKey: 0ba1caf83a26a72170149b7504895f34
ReadCommand: bd00000000100000
Secret: 6a0d0f0d5c8f054b1e5914a42e49728622774c6272e5c34a69ed302251576aaf
先用CMACing加密cmd得到如下IV进一步解密(注意使用SessionKey):
A70BEC41E95A706F11F7DA3D59F2F256
然后用IV cmac(cmd)在CBC模式下解密得到结果:
01000030303030313233343536100300F1F74BD9000000000000000000000000
在 CMACing 中仍然有问题,所以我们使用了一个 NuGet Packege,效果很好。
我们正在努力解密 DESFire 数据。我们已经成功验证并且可以解密与我们创建的 RndA 相同的 RndA。
现在我们尝试从位置 0 读取 16 个字节的加密文件。
从一些 java 库中我们可以看出,我们必须使用加密命令作为 IV 进行解密。是吗?
示例如下:
SessionKey: 0ba1caf83a26a72170149b7504895f34
ReadCommand: bd00000000100000
Crc32C for Cmd: D9CEE76B
Secret: 6a0d0f0d5c8f054b1e5914a42e49728622774c6272e5c34a69ed302251576aaf
现在我们用 Crc32C 连接 ReadCommand:
bd00000000100000D9CEE76B
然后我们将零填充到 16 个字节
bd00000000100000D9CEE76B00000000
然后我们用会话密钥和IV 0生成e(cmd + crc + padding)以获得下一个iv用于解密resposne:
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);
}
我们发现,我们必须使用 CMACing 而不是 CRC32C 来加密命令。
因此解决方案如下:
SessionKey: 0ba1caf83a26a72170149b7504895f34
ReadCommand: bd00000000100000
Secret: 6a0d0f0d5c8f054b1e5914a42e49728622774c6272e5c34a69ed302251576aaf
先用CMACing加密cmd得到如下IV进一步解密(注意使用SessionKey):
A70BEC41E95A706F11F7DA3D59F2F256
然后用IV cmac(cmd)在CBC模式下解密得到结果:
01000030303030313233343536100300F1F74BD9000000000000000000000000
在 CMACing 中仍然有问题,所以我们使用了一个 NuGet Packege,效果很好。