Android: Autenticación con NXP MiFare Ultralight C

He estado intentando por más de una semana para hacer un teléfono Android autenticar con un Mifare Ultralight C. He confirmado que puedo escribir en la etiqueta (escribiendo a una página de memoria sin garantía y luego leer lo que escribí). También puedo escribir en las páginas clave (44-47) y escribir 0x00 para los 16 bytes clave.

Cuando intento autenticar, el siguiente es un ejemplo de los datos involucrados durante un intercambio – es de un registro escrito por mi aplicación. ¿Puede alguien decirme si estoy haciendo algo incorrecto? SOY bajo no divulgación y tengo acceso a las hojas de datos completas . Tenga en cuenta que las cadenas hexadecimales a continuación son obviamente versiones legibles por humanos de los datos que se envían y reciben, que en el código consta de arrays de bytes.

Enviar comando de autenticación

Received rndB: 8A5735694D9D7542 Key: 00000000000000000000000000000000 IV: 0000000000000000 Decrypted rndB: EF340C62E1B866D4 rndB': 340C62E1B866D4EF rndA: 6E262630E299F94F rndA+rndB': 6E262630E299F94F340C62E1B866D4EF Key: 00000000000000000000000000000000 IV: 8A5735694D9D7542 ek(RndA+rndB'): E36C6C46FAAC60BA45DDF5F5A0802C79 

Después de enviar 0xAF + E36C6C46FAAC60BA45DDF5F5A0802C79 inmediatamente pierdo la conexión con la etiqueta. He examinado la hoja de datos y leído todas las publicaciones que puedo encontrar aquí. También he mirado el código libfreefare y honestamente no puedo entender lo que estoy haciendo mal.

El soporte técnico de NXP había sido completamente insensible.

¿Algunas ideas? Estoy en una pérdida.

A continuación se muestra un ejemplo de código java para realizar la autenticación Ultralight-C como se describe en MF0ICU2 / MIFARE Ultralight C – Documento IC de tickets sin contacto (capítulo 7.5.5 – Autenticación 3DES, página 15):

 public void authenticate(byte[] key) throws CardException { System.out.println("AUTHENTICATE"); byte[] encRndB = transmitRaw(new byte[] { 0x1A, 0x00 }); if((encRndB.length!=9)||(encRndB[0]!=AF)) { throw new RuntimeException("Invalid response!"); } encRndB=Arrays.copyOfRange(encRndB, 1, 9); System.out.println(" - EncRndB: " + toHex(encRndB)); byte[] rndB = desDecrypt(key, encRndB); System.out.println(" - RndB: " + toHex(rndB)); byte[] rndBrot = rotateLeft(rndB); System.out.println(" - RndBrot: " + toHex(rndBrot)); byte[] rndA = new byte[8]; generateRandom(rndA); System.out.println(" - RndA: " + toHex(rndA)); byte[] encRndArotPrime = transmitRaw(ArrayUtils.addAll(new byte[] {AF}, desEncrypt(key, ArrayUtils.addAll(rndA, rndBrot)))); if((encRndArotPrime.length!=9)||(encRndArotPrime[0]!=0x00)) { throw new RuntimeException("Invalid response!"); } encRndArotPrime=Arrays.copyOfRange(encRndArotPrime, 1, 9); System.out.println(" - EncRndArot': " + toHex(encRndArotPrime)); byte[] rndArotPrime = desDecrypt(key, encRndArotPrime); System.out.println(" - RndArot': " + toHex(rndArotPrime)); if(!Arrays.equals(rotateLeft(rndA), rndArotPrime)) { throw new RuntimeException("Card authentication failed"); } } protected static SecureRandom rnd = new SecureRandom(); protected static void generateRandom(byte[] rndA) { rnd.nextBytes(rndA); } protected byte[] desEncrypt(byte[] key, byte[] data) { return performDes(Cipher.ENCRYPT_MODE, key, data); } protected byte[] desDecrypt(byte[] key, byte[] data) { return performDes(Cipher.DECRYPT_MODE, key, data); } private byte[] iv = new byte[8]; protected byte[] performDes(int opMode, byte[] key, byte[] data) { try { Cipher des = Cipher.getInstance("DESede/CBC/NoPadding"); SecretKeyFactory desKeyFactory = SecretKeyFactory.getInstance("DESede"); Key desKey = desKeyFactory.generateSecret(new DESedeKeySpec(ArrayUtils.addAll(key, Arrays.copyOf(key, 8)))); des.init(opMode, desKey, new IvParameterSpec(iv)); byte[] ret = des.doFinal(data); if(opMode==Cipher.ENCRYPT_MODE) { iv=Arrays.copyOfRange(ret, ret.length-8, ret.length); } else { iv=Arrays.copyOfRange(data, data.length-8, data.length); } return ret; } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidKeySpecException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) { throw new RuntimeException(e); } } protected static byte[] rotateLeft(byte[] in) { return ArrayUtils.add(Arrays.copyOfRange(in, 1, 8), in[0]); } 

Nota: este código utiliza Apache Commons Lang .

  • Lectura RFID con teléfonos Android
  • ¿Etiqueta criptográfica de NFC / RFID?
  • Etiqueta NFC / Codificación de etiquetas
  • Cómo obtener ayuda para el lector Emulación de tarjeta basada en host
  • Lector RFID para dispositivos móviles
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.