Announce two new product: SmartCard Reader Rockey200 and USB2.0 Extension Cable

ROCKEY 200 is a handy and portable USB Smart Card reader that can perform read/write operations on any ISO 7816-1/2/3/4 smart cards which are compatible with protocol T=0 and T=1.

USB2.0 Extension Cable With high speed USB 2.0 devices such as USB token ,USB Card Reader and so on.

Come to try it now!

3DES

JavaCard Applet Development Related Questions and Answers.
deepanshsinghal
Posts: 44
Joined: Thu Apr 06, 2017 8:01 am
Points: 452
Contact:

3DES

Postby deepanshsinghal » Sat Apr 29, 2017 1:36 am

Hi Everyone,

Does anyone have code snippet for implementation of 3DES.
i implemented 3DES but it is not generating correct MAC.

public EMVCrypto(GenerateAC x) {
theApplet = x; // reference back to the applet

diversification_data = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_DESELECT);
sessionkey = JCSystem.makeTransientByteArray((short) 16, JCSystem.CLEAR_ON_DESELECT);
transaction_data = JCSystem.makeTransientByteArray((short) 256, JCSystem.CLEAR_ON_DESELECT);

desCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_ISO9797_M2, false);
desMAC = Signature.getInstance(Signature.ALG_DES_MAC8_ISO9797_M2, false);

mk = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_2KEY, false);
mk.setKey(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09,
(byte) 0x10, (byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16 }, (short) 0);
sk = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_2KEY, false);
}

private void setSessionKey(APDU apdu) {

// as 8-byte diversification data we take the ATC followed by all zeroes
Util.setShort(diversification_data, (short) 0, theApplet.protocolState.getATC());
// Util.arrayFillNonAtomic(diversification_data, (short) 2, (short) 6, (byte) 0);

desCipher.init(mk, Cipher.MODE_ENCRYPT);

// compute left 8 bytes of the session key
diversification_data[2] = (byte) 0xF0;
desCipher.doFinal(diversification_data, (short) 0, (short) 8, sessionkey, (short) 0);

// compute right 8 byte of the session key
diversification_data[2] = (byte) 0x0F;
desCipher.doFinal(diversification_data, (short) 0, (short) 8, sessionkey, (short) 0);

sk.setKey(sessionkey, (short) 0);

}


private void computeAC(byte cid, byte[] apduBuffer, short length, byte[] response, short offset) {

Util.arrayCopy(apduBuffer, OFFSET_CDATA, transaction_data, (short) 0, length);

// MAC is a CBC-MAC computed according to ISO/IEC 9797-1, padding method 2
desMAC.init(sk, Signature.MODE_SIGN);
desMAC.sign(transaction_data, (short) 0, (short) (length), response, offset);

}

This code snippet is taken from openemv

Correct me where i am doing mistake.

Regards,
Deepansh

User avatar
UNKNwYSHSA
Posts: 628
Joined: Thu May 21, 2015 4:05 am
Points: 2975
Contact:

Re: 3DES

Postby UNKNwYSHSA » Tue May 02, 2017 2:39 am

Please make sure first that your key is
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16

not
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
sense and simplicity

User avatar
UNKNwYSHSA
Posts: 628
Joined: Thu May 21, 2015 4:05 am
Points: 2975
Contact:

Re: 3DES

Postby UNKNwYSHSA » Tue May 02, 2017 2:53 am

And follow the EMV specification, it said:
For the session key used to generate and verify the Application Cryptogram and
the ARPC, the diversification value is the ATC followed by n-2 bytes of '00':
R := ATC || '00' || '00' || … || '00' || '00' || '00'.

But your implementation is:

Code: Select all

private void setSessionKey(APDU apdu) {

   // as 8-byte diversification data we take the ATC followed by all zeroes
   Util.setShort(diversification_data, (short) 0, theApplet.protocolState.getATC());
   // Util.arrayFillNonAtomic(diversification_data, (short) 2, (short) 6, (byte) 0);

   desCipher.init(mk, Cipher.MODE_ENCRYPT);

   // compute left 8 bytes of the session key
   diversification_data[2] = (byte) 0xF0;
   desCipher.doFinal(diversification_data, (short) 0, (short) 8, sessionkey, (short) 0);

   // compute right 8 byte of the session key
   diversification_data[2] = (byte) 0x0F;
   desCipher.doFinal(diversification_data, (short) 0, (short) 8, sessionkey, (short) 0);

   sk.setKey(sessionkey, (short) 0);
}
sense and simplicity

deepanshsinghal
Posts: 44
Joined: Thu Apr 06, 2017 8:01 am
Points: 452
Contact:

Re: 3DES

Postby deepanshsinghal » Thu May 25, 2017 10:37 am

Thanks UNKNwYSHSA,

As per you suggested i did according to that and i was able to generate the session key. Now Can you help to find the mistake in computeAC().

Thanks in Advance,
Deepansh

User avatar
UNKNwYSHSA
Posts: 628
Joined: Thu May 21, 2015 4:05 am
Points: 2975
Contact:

Re: 3DES

Postby UNKNwYSHSA » Fri May 26, 2017 6:02 am

Let me have a look.
sense and simplicity

deepanshsinghal
Posts: 44
Joined: Thu Apr 06, 2017 8:01 am
Points: 452
Contact:

Re: 3DES

Postby deepanshsinghal » Fri May 26, 2017 8:58 am

Hi UNKNwYSHSA,

This is the method i'm using can you tell me the mistake that i am doing....

private void computeAC(byte cid, byte[] apduBuffer, short length, byte[] response, short offset) {

/* Collect the data to be MAC-ed in the array transaction_data */

// Copy CDOL from the APDU buffer, at offset 0:
Util.arrayCopy(apduBuffer, OFFSET_CDATA, transaction_data, (short) 0, length);

// MAC is a CBC-MAC computed according to ISO/IEC 9797-1, padding method 2
desMAC.init(sk, Signature.MODE_SIGN);
// desMAC.init(sk, Cipher.MODE_ENCRYPT);
desMAC.sign(transaction_data, (short) 0, (short) (length), response, offset);

}

public void generateFirstACReponse(APDU apdu, byte cid, byte[] apduBuffer, short length, byte[] iad, short iad_length, byte[] response,
short offset) {

setSessionKey(apdu);

response[offset] = (byte) 0x80; // Tag for Format 1 cryptogram

// Length: 1 byte CID + 2 byte ATC + 8 byte AC = 11
response[(short) (offset + 1)] = (byte) 11;

// 1 byte CID, ie the type of AC returned
response[(short) (offset + 2)] = cid;

// 2 byte ATC, at offset 3:
Util.setShort(response, (short) (offset + 3), theApplet.protocolState.getATC());

// the AC itself
computeAC(cid, apduBuffer, length, response, (short) (offset + 5));

// generateSecondACReponse(cid, apduBuffer, length, iad, iad_length, response, offset);
}

Thanks

tay00000
Posts: 112
Joined: Tue Sep 27, 2016 10:58 am
Points: 1472
Contact:

Re: 3DES

Postby tay00000 » Fri May 26, 2017 12:14 pm

Please use the code block to encapsulate your codes. It is hard to read.

Code: Select all

/*
 * Collect the data to be MAC-ed in the array transaction_data
 */
private void computeAC(byte cid, byte[] apduBuffer, short length, byte[] response, short offset) {
    // Copy CDOL from the APDU buffer, at offset 0:
    Util.arrayCopy(apduBuffer, OFFSET_CDATA, transaction_data, (short) 0, length);

    // MAC is a CBC-MAC computed according to ISO/IEC 9797-1, padding method 2
    desMAC.init(sk, Signature.MODE_SIGN);
   
    desMAC.sign(transaction_data, (short) 0, (short) (length), response, offset);
}

public void generateFirstACReponse(APDU apdu, byte cid, byte[] apduBuffer, short length, byte[] iad, short iad_length, byte[] response,
short offset) {

    setSessionKey(apdu);

    response[offset] = (byte) 0x80; // Tag for Format 1 cryptogram

    // Length: 1 byte CID + 2 byte ATC + 8 byte AC = 11
    response[(short) (offset + 1)] = (byte) 11;

    // 1 byte CID, ie the type of AC returned
    response[(short) (offset + 2)] = cid;

   // 2 byte ATC, at offset 3:
    Util.setShort(response, (short) (offset + 3), theApplet.protocolState.getATC());

    // the AC itself
    computeAC(cid, apduBuffer, length, response, (short) (offset + 5));

    // generateSecondACReponse(cid, apduBuffer, length, iad, iad_length, response, offset);
}

User avatar
UNKNwYSHSA
Posts: 628
Joined: Thu May 21, 2015 4:05 am
Points: 2975
Contact:

Re: 3DES

Postby UNKNwYSHSA » Sat May 27, 2017 1:19 am

deepanshsinghal wrote:Hi UNKNwYSHSA,

This is the method i'm using can you tell me the mistake that i am doing....

private void computeAC(byte cid, byte[] apduBuffer, short length, byte[] response, short offset) {

/* Collect the data to be MAC-ed in the array transaction_data */

// Copy CDOL from the APDU buffer, at offset 0:
Util.arrayCopy(apduBuffer, OFFSET_CDATA, transaction_data, (short) 0, length);

// MAC is a CBC-MAC computed according to ISO/IEC 9797-1, padding method 2
desMAC.init(sk, Signature.MODE_SIGN);
// desMAC.init(sk, Cipher.MODE_ENCRYPT);
desMAC.sign(transaction_data, (short) 0, (short) (length), response, offset);

}

public void generateFirstACReponse(APDU apdu, byte cid, byte[] apduBuffer, short length, byte[] iad, short iad_length, byte[] response,
short offset) {

setSessionKey(apdu);

response[offset] = (byte) 0x80; // Tag for Format 1 cryptogram

// Length: 1 byte CID + 2 byte ATC + 8 byte AC = 11
response[(short) (offset + 1)] = (byte) 11;

// 1 byte CID, ie the type of AC returned
response[(short) (offset + 2)] = cid;

// 2 byte ATC, at offset 3:
Util.setShort(response, (short) (offset + 3), theApplet.protocolState.getATC());

// the AC itself
computeAC(cid, apduBuffer, length, response, (short) (offset + 5));

// generateSecondACReponse(cid, apduBuffer, length, iad, iad_length, response, offset);
}

Thanks


The data elements for generate AC in your code is not same as specification mentioned.
Please see specification EMV 4.3 Book 2 Security and Key Management 8.1.1 for details.
And the OpenEMV applet implement it as following (same as specification):

Code: Select all

   private void computeAC(byte cid, byte[] apduBuffer, short length,
         byte[] response, short offset){
      /* Collect the data to be MAC-ed in the array transaction_data */

      // Copy CDOL from the APDU buffer, at offset 0:
      Util.arrayCopy(apduBuffer, OFFSET_CDATA, transaction_data, (short)0, length);
      // 2 bytes AIP, at offset length:
      Util.setShort(transaction_data, length, theApplet.staticData.getAIP());
      // 2 bytes ATC, at offset length + 2:
      Util.setShort(transaction_data, (short)(length+2), theApplet.protocolState.getATC());
 
      //TODO What is the following data?
      transaction_data[(short)(length+4)] = (byte) 0x80;
      transaction_data[(short)(length+5)] = (byte) 0x0;
      transaction_data[(short)(length+6)] = (byte) 0x0;

      // MAC is a CBC-MAC computed according to ISO/IEC 9797-1, padding method 2
        desMAC.init(sk, Signature.MODE_SIGN);
       desMAC.sign(transaction_data, (short)0, (short)(length+7), response, offset);

   }
sense and simplicity

deepanshsinghal
Posts: 44
Joined: Thu Apr 06, 2017 8:01 am
Points: 452
Contact:

Re: 3DES

Postby deepanshsinghal » Mon May 29, 2017 10:07 am

I tried with openemv implementation also... but no success

User avatar
UNKNwYSHSA
Posts: 628
Joined: Thu May 21, 2015 4:05 am
Points: 2975
Contact:

Re: 3DES

Postby UNKNwYSHSA » Tue May 30, 2017 9:36 pm

deepanshsinghal wrote:I tried with openemv implementation also... but no success


Can you tell me, how do you verify the result? And i will have a try to resolve this problem. I have no terminate application to verify the applet functions. :?
sense and simplicity


Return to “Questions & Answers”

Who is online

Users browsing this forum: No registered users and 2 guests

JavaCard OS : Disclaimer