Como descriptografar a primeira mensagem enviada pelo Mifare Desfire EV1
Alguém tem uma idéia de como descriptografar a primeira mensagem enviada do cartão? Quero dizer, após o sucesso da autenticação e, em seguida, você envia um comando (por exemplo 0x51 (GetRealTagUID). Ele retorna 00 + random32bits (sempre diferente). Eu tento descriptografá-lo com:
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;
}
E chamando-o com decrypt (sessionKey, resposta, iv)
IV = todos os zeros (16 bytes)
resposta = que 32randombits após o comando 0x51 (acabou de remover os dois zeros)
Alguém me disse, que o IV muda após o primeiro comando enviado (0x51). Como gerar o IV correto para descriptografar essa resposta? Eu acho que todos os zeros estão errados, porque a mensagem descriptografada é sempre diferente e deve ser sempre a mesma com o mesmo cartão.
-EDITAR-
Depois de aplicar suas instruções (de Michael Roland), a resposta descriptografada ainda é apenas um bit aleatório. Aqui está o meu código (acho que estou fazendo algo errado):
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));
-EDIT3-
Ainda retornando sempre valores diferentes. Eu acho que o problema pode estar aqui:
byte[] iv2 = encrypt(sessionKey, command, iv);
Qual IV usar ao criar o novo IV para descriptografar a resposta? É tudo zeros lá.