Topic: Authentication with Mifare Classic using libnfc

Hi,

Has anyone here tried using API functions nfc_initiator_transceive_bits() or nfc_initiator_transceive_bytes() functions (not nfc_initiator_mifare_cmd) to program an authentication for a Mifare Classic tag using a known key and crapto1?

I have tried extending builtin anticol by sending {Nr} and {Ar} with parity bits, but the tag does not respond with {At}.. Here is my code snippet (pardon me as I am not proficient in C):

//I have made Crypto1State a static struct, so let's assume crypto1_create() instantiates it
crypto1_create(key);
nt = abtNT[0]<<24|abtNT[1]<<16|abtNT[2]<<8|abtNT[3];
uid = abtUid[0]<<24|abtUid[1]<<16|abtUid[2]<<8|abtUid[3]; 
ks0 = crypto1_word(uid^nt, 0);
ks1 = crypto1_word(nr_enc,1);  //nr_enc is encrypted Nr
ks2 = crypto1_word(0,0);
ks3 = crypto1_word(0,0);
ar = prng_successor(nt,64);
nr = ks1^nr_enc;
//I am reusing the parity() function from crapto1
abtRNandRPar[0] = parity((nr >> 24)&0xff)^1;
abtRNandRPar[1] = parity((nr >> 16)&0xff)^1;
abtRNandRPar[2] = parity((nr >> 8)&0xff)^1;
abtRNandRPar[3] = parity(nr&0xff)^1;
abtRNandRPar[4] = parity((ar >> 24)&0xff)^1;
abtRNandRPar[5] = parity((ar >> 16)&0xff)^1;
abtRNandRPar[6] = parity((ar >> 8)&0xff)^1;
abtRNandRPar[7] = parity(ar&0xff)^1;
ar_enc = ar^ks2;
//abtRNandR[0] to [3] already contains my nr_enc, so only update [4] to [7]
abtRNandR[4]=ar_enc>>24&0xff;
abtRNandR[5]=ar_enc>>16&0xff;
abtRNandR[6]=ar_enc>>8&0xff;
abtRNandR[7]=ar_enc&0xff;
// Calculate parity bits and store in byte array abtRNandRPar
abtRNandRPar[0] ^= BIT(ks1,23);
abtRNandRPar[1] ^= BIT(ks1,15);
abtRNandRPar[2] ^= BIT(ks1,7);
abtRNandRPar[3] ^= BIT(ks2,31);
abtRNandRPar[4] ^= BIT(ks2,23);
abtRNandRPar[5] ^= BIT(ks2,15);
abtRNandRPar[6] ^= BIT(ks2,7);
abtRNandRPar[7] ^= BIT(ks3,31);

//turn off handling parity bits
nfc_configure(pdi,DCO_HANDLE_PARITY,false);
if (!nfc_reader_transceive_bits(pdi,abtRNandR,64,abtRNandRPar,abtRx,&uiRxBits,abtRxPar)) {
    printf("No response from Tag for {At} message\n");
    return 1;
}

I suspect my parity bits are calculated wrongly, but I have verified them manually by hand, unless my understanding is wrong in the first place. Is there someone here kind enough to help me on this? smile Thank you!

Re: Authentication with Mifare Classic using libnfc

Hi Marcus,

marcus2608 wrote:

Has anyone here tried using API functions nfc_initiator_transceive_bits() or nfc_initiator_transceive_bytes() functions (not nfc_initiator_mifare_cmd) to program an authentication for a Mifare Classic tag using a known key and crapto1?

I haven't tried what you are talking about but reading API documentation, i saw that "nfc_initiator_transceive_bytes" function need the configuration option DCO_HANDLE_PARITY to be set to true.

http://www.libnfc.org/libnfc/documentation/api at "Transceive byte and APDU frames" section.

I don't know exactly why and Roel is not available for few days to better explain than me. But I hope it help.

--
Romuald

Romuald Conty

Re: Authentication with Mifare Classic using libnfc

Hello

Iam trying to use my touchatag reader to work with my crapto code. From my understanding after a successfull anticollision and a select with the following command the reader will try to authenticate to sector 4
nfc_initiator_mifare_cmd(pdi,MC_AUTH_A,4,&mp) where mp.mpa.abtKey is for example the default transport key fffffffff.

I have enabled the debug output but i still can not find where the tag nonce is received.

Also another question...i see from the snippet marcus posted he stores the nonce with shifts in variable nt which i suppose is a uint32_t type.(nt = abtNT[0]<<24|abtNT[1]<<16|abtNT[2]<<8|abtNT[3]).
Could this also be done through swap_endian32?

Re: Authentication with Mifare Classic using libnfc

pgrahamm wrote:

Iam trying to use my touchatag reader to work with my crapto code.

Dear pgrahamm,

What do you mean 'my' crapto code? Would you care to elaborate?

Cheers,
Tom

Re: Authentication with Mifare Classic using libnfc

Oh sorry.. i was using the crypto1 implementation from the crapto1 source code on the google projects.

Re: Authentication with Mifare Classic using libnfc

pgrahamm wrote:

Hello
Iam trying to use my touchatag reader to work with my crapto code. From my understanding after a successfull anticollision and a select with the following command the reader will try to authenticate to sector 4
nfc_initiator_mifare_cmd(pdi,MC_AUTH_A,4,&mp) where mp.mpa.abtKey is for example the default transport key fffffffff.

For sector 4 (which is block16...19) you can use the NFC controller to take care of the authentication for you or do it yourself. When you want to let the chip do the crypto, you only have to supply the key (e.g. transport key = ffffffffffff = 12xf) and use the nfc_initiator_mifare_cmd() command.

For sending the frames manually you need the nfc_initiator_transceive_bits() functions to do the crypto yourself. You can implement the cipher yourself, or use a library like crapto1. But you have to do more yourself, the MIFARE Classic card uses a certain command set with parameters. More information about these commands is available at the end of page 13 in this paper.

pgrahamm wrote:

I have enabled the debug output but i still can not find where the tag nonce is received.

Use the authentication auth() command to request it from the card. Check this page for an example trace.

pgrahamm wrote:

Also another question...i see from the snippet marcus posted he stores the nonce with shifts in variable nt which i suppose is a uint32_t type.(nt = abtNT[0]<<24|abtNT[1]<<16|abtNT[2]<<8|abtNT[3]).
Could this also be done through swap_endian32?

I guess this would work fine, but it may could violate platform dependency (INTEL/MOTOROLA endianness).

7 (edited by pgrahamm 2009-09-17 20:16:11)

Re: Authentication with Mifare Classic using libnfc

thank you roel for your answer. I was doing a basic mistake and forgot to call the append crc cause i was confused with the crc configuration. All working fine now big_smile

Re: Authentication with Mifare Classic using libnfc

hmm...although i manage to get random nonce from the tag i must be doing something wrong because i get no At from it in order to do a successfull authentication. The situation is the following. Default key=12xf, uid=7aee5506.i send a transceive bytes with 60 04 and the correct crc and get the nT. Both of them i swap_endian for the bit ordering.
Then im creating a crypto1_state with the key, then calculating ks0,ks1,ks2,ks3 with parsing into the lfsr the uid^nt, the Reader nonce which i first xor with ks0 and then the ks2,ks3 which is crypto1_word(state,0,0) and the reader response
ar = prng_successor(nt,64).

I then send nfc_initiator_transceive_bits(pdi,nRaR,64,nRaRPar,abtRx,&uiRxBits,abtRxPar). the parities are calculated over the plaintext and xored with the keystreams ks1,ks2,ks3. However the tag timeouts with no answer. Iam missing something obvious?

Re: Authentication with Mifare Classic using libnfc

Since there are more questions about this topic I decided to write a working example.
This peace of code uses the current SVN repository version of libnfc and the crapto1 implementation.
I hope this example explains how to perform a manual MIFARE Classic authentication.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libnfc.h>
#include "crapto1.h"

bool mifare_test(dev_info* pdi, byte_t* pbtUid, uint64_t ui64Key, uint32_t uiBlock)
{
  uint32_t pos, nt;
  struct Crypto1State* pcs;
  byte_t abtAuth[4]        = { 0x60,0x00,0x00,0x00 };
  byte_t abtArEnc[8]       = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  byte_t abtArEncPar[8]    = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  byte_t abtRx[MAX_FRAME_LEN];
  byte_t abtRxPar[MAX_FRAME_LEN];
  uint32_t uiRxLen;
  
  // Configure the authentication frame using the supplied block 
  abtAuth[1] = uiBlock;
  append_iso14443a_crc(abtAuth,2);

  // Now we take over, first we need full control over the CRC
  nfc_configure(pdi,DCO_HANDLE_CRC,false);

  // Request plain tag-nonce
  printf(" Nt: ");
  if (!nfc_initiator_transceive_bytes(pdi,abtAuth,4,abtRx,&uiRxLen)) return false;
  print_hex(abtRx,4);
  
  // Save the tag nonce (nt)
  nt = swap_endian32(abtRx);

  // Init cipher with key
  pcs = crypto1_create(ui64Key);

  // Load (plain) uid^nt into the cipher
  for (pos=0; pos<4; pos++)
  {
    // Update the cipher with the tag-initialization 
    crypto1_byte(pcs,pbtUid[pos]^abtRx[pos],0);
  }

  // Generate (encrypted) nr+parity by loading it into the cipher
  for (pos=0; pos<4; pos++)
  {
    // Load in, and encrypt, the reader nonce (plain nr=0x00000000)
    abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ 0x00;
    // Encrypt the parity bits for the 4 plaintext bytes of nr
    abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(0x00);
  }
  
  // Skip 32 bits in pseudo random generator
  nt = prng_successor(nt,32);
  
  // Generate reader-answer from tag-nonce
  for (pos=4; pos<8; pos++)
  {
    // Get the next random byte for verify the reader to the tag 
    nt = prng_successor(nt,8);

    // Encrypt the reader-answer (nt' = suc2(nt))
    abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ (nt&0xff);
    // Encrypt the parity bits for the 4 plaintext bytes of nt'
    abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(nt&0xff);
  }

  // Finally we want to send arbitrary parity bits
  nfc_configure(pdi,DCO_HANDLE_PARITY,false);

  // Transmit reader-answer
  printf(" Ar: ");
  print_hex_par(abtArEnc,64,abtArEncPar);
  if (!nfc_initiator_transceive_bits(pdi,abtArEnc,64,abtArEncPar,abtRx,&uiRxLen,abtRxPar)) return false;
  printf(" At: "); 
  print_hex_par(abtRx,uiRxLen,abtRxPar);
  
  crypto1_destroy(pcs);

  return true;
}


int main(int argc, const char* argv[])
{
  dev_info* pdi;
  tag_info ti;
  uint32_t uiBlock;
  uint64_t ui64Key;

  if (argc < 3)
  {
    printf("syntax: %s <key> <block>\n",argv[0]);
    return 1;
  }
  
  sscanf(argv[1],"%012llx",&ui64Key);
  sscanf(argv[2],"%02x",&uiBlock);
  
  // Try to open the NFC reader
  pdi = nfc_connect(NULL);
  
  if (pdi == INVALID_DEVICE_INFO)
  {
    printf("Error connecting NFC reader\n");
    return 1;
  }
  nfc_initiator_init(pdi);

  // Drop the field for a while, so the card can reset
  nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);

  // Let the reader only try once to find a tag
  nfc_configure(pdi,DCO_INFINITE_SELECT,false);

  // Configure the CRC and Parity settings
  nfc_configure(pdi,DCO_HANDLE_CRC,true);
  nfc_configure(pdi,DCO_HANDLE_PARITY,true);

  // Enable field so more power consuming cards can power themselves up
  nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);

  printf("\nConnected to NFC reader: %s\n\n",pdi->acName);
  
  // Poll for a ISO14443A (MIFARE) tag
  if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
  {
    printf("Error connecting to MIFARE Classic tag\n");
    nfc_disconnect(pdi);
    return 1;
  }
  
  // Print the uid to the screen 
  printf("   uid: %08x\n",swap_endian32(ti.tia.abtUid));
  printf("   key: %012llx\n",ui64Key);
  printf(" block: %02x\n",uiBlock);
  printf("\n");
  
  // Run the MIFARE Classic test
  if (mifare_test(pdi,ti.tia.abtUid,ui64Key,uiBlock))
  {
    printf("\nAuthentication Succesful\n\n");
  } else {
    printf("\nAuthentication failed\n");
  }

  // Reset the "advanced" configuration to normal
  nfc_configure(pdi,DCO_HANDLE_CRC,true);
  nfc_configure(pdi,DCO_HANDLE_PARITY,true);

  // Clean up and release device
  nfc_disconnect(pdi);
  return 0;
}

I used the following line for compilation.

gcc -o crypto1test crypto1test.c crypto1.c crapto1.h -I/usr/local/include/libnfc -L/usr/local/lib/ -lnfc

And the console output during execution

./crypto1test ffffffffffff 14

Connected to NFC reader: ACR122U101 - PN532 v1.4 (0x07)

   uid: 6c14df2a
   key: ffffffffffff
 block: 14

 Nt: 65  25  bb  51  
 Ar: 8c! ca  16  f9! c8! 2d  2a! 54  
 At: 9e  cf! 75! 77  

Authentication Succesful

Re: Authentication with Mifare Classic using libnfc

abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(0x00);

Ohh man... that easy?? big_smile thanks roel..i guess i need to understand the filter function better.
Why do u skip 32bits---> nt = prng_successor(nt,32)  and then nt = prng_successor(nt,8);

with ar=prng_successor(nt,64) wont we get the same?


Thanks this example is crystal clear.

Re: Authentication with Mifare Classic using libnfc

pgrahamm wrote:

Why do u skip 32bits---> nt = prng_su1ccessor(nt,32)  and then nt = prng_successor(nt,8);

Since the 32bits during the transmission of Nr are ignored, we have to skip over these.

After processing and loading the Nr into the cipher we need the next 4 bytes produced by the prng (nt').
Each byte needs a correct (encrypted) parity bit. When we handle 8bits (1byte) at the time, we can pause to get the next key-stream bit from the cipher (without shifting it) by using the filter() function and xor the result against the plain text oddparity of the current Nt' byte.

Re: Authentication with Mifare Classic using libnfc

yeah now i understand. you work byte by byte instead of fiddling with bit positions. a really clever way. nicely implemented wink

13 (edited by schwa226 2009-09-23 06:02:00)

Re: Authentication with Mifare Classic using libnfc

@roel

thanks for this code!

Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9
Auth: 60  03  6e  49
Nt: a7  fa  8f  84
Ar: f1  f1  db  ce! 12  f8! a0  0c!
At: c7  35! 36! 4c!

But for the nested attack I want to repeat an auth().
For this only another auth() request 0x6X 0xYY 0xZZ 0xZZ is needed to get the new encrypted Nt'.

Re: Authentication with Mifare Classic using libnfc

As roel mentioned in another post about controlling nonces,in the second time if you reselect the card this time by not doing a full anticollision but with sending the nfc_initiator_select_tag(pdi,IM_ISO14443A_106,uid,4,&ti) with uid=the already acquired uid the reader will send a WUPA and you can repeat the authentication.

Dont forget however to
nfc_configure(pdi,DCO_HANDLE_CRC,true);
  nfc_configure(pdi,DCO_HANDLE_PARITY,true);
  nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);
after the first authentication. It would work if im not mistaken only if for the other sector u want to authenticate the key is also ffffffffffff. For the nested auth you only need the encrypted nt that the tag will send.

15 (edited by schwa226 2009-09-23 16:10:05)

Re: Authentication with Mifare Classic using libnfc

Thanks,

but I tried to do after successfull manual encrypted auth:

nfc_configure(pdi,DCO_HANDLE_CRC,true);
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);

nfc_initiator_select_tag(pdi,IM_ISO14443A_106,uid,4,&ti)

But the tag isn't responding!

So the idea is do extend the code above with a second:

  abtAuth[1] = uiBlock;
  append_iso14443a_crc(abtAuth,2);

encrypt the 4 bytes with the chiper and same key as the first auth an send it to the tag.
The tag should now send an new Nt'.

Also just a question about the symbol: ⊕ : what does it mean? XOR or ^?

Re: Authentication with Mifare Classic using libnfc

You can find the specific details in this paper

Wirelessly Pickpocketing a Mifare Classic Card wrote:

3.2. Nested authentications
Once an attacker knows a single sector key of a
Mifare Classic, there is a vulnerability that allows
an adversary to recover more keys. When a reader
is already communicating (encrypted) with a tag, a
subsequent authentication command for a new sector
also has to be sent encrypted. After this authentication
command, the internal state of the cipher is set to the
key
for the new sector and the authentication protocol
from Section 2.5 starts again. This time, however, the
challenge of the tag is also sent encrypted. Because
there are only 216 possible nonces, an attacker can
simply try to guess a nonce to recover 32 bits of
keystream.

And yes, it means xor.

Re: Authentication with Mifare Classic using libnfc

schwa226 wrote:

Also just a question about the symbol: ⊕ : what does it mean? XOR or ^?

In C the symbol ^ is xoring. In the papers xoring is also ⊕. In mathematics(matlab area) the symbol ^ means power. i havent found out any other use for that symbol yet tongue

Re: Authentication with Mifare Classic using libnfc

schwa226 wrote:

Thanks,

but I tried to do after successfull manual encrypted auth:

nfc_configure(pdi,DCO_HANDLE_CRC,true);
nfc_configure(pdi,DCO_HANDLE_PARITY,true);
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);

nfc_initiator_select_tag(pdi,IM_ISO14443A_106,uid,4,&ti)

But the tag isn't responding!

Clarification: What i mentioned earlier is if you have a valid reader,tag and you just want to authenticate to another sector where you already know the key.

Re: Authentication with Mifare Classic using libnfc

I just tried this code:

  //do encrypted second auth
  abtAuth2[0] = 0x60;

  // Configure the authentication frame using the supplied block 
  abtAuth2[1] = uiBlock;
  append_iso14443a_crc(abtAuth2,2);

  // Generate (encrypted) abtAuth2by loading it into the cipher
  for (pos=0; pos<4; pos++)
  {
    // Encrypt the abtAuth2
    abtArEnc2[pos] = crypto1_byte(pcs,0x00,0) ^ abtAuth2[pos];
    // Encrypt the parity bits for the 4 plaintext bytes of abtAuth2
    abtArEncPar2[pos] = filter(pcs->odd) ^ oddparity(abtAuth2[pos]);
  }

  // Finally we want to send arbitrary parity bits
  nfc_configure(pdi,DCO_HANDLE_PARITY,false);

  // Transmit second auth
  printf(" Auth2: ");
  print_hex_par(abtArEnc2,32,abtArEncPar2);
  if (!nfc_initiator_transceive_bits(pdi,abtArEnc2,32,abtArEncPar2,abtRx,&uiRxLen,abtRxPar)) return false;
  printf(" Nt': "); 
  print_hex_par(abtRx,uiRxLen,abtRxPar);

Result:

Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9

Auth: 60  03  6e  49
Nt: fa  8f  84  19
Ar: d1  74  3c  52! 4f! 50  aa! fb!
At: 76  86  70! c0!
Auth2: d3  f0  bc! 3c!
Nt': 01

Why just get 1 Byte back, or does this mean that the command was not right encryptet.
Once I got back a 0x00, once I got a 0x0A.

Re: Authentication with Mifare Classic using libnfc

If you check the result length (in bits) you will actually see that you have received only 4 bits (half a byte).
This is most likely a NACK (0x5) encrypted (with the old keystream). Your encrypted bytes probably does not make sense.

Debug your encryption using a multi-auth() trace simulation example.

Re: Authentication with Mifare Classic using libnfc

thx for this traces!

When I do a offline encryption with my tag UID and nr=0x00000000 and my KeyA I can reproduce my log.

If I take your log the auth encryption went wrong.
I think the mistake is already in this part:

  // Generate (encrypted) nr+parity by loading it into the cipher
  for (pos=0; pos<4; pos++)
  {
    // Load in, and encrypt, the reader nonce (plain nr=0x00000000)
    abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ 0x00;
    // Encrypt the parity bits for the 4 plaintext bytes of nr
    abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(0x00);
  }

My question is now what is (pcs,0x00,0)
The byte what should be encrypted, isn't it?

I think nr[0..3], but why xor with 0x00? Is this also nr[0..3]?
For oddparity(0x00) it is nr[0..3]

Because in your trace nr = EF EA 1C DA.

LOL, I m realy confused now!

22 (edited by pgrahamm 2009-09-24 21:52:41)

Re: Authentication with Mifare Classic using libnfc

the way roels code works is byte by byte feeding the values in the lfsr. With the nested authentication the Nr from the reader is encrypted with the already generated keystream. if you just copy paste the code you are creating new keystream. Once you send the encrypted Nr the tag will shift in the register the new sector key and then goes as planned. Till then you are working with the old keystream. What you need is to think that you have to have both the LFSR in the tag and the LFSR in the reader at the same state everytime. If you think about it, the tag in order to reply to you made an extra step by calculating the suc96(nT) and you havent thus the two keystreams are not the same. I hope i make sense

Re: Authentication with Mifare Classic using libnfc

Again me bcause of encryption after one successfull auth!

What I know is after one successful auth I will have a keystream.
Then Chiper = Plain ^ keystream.

But I don't know how to get the keystream.

I tried to recover ks4 from the data I have but it only works with one sample trace.
My tag is every time repsonding with 0x01!

Somebody have a small example after auth to encrypt the plain data?

Re: Authentication with Mifare Classic using libnfc

schwa226 wrote:

But I don't know how to get the keystream.

Check out the example encrypted and decrypted trace I pointed out earlier. If you XOR the ciphertext (encrypted trace) against the plaintext trace, you will get the keystream. Try to get this simulated in your application.
When you got it 100% matching, I can assure you, it will work with your "genuine" tag wink

schwa226 wrote:

My question is now what is (pcs,0x00,0)
The byte what should be encrypted, isn't it?

Incorrect!

This is the byte that is loaded (fed) into the cipher internal state (LFSR). Only the key, Uid, Nt and Nr are fed into the cipher.
After that the internal state only running rounds without new input. So the return value of crypto1_byte() is the keystream-byte, which needs to be XOR'ed against a plaintext byte.

Re: Authentication with Mifare Classic using libnfc

Thanks for this info!

I think I have a misstake with the parity!

Found tag with UID: 9c599b32

Auth: 60  00  f5  7b
Nt: 82  a4  16  6c
Ar: a1  e4! 58  ce! 6e  ea! 41  e0!
At: 5c! ad  f4  39!
KeyStream:  ee0ea8c2
Auth2 plain: 60  00  f5  7b
Auth2: 8e  0e! 5d! b9!

I do

  // Generate (encrypted) abtAuth2by
  for (pos=0; pos<4; pos++)
  {
    // Encrypt the abtAuth2
    abtArEnc2[pos] = abtAuth2[pos] ^ KeyStream[pos];
    // Encrypt the parity bits for the 4 plaintext bytes of abtAuth2
    abtArEncPar2[pos] = filter(pcs->odd) ^ oddparity(abtAuth2[pos]);
  }

When I do this with my tag (nr = EF EA 1C DA) then

Found tag with UID: b4d103a9

Auth: 60  00  f5  7b
Nt: d5  7f  24  cc
Ar: fc  04! 70  6f  a7  d1  d1! d8!
At: b8  53  b4! 35
KeyStream:  d9b59b91
60  00  f5  7b
Auth2 plain: b9! b5! 6e! ea!
Nt': 01