android authentication nfc rfid mifare

Android: autenticación con NXP MiFare Ultralight C



authentication nfc (1)

A continuación se muestra un código java de ejemplo para realizar la autenticación Ultralight-C tal como se describe en el documento IC de ticket MF0ICU2 / MIFARE Ultralight C - Contactless (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 usa Apache Commons Lang .

Hace más de una semana que intento hacer que un teléfono Android se autentique con un Mifare Ultralight C. He confirmado que puedo escribir en la etiqueta (escribiendo en una página de memoria no segura y luego leyendo lo que escribí). También puedo escribir en las páginas clave (44-47) y he escrito 0x00 para los 16 bytes clave.

Cuando trato de autenticar, el siguiente es un ejemplo de los datos involucrados durante un intercambio: es de un registro escrito por mi aplicación. ¿Alguien puede decirme si estoy haciendo algo incorrecto? YO SOY bajo no divulgación y tengo acceso a las hojas de datos completos . 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 matrices 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 , pierdo inmediatamente la conexión con la etiqueta. He revisado la hoja de datos y he 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.