JavacardOS will not accept order any more, please contact our partner Feitian online Store:
https://ftsafe.en.alibaba.com/index.html
https://ftsafe.en.alibaba.com/index.html
3DES
-
- Posts: 44
- Joined: Thu Apr 06, 2017 8:01 am
- Points :460
- Contact:
3DES
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
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
- UNKNwYSHSA
- Posts: 630
- Joined: Thu May 21, 2015 4:05 am
- Points :3055
- Contact:
Re: 3DES
Please make sure first that your key is
not
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
- UNKNwYSHSA
- Posts: 630
- Joined: Thu May 21, 2015 4:05 am
- Points :3055
- Contact:
Re: 3DES
And follow the EMV specification, it said:
But your implementation is:
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
-
- Posts: 44
- Joined: Thu Apr 06, 2017 8:01 am
- Points :460
- Contact:
Re: 3DES
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
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
- UNKNwYSHSA
- Posts: 630
- Joined: Thu May 21, 2015 4:05 am
- Points :3055
- Contact:
-
- Posts: 44
- Joined: Thu Apr 06, 2017 8:01 am
- Points :460
- Contact:
Re: 3DES
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
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
Re: 3DES
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);
}
- UNKNwYSHSA
- Posts: 630
- Joined: Thu May 21, 2015 4:05 am
- Points :3055
- Contact:
Re: 3DES
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
-
- Posts: 44
- Joined: Thu Apr 06, 2017 8:01 am
- Points :460
- Contact:
Re: 3DES
I tried with openemv implementation also... but no success
- UNKNwYSHSA
- Posts: 630
- Joined: Thu May 21, 2015 4:05 am
- Points :3055
- Contact:
Re: 3DES
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
Who is online
Users browsing this forum: No registered users and 45 guests