This discussion is archived
9 Replies Latest reply: Jun 8, 2012 2:06 AM by 941427 RSS

can't generate the correct session keys for mutual authentification

941427 Newbie
Currently Being Moderated
Hi,

I'm working on mutual authentification process using SCP02 of global plateform and i can't generate the correct session keys . here is my process in java

kmc="52554E4E43415244454E53494341454E"

private static byte[] Static_ENC_key={0x27,(byte) 0x28,(byte)0x37,(byte) 0x34,(byte) 0x03,(byte) 0xD9,(byte) 0x90,(byte) 0xBD,(byte) 0xA5,(byte) 0x0F,
          (byte) 0xFC,(byte) 0x8F,(byte) 0x65,(byte) 0xF8,(byte) 0xAC,(byte) 0x21};

private static byte[] Static_MAC_key={(byte) 0x38,0x53,(byte)0x66,(byte) 0x85,(byte) 0xE3,(byte) 0xBB,(byte) 0xF9,(byte) 0xFA,(byte) 0xE7,
                         (byte) 0x41,(byte) 0x9D,(byte) 0x89,(byte) 0xDB,(byte) 0xAE,(byte) 0x22,(byte) 0xE0};

byte[] sequence_counter={0x00,0x05};
          byte[] card_challenge={(byte) 0x9C,(byte) 0xB0,0x21,(byte) 0x99,0x67,0x18};
          byte[] card_cryptogram={(byte) 0xEE,0x69,(byte) 0xEE,0x05,0x3A,0x04,0x4E,0x2F};
          
     byte[] padding={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
          
          //for S-ENC
          byte[] derivation_data_enc=new byte [16];
          byte[] constant_enc={0x01,(byte) 0x82};
          System.arraycopy(constant_enc,0,derivation_data_enc,0,constant_enc.length);
          System.arraycopy(sequence_counter,0,derivation_data_enc,constant_enc.length,sequence_counter.length);
          System.arraycopy(padding,0,derivation_data_enc,sequence_counter.length+constant_enc.length,padding.length);
     
          //for S-MAC
          byte[] derivation_data_mac=new byte [16];
          byte[] constant_mac={0x01,(byte) 0x01};
          System.arraycopy(constant_mac,0,derivation_data_mac,0,constant_mac.length);
          System.arraycopy(sequence_counter,0,derivation_data_mac,constant_mac.length,sequence_counter.length);
          System.arraycopy(padding,0,derivation_data_mac,sequence_counter.length+constant_mac.length,padding.length);
     
          
          
          //create a 3DES key from static ENC key
          DESedeKeySpec key_deriv = new DESedeKeySpec(Apdu.ba2s(Static_ENC_key).getBytes());
          SecretKeyFactory key_factory=SecretKeyFactory.getInstance("DESede");
          javax.crypto.SecretKey key_enc = key_factory.generateSecret(key_deriv);

     //create a 3DES key from static MAC key
          DESedeKeySpec key_deriv1 = new DESedeKeySpec(Apdu.ba2s(Static_MAC_key).getBytes());
          SecretKeyFactory key_factory1=SecretKeyFactory.getInstance("DESede");
          javax.crypto.SecretKey key_mac = key_factory1.generateSecret(key_deriv1);
          
          IvParameterSpec iv = new IvParameterSpec(new byte[]{0, 0, 0, 0, 0, 0, 0, 0});
          
          
          
          /*******************Generation of ENC and MAC session key according to SCP02*************/
          try {
               
               Cipher cipherCBC_enc = Cipher.getInstance("DESede/CBC/noPadding");
               
               //create Kenc
               cipherCBC_enc.init(Cipher.ENCRYPT_MODE,key_enc,iv);
               byte[] Session_S_ENC_key=cipherCBC_enc.doFinal(derivation_data_enc);     
               
               System.out.println("S-ENC Session Key"+Apdu.ba2s(Session_S_ENC_key));
               //create Kmac
               cipherCBC_enc.init(Cipher.ENCRYPT_MODE,key_mac,iv);
               byte[] Session_S_MAC_key=cipherCBC_enc .doFinal(derivation_data_mac);     
               System.out.println("S-MAC Session Key"+Apdu.ba2s(Session_S_MAC_key));
               
               
          } catch (IllegalBlockSizeException e) {     
               // TODO Auto-generated catch block
               e.printStackTrace();
          } catch (BadPaddingException e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
          }
          catch (InvalidKeyException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
          }               
          
i got S-ENC Session Key16: 83D00FEB8EF10A3A121CCD6E3AD9801F
S-MAC Session Key16: 06F56718AD5E029E67C7913F87C90FD0

But the correct one is
S-ENC Session Key: F6371CEB27A62FB944C4DDC1A2E52E70

Please help, i can't move to verifying the card crypto until i get the correct keys
  • 1. Re: can't generate the correct session keys for mutual authentification
    Sebastien_Lorquet Journeyer
    Currently Being Moderated
    this crypto is not a trivial piece of work, it requires very careful inspection of the gp spec. Everything is written in there. the only other document required is the way to compute the ISO9697 (IIRC) HMAC. single DES rounds plus final triple des is tricky. (maybe it's for SCP01? can't remember, I implemented both, because I also have old cards - that was 3 years ago)

    Anyway it's normal to spend a large amount of time on it.

    are you sure that you used the same challenges and sequence counter?
    also check the IVParameterSpec is not passed by reference so the iv may be modified between the two uses.
    and check the chaining mode, I remember ECB and CBC are used, I may be confused wit SCP01

    and double check all constants, I don't have the spec under my nose right now but I remember there was a 0181 somewhere, maybe not 0182.

    All of this from memory of course, that's just some ways to go forward. this needs to be fact checked with the proper documents.
  • 2. Re: can't generate the correct session keys for mutual authentification
    941427 Newbie
    Currently Being Moderated
    I'm using the SCP02 conforming to the GPCardSpec_v2.2 , and for the generation of th EN key session the constant is 0182, 0181 is for KEK session key. For the ecryption mode it's the CBC one i cheked on the spec. But fir the IV i don't get it, you say 'is not passed by reference' , because first i initialize it and pass it in the method init directly.

    In the spec the way we obtain the derivation data for SCP02 is constant+sequence counter+padding (0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00).

    I think the problem is the way i encrypt or i don't khwo because i'm using DESedeKeySpec for the instantiation of the key and SecretKeyFactory . Do you think this implementation is the problem???

    NB: i'm using the information of anathor test that was succesful in external authentificate , so i used the same keys and the same card response f0r init update just to obtain the correct session key.
  • 3. Re: can't generate the correct session keys for mutual authentification
    Sebastien_Lorquet Journeyer
    Currently Being Moderated
    okay

    if you have doubts about crypto, you can use bouncycastle. instead of using normal java crypto api, this lib has direct crypto routines that are simpler to use
    See the following classes:

    import org.bouncycastle.crypto.BlockCipher;
    import org.bouncycastle.crypto.digests.SHA1Digest; //nothing to do with gp!
    import org.bouncycastle.crypto.digests.SHA256Digest;
    import org.bouncycastle.crypto.engines.DESEngine;
    import org.bouncycastle.crypto.engines.DESedeEngine;
    import org.bouncycastle.crypto.modes.CBCBlockCipher;
    import org.bouncycastle.crypto.params.KeyParameter;
    import org.bouncycastle.crypto.params.ParametersWithIV;


    the thing with the iv was: are you sure the iv is correctly initialized each time you use it in cipher.init()?

    it could happen that the data inside the iv array is modified after being used in init/update/dofinal, to allow continuation of the crypto stream in next calls. displaying the value of "iv" just before use could help.
  • 4. Re: can't generate the correct session keys for mutual authentification
    Adriaan Explorer
    Currently Being Moderated
    For a good working example, look at the GPJ source code: http://sourceforge.net/projects/gpj/
  • 5. Re: can't generate the correct session keys for mutual authentification
    941427 Newbie
    Currently Being Moderated
    thank a lot i used the boucy castle API and i got the good key.
  • 6. Re: can't generate the correct session keys for mutual authentification
    941427 Newbie
    Currently Being Moderated
    i can't find import org.bouncycastle.crypto.modes.ECBBlockCipher . i need to encrypt with ECB mode but eclipse can't resolve it , knowing that it recognize all other importations.

    Thankx,
  • 7. Re: can't generate the correct session keys for mutual authentification
    Sebastien_Lorquet Journeyer
    Currently Being Moderated
    yes, there is no class for ECB, because Electronic Code*B*ook is the trivial mode.
    On the contrary CBC is an additional "layer" (mode of operation) that can work with any block algorithm, so a helper class was made for it.

    Just encode the input blocks with DESedeEngine with the same key without any chaining.

    If you're implementing a spec that uses ECB that's ok, but for anything else (including large data blocks) it's not very secure. Just see the wikipedia article and compare the tux images!

    http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation


    I'm glad that I could help.

    Regards

    (PS: @Adriaan "a fishing pole is better that a fish", looking at someone else's code is not a good way to build expertise - you may loose time, copy hidden bugs, and loose freedom to implement it in a way that you control and understand - specifically such a crypto code. going back to the spec is the best way to learn here. If you want to check you work, generate test vectors with a known good implementation and compare. in that situation, the test vectors were already made by our "numbered" friend)
  • 8. Re: can't generate the correct session keys for mutual authentification
    941427 Newbie
    Currently Being Moderated
    Thank you very match!! it works just with DESedeEngine(). I have to say that the bouncy castle API is very efficient, i didn't expect that !
  • 9. Re: can't generate the correct session keys for mutual authentification
    941427 Newbie
    Currently Being Moderated
    Hi,

    I have a strange problem that i can't understand.I'm testing the mutual authentification process,so i have already a test that succeded but not in my application.So when i take information for the response of the card to init update (i mean sequence counter , data diversification , card challenge and cart cryptogram) i get the good session keys , card cryptogram and MAC when i compare to the result of the other test .But!! when i use another test with another information , it failed !!! I can't understand

    Please help if you have an idea about the reason of this problem

    Thankx

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points