如何解密从Mifare Desfire EV1发送的第一条消息
有人知道如何解密从卡发送的第一条消息吗?我的意思是,在身份验证成功之后,然后您发送命令(例如0x51(GetRealTagUID)。它返回00 +
random32bits(总是不同)。我尝试使用以下方法对其进行解密:
private byte[] decrypt(byte[] raw, byte[] encrypted, byte[] iv) throws Exception {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
并使用解密(sessionKey,响应,iv)调用它
IV =全零(16字节)
响应= 0x51命令后的32randombits(只是删除了两个零)
有人告诉我,IV在第一个发送命令(0x51)之后发生变化。如何生成正确的IV来解密该响应?我认为全零是错误的,因为解密的消息始终是不同的,并且对于同一张卡它应该始终相同。
-编辑-
应用了(Michael Roland)指令后,解密后的响应仍然只是随机位。这是我的代码(我想我做错了什么):
byte[] x = encrypt(sessionKey, iv, iv); byte[] rx = rotateBitsLeft(x);
if ((rx[15] & 0x01) == 0x01)
rx[15] = (byte) (rx[15] ^ 0x87);
if ((rx[15] & 0x01) == 0x00)
rx[15] = (byte) (rx[15] ^ 0x01);
byte[] crc_k1 = rx;
byte[] rrx = rotateBitsLeft(rx);
if ((rrx[15] & 0x01) == 0x01)
rrx[15] = (byte) (rrx[15] ^ 0x87);
if ((rrx[15] & 0x01) == 0x00)
rrx[15] = (byte) (rrx[15] ^ 0x01);
byte[] crc_k2 = rrx;
byte[] command = { (byte) 0x51, (byte) 0x80, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00 };
for (int i = 0; i < 16; i++){
command[i] = (byte) (command[i] ^ crc_k2[i]);
}
byte[] iv2 = encrypt(sessionKey, command, iv);
byte[] RealUID = decrypt(sessionKey, ReadDataParsed, iv2);
Log.e("RealUID", ByteArrayToHexString(RealUID));
-编辑3-
仍然返回始终不同的值。我认为问题可能出在这里:
byte[] iv2 = encrypt(sessionKey, command, iv);
创建用于解密响应的新IV时要使用什么IV?那里全都是零。
回答:
认证后,IV重置为全零。使用AES身份验证时,您必须为每个后续命令计算CMAC(即使CMAC实际上未附加到该命令之后)。因此,针对您的命令的CMAC计算将导致正确的IV初始化,以对响应进行解码。即,该命令的CMAC等于解密响应的IV。同样,对于所有其他命令,IV是来自先前加密/
CMAC的最后一个密码块。
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
使用会话密钥(使用零的IV)加密一个零块()。->x[0..15]
x[0..15]
向左旋转一位。->rx[0..15]
- 如果最后一位(中的位0
rx[15]
)为1:rx[15]
与或0x86
。 - 储存
rx[0..15]
为crc_k1[0..15]
。 rx[0..15]
向左旋转一位。->rrx[0..15]
- 如果最后一位(中的位0
rrx[15]
)为1:rrx[15]
与或0x86
。 - 储存
rrx[0..15]
为crc_k2[0..15]
。
- 使用
0x80 0x00 0x00 ...
密码的块大小填充命令(AES为16字节)。如果命令长度与块大小的倍数匹配,则不添加填充。 - 对于您的命令(
0x51
),它看起来像:0x51 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
- 如果添加了填充,请使用来对填充命令的最后16个字节进行xor运算
crc_k2[0..15]
。 - 如果未添加填充,请使用来对命令的最后16个字节进行xor运算
crc_k1[0..15]
。 enc(IV xor datablock)
用会话密钥加密(在发送模式下,即前一个块的密文为新的IV)结果。- 最后一块的密文是CMAC和新的IV。
public void rotateLeft(byte[] data) { byte t = (byte)((data[0] >>> 7) & 0x001);
for (int i = 0; i < (data.length - 1); ++i) {
data[i] = (byte)(((data[i] << 1) & 0x0FE) | ((data[i + 1] >>> 7) & 0x001));
}
data[data.length - 1] = (byte)(((data[data.length - 1] << 1) & 0x0FE) | t);
}
以上是 如何解密从Mifare Desfire EV1发送的第一条消息 的全部内容, 来源链接: utcz.com/qa/407511.html