IsoSecureChannel - Reference Documentation
Class to support a secure communication channel via secure messaging according to ISO 7816-4 and CWA 14890 (eSign-K).
This implementation supports 3-TDES and AES keys for MAC and encryption.
For 3-TDES keys the MAC algorithm is ISO 9797 Algorithm 3 (Retail-MAC or EMV-MAC), the encryption algorithm is DES-CBC.
For AES keys the MAC algorithm is AES-CMAC and the encryption algorithm is AES-CBC.
Three policies for handling send sequence counters are available:
SSC_DEFAULT_POLICY
If a send sequence counter for MAC is defined, then it is incremented for each new MAC and prepended to the protected message.
If a send sequence counter for encryption is defined, then it is incremented for each new cryptogram and used as initialisation vector.
SSC_SYNC_POLICY
If a send sequence counter for MAC is defined, then it is incremented for each new MAC and prepended to the protected message.
The same send sequence counter is used as initialisation vector for encrypted data (EAC 2.0 with 3-TDES).
SSC_SYNC_ENC_POLICY
If a send sequence counter for MAC is defined, then it is incremented for each new MAC and prepended to the protected message.
The same send sequence counter is encrypted and the result is used as initialisation vector for encrypted data. This has the same effect as prepending the message to be encrypted with the SSC (EAC 2.0 with AES).
Index of Methods
- IsoSecureChannel() constructor
- setEncKey()
- setMacKey()
- setMACSendSequenceCounter()
- setEncryptionSendSequenceCounter()
- setIV()
- setMacLength()
- wrap()
- unwrap()
- setCRT()
Constants
Type | Name | Description |
---|---|---|
Number | SSC_DEFAULT_POLICY | Default SSC policy |
Number | SSC_SYNC_POLICY | Same send sequence counter for MAC and encryption |
Number | SSC_SYNC_ENC_POLICY | Same send sequence counter for MAC and encrypted SSC for encryption |
Properties
Type | Name | Description |
---|---|---|
ByteString | encryptionSendSequenceCounter | Current value of send sequence counter for encryption |
ByteString | MACSendSequenceCounter | Current value of send sequence counter for MAC calculation |
Constructor
Prototype
IsoSecureChannel(Crypto crypto)
IsoSecureChannel(Crypto crypto, Number policy)
Description
Instantiate an IsoSecureChannel object that allows to wrap command-APDUs and unwrap response-APDUs using secure messaging as defined in ISO 7816-4 and CWA 14890 (eSign-K).
The object instantiated with this constructor must be further initialized using the setEncKey(), setMacKey() and setMACSendSequenceCounter() methods.
The class only supports 3DES/CBC and RetailMAC as cryptographic algorithms using a double or triple length DES key.
Objects of this class can be used in Card.setCredential() and CardFile.setCredential() as credential object.
Arguments
Type | Name | Description |
---|---|---|
Crypto
|
crypto | Crypto object to use for cryptographic operations |
Number
|
policy | One of SSC_DEFAULT_POLICY, SSC_SYNC_POLICY or SSC_SYNC_ENC_POLICY |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
Example
var crypto = new Crypto(); var isc = new IsoSecureChannel(crypto);
setEncKey()
Prototype
void setEncKey(Key kenc)
Description
Set the key to be used for encryption of command-APDUs and decryption of response-APDUs.
Arguments
Type | Name | Description |
---|---|---|
Key
|
kenc | The encryption key |
Return
void
|
The method does not return a value |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | Argument must be of type Key |
Example
var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX); var kenc = new Key(); kenc.setComponent(Key.DES, kencval); isc.setEncKey(kenc);
setMacKey()
Prototype
void setMacKey(Key kmac)
Description
Set the key to be used for calculating and verifying the message authentication code (MAC).
Arguments
Type | Name | Description |
---|---|---|
Key
|
kmac | The message authentication key |
Return
void
|
The method does not return a value |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | Argument must be of type Key |
Example
var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", HEX); var kmac = new Key(); kmac.setComponent(Key.DES, kmacval); isc.setMacKey(kmac);
setMACSendSequenceCounter()
Prototype
void setMACSendSequencCounter(ByteString ssc)
Description
Set the initial value for the send sequence counter using for message authentication codes.
If a send sequence counter is defined, then this counter will be incremented for each command or response APDU that contains a MAC.
The deprecated setSendSequenceCounter() maps to this method.
Arguments
Type | Name | Description |
---|---|---|
ByteString
|
ssc | The initial value for the send sequence counter or null |
Return
void
|
The method does not return a value |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | The argument must be of type ByteString |
Example
var ssc = new ByteString("FFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc);
setEncryptionSendSequenceCounter()
Prototype
void setEncryptionSendSequencCounter(ByteString ssc)
Description
Set the initial value for the send sequence counter used for encryption.
If a send sequence counter is defined, then this counter will be incremented for each command or response APDU that contains encrypted contents.
Arguments
Type | Name | Description |
---|---|---|
ByteString
|
ssc | The initial value for the send sequence counter or null |
Return
void
|
The method does not return a value |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | The argument must be of type ByteString |
Example
// see setMACSendSequenceCounter() for an example.
setIV()
Prototype
void setIV(ByteString iv)
Description
Set the initial vector for DES/CBC encryption and decryption.
The default value used without using this method is '0000000000000000'.
Arguments
Type | Name | Description |
---|---|---|
ByteString
|
iv | The initial vector or null |
Return
void
|
The method does not return a value |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | The argument must be of type ByteString |
Example
var iv = new ByteString("1111111111111111", HEX); isc.setIV(iv);
setMacLength()
Prototype
void setMacLength(Number maclen)
Description
Set the length of the message authentication code as number of most significant bytes from the last cryptographic operation.
The default value is 8 byte.
Arguments
Type | Name | Description |
---|---|---|
Number
|
maclen | The number of leftmost / most significant bytes to be used as MAC |
Return
void
|
The method does not return a value |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | The argument must be of type ByteString |
Example
isc.setMacLength(8);
wrap()
Prototype
ByteString wrap(ByteString apduToWrap, Number usageQualifier)
Description
Wrap a command-APDU with a secure messaging block.
Depending on the usageQualifier, no transformation (0), an encryption (Card.CENC), a MAC calculation (Card.CPRO) or both (Card.CENC|Card.CPRO) is performed.
The APDU is transformed as defined in ISO 7816-4 and CWA 14890 (eSignK).
Arguments
Type | Name | Description |
---|---|---|
ByteString
|
apduToWrap | The command APDU to wrap |
Number
|
usageQualifier | A bitwise combination of Card.CPRO and Card.CENC. |
Return
ByteString
|
Wrapped command APDU |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | The type of the argument passed to the method is invalid |
GPError | GPError.INVALID_MECH | The cryptographic operating is not supported by the selected crypto service |
Example
// #### Using 3-TDES with short APDUs #### var ssc = new ByteString("FFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); // Case 1 Command APDU CLA=00 INS=10 P1=20 P2=30 var apdu = new ByteString("00102030", HEX); // Case 1 Plain -> CLA'|INS|P1|P2 var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "08102030"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF6"); // Case 1 CENC -> CLA'|INS|P1|P2 var r = isc.wrap(apdu, Card.CENC); // Test result assert(r.toString(16) == "08102030"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF6"); // Case 1 CPRO -> CLA'|INS|P1|P2|Lc'|TLmac var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C1020300A8E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFF70C10203080000000", HEX)); exp = exp.concat(mac); assert(r.equals(exp)); // Case 1 CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLmac var r = isc.wrap(apdu, Card.CENC|Card.CPRO); // Test result var exp = new ByteString("0C1020300A8E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFF80C10203080000000", HEX)); exp = exp.concat(mac); assert(r.equals(exp)); // Case 2s Command APDU CLA=00 INS=10 P1=20 P2=30 Le=80 var apdu = new ByteString("0010203080", HEX); // Case 2s Plain -> CLA'|INS|P1|P2|Lc'|TLle|00 var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "081020300396018000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8"); // Case 2s CENC -> CLA'|INS|P1|P2|Lc'|TLle|00 var r = isc.wrap(apdu, Card.CENC); // Test result assert(r.toString(16) == "081020300396018000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8"); // Case 2s CPRO -> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C1020300D9701808E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFF90C102030800000009701808000000000", HEX)); exp = exp.concat(mac).concat(new ByteString("00", HEX)); assert(r.equals(exp)); // Case 2s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CPRO|Card.CENC); // Test result var exp = new ByteString("0C1020300D9701808E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFFA0C102030800000009701808000000000", HEX)); exp = exp.concat(mac).concat(new ByteString("00", HEX)); assert(r.equals(exp)); // Case 3s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 var apdu = new ByteString("001020300441424344", HEX); // Case 3s Plain -> CLA'|INS|P1|P2|Lc'|TLplain var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "0810203006800441424344"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFA"); // Case 3s CENC -> CLA'|INS|P1|P2|Lc'|TLenc var r = isc.wrap(apdu, Card.CENC); // Test result var exp = new ByteString("081020300B860901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); assert(r.equals(exp)); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFB"); // Case 3s CPRO -> CLA'|INS|P1|P2|Lc'|TLplain|TLmac var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C102030108104414243448E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFFC0C102030800000008104414243448000", HEX)); exp = exp.concat(mac); assert(r.equals(exp)); // Case 3s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLmac var r = isc.wrap(apdu, Card.CENC|Card.CPRO); // Test result var exp = new ByteString("0C10203015870901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("8E08", HEX)); var macinp = new ByteString("FFFFFFFFFFFFFFFD0C10203080000000870901", HEX); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("8000000000", HEX)); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp); exp = exp.concat(mac); assert(r.equals(exp)); // Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80 var apdu = new ByteString("00102030044142434480", HEX); // Case 4s Plain -> CLA'|INS|P1|P2|Lc'|TLplain|TLle|00 var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "081020300980044142434496018000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFD"); // Case 4s CENC -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|00 var r = isc.wrap(apdu, Card.CENC); // Test result var exp = new ByteString("081020300E860901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("96018000", HEX)); assert(r.equals(exp)); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFE"); // Case 4s CPRO -> CLA'|INS|P1|P2|Lc'|TLplain|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C102030138104414243449701808E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFFF0C1020308000000081044142434497018080000000000000", HEX)); exp = exp.concat(mac).concat(new ByteString("00", HEX)); assert(r.equals(exp)); // Case 4s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CENC|Card.CPRO); // Test result var exp = new ByteString("0C10203018870901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("9701808E08", HEX)); var macinp = new ByteString("00000000000000000C10203080000000870901", HEX); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("970180", HEX)); macinp = macinp.concat(new ByteString("8000", HEX)); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp); exp = exp.concat(mac).concat(new ByteString("00", HEX)); assert(r.equals(exp)); //#### Using 3-TDES with extended APDUs #### var ssc = new ByteString("FFFFFFFFFFFFFFF8", HEX); isc.setMACSendSequenceCounter(ssc); //Case 2e Command APDU CLA=00 INS=10 P1=20 P2=30 Le=000180 var apdu = new ByteString("00102030000180", HEX); // Case 2e Plain -> CLA'|INS|P1|P2|Lc'|TLle|00 var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "08102030000004960201800000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8"); // Case 2e CENC -> CLA'|INS|P1|P2|Lc'|TLle|00 var r = isc.wrap(apdu, Card.CENC); // Test result assert(r.toString(16) == "08102030000004960201800000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8"); // Case 2e CPRO -> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C10203000000E970201808E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFF90C102030800000009702018080000000", HEX)); exp = exp.concat(mac).concat(new ByteString("0000", HEX)); // print("Expected " + exp); // print("Received " + r); assert(r.equals(exp)); // Case 2e CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CPRO|Card.CENC); // Test result var exp = new ByteString("0C10203000000E970201808E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFFA0C102030800000009702018080000000", HEX)); exp = exp.concat(mac).concat(new ByteString("0000", HEX)); assert(r.equals(exp)); //Case 3e Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 var apdu = new ByteString("0010203000000441424344", HEX); // Case 3e Plain -> CLA'|INS|P1|P2|Lc'|TLplain var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "08102030000006800441424344"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFA"); // Case 3e CENC -> CLA'|INS|P1|P2|Lc'|TLenc var r = isc.wrap(apdu, Card.CENC); // Test result var exp = new ByteString("0810203000000B860901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); assert(r.equals(exp)); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFB"); // Case 3e CPRO -> CLA'|INS|P1|P2|Lc'|TLplain|TLmac var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C1020300000108104414243448E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFFC0C102030800000008104414243448000", HEX)); exp = exp.concat(mac); assert(r.equals(exp)); // Case 3e CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLmac var r = isc.wrap(apdu, Card.CENC|Card.CPRO); // Test result var exp = new ByteString("0C102030000015870901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("8E08", HEX)); var macinp = new ByteString("FFFFFFFFFFFFFFFD0C10203080000000870901", HEX); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("8000000000", HEX)); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp); exp = exp.concat(mac); assert(r.equals(exp)); //Case 4e Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=000004 Data=41424344 Le=000180 var apdu = new ByteString("00102030000004414243440180", HEX); // Case 4e Plain -> CLA'|INS|P1|P2|Lc'|TLplain|TLle|00 var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "0810203000000A800441424344960201800000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFD"); // Case 4e CENC -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|00 var r = isc.wrap(apdu, Card.CENC); // Test result var exp = new ByteString("0810203000000F860901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("960201800000", HEX)); assert(r.equals(exp)); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFE"); // Case 4e CPRO -> CLA'|INS|P1|P2|Lc'|TLplain|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C102030000014810441424344970201808E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFFF0C1020308000000081044142434497020180800000000000", HEX)); exp = exp.concat(mac).concat(new ByteString("0000", HEX)); assert(r.equals(exp)); // Case 4e CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CENC|Card.CPRO); // Test result var exp = new ByteString("0C102030000019870901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString("4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("970201808E08", HEX)); var macinp = new ByteString("00000000000000000C10203080000000870901", HEX); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("97020180", HEX)); macinp = macinp.concat(new ByteString("80", HEX)); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp); exp = exp.concat(mac).concat(new ByteString("0000", HEX)); assert(r.equals(exp)); // Special case: No MAC and no ENC var ssc = new ByteString("FFFFFFFFFFFFFFF8", HEX); isc.setMACSendSequenceCounter(ssc); //Case 2e Command APDU CLA=00 INS=10 P1=20 P2=30 Le=000180 var apdu = new ByteString("00102030000000", HEX); // Case 2e Plain -> CLA'|INS|P1|P2|Lc'|TLle|00 var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "08102030000004960200000000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFF8"); // Using AES with SSC default policy var isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var iv = new ByteString("11111111111111111111111111111111", HEX); isc.setIV(iv); //Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80 var apdu = new ByteString("00102030044142434480", HEX); //Case 4s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CENC|Card.CPRO); //Test result var exp = new ByteString("0C10203020871101", HEX); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString("41424344800000000000000000000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("9701808E08", HEX)); var macinp = new ByteString( "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C" + "102030800000000000000000000000871101", HEX); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("970180", HEX)); macinp = macinp.concat(new ByteString("80000000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX)); // print("Expected " + exp); // print("Received " + r); assert(r.equals(exp)); // Using AES with SSC_SYNC_POLICY var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_POLICY); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); var iv = new ByteString("00000000000000000000000000000000", HEX); //Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80 var apdu = new ByteString("00102030044142434480", HEX); //Case 4s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CENC|Card.CPRO); //Test result var exp = new ByteString("0C10203020871101", HEX); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "41424344800000000000000000000000", HEX), nextssc); exp = exp.concat(enc); exp = exp.concat(new ByteString("9701808E08", HEX)); var macinp = nextssc.concat(new ByteString( "0C102030800000000000000000000000871101", HEX)); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("970180", HEX)); macinp = macinp.concat(new ByteString("80000000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX)); // print("Expected " + exp); // print("Received " + r); assert(r.equals(exp)); //Using AES with SSC_SYNC_POLICY var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_ENC_POLICY); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); var iv = new ByteString("00000000000000000000000000000000", HEX); //Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80 var apdu = new ByteString("00102030044142434480", HEX); //Case 4s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CENC|Card.CPRO); //Test result var exp = new ByteString("0C10203020871101", HEX); var niv = crypto.encrypt(kenc, Crypto.AES_CBC, nextssc, iv); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "41424344800000000000000000000000", HEX), niv); exp = exp.concat(enc); exp = exp.concat(new ByteString("9701808E08", HEX)); var macinp = nextssc.concat(new ByteString( "0C102030800000000000000000000000871101", HEX)); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("970180", HEX)); macinp = macinp.concat(new ByteString("80000000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX)); // print("Expected " + exp); // print("Received " + r); assert(r.equals(exp)); //Using AES with SSC default policy and odd instruction byte var isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var iv = new ByteString("11111111111111111111111111111111", HEX); isc.setIV(iv); //Case 4s Command APDU CLA=00 INS=11 P1=20 P2=30 Lc=04 Data=41424344 Le=80 var apdu = new ByteString("00112030048002123480", HEX); //Case 4s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CENC|Card.CPRO); //Test result var exp = new ByteString("0C1120301F8510", HEX); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "80021234800000000000000000000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("9701808E08", HEX)); var macinp = new ByteString( "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C" + "1120308000000000000000000000008510", HEX); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("970180", HEX)); macinp = macinp.concat(new ByteString("8000000000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); exp = exp.concat(mac.left(8)).concat(new ByteString("00", HEX)); print("Expected " + exp); print("Received " + r); assert(r.equals(exp));
unwrap()
Prototype
ByteString unwrap(ByteString apduToUnwrap, Number usageQualifier)
Description
Unwrap a response-APDU from a secure messaging block and check the encryption and MAC.
Depending on the usageQualifier, no transformation (0), an decryption (Card.RENC), a MAC verification (Card.RPRO) or both (Card.RENC|Card.RPRO) is performed.
The APDU is transformed as defined in ISO 7816-4 and CWA 14890 (eSignK).
Arguments
Type | Name | Description |
---|---|---|
ByteString
|
apduToUnwrap | The response APDU to unwrap |
Number
|
usageQualifier | A bitwise combination of Card.RPRO and Card.RENC. |
Return
ByteString
|
Unwrapped response APDU |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | The type of the argument passed to the method is invalid |
GPError | GPError.INVALID_MECH | The cryptographic operating is not supported by the selected crypto service |
GPError | GPError.CRYPTO_FAILED | Either the MAC verification or data block decryption failed |
Example
var isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D961" + "9DC1376E4A1A6E570131D961", HEX); var kenc = new Key(); kenc.setComponent(Key.DES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA11045" + "4A1A6E579DC1376E7CA11045", HEX); var kmac = new Key(); kmac.setComponent(Key.DES, kmacval); isc.setMacKey(kmac); var iv = new ByteString("1111111111111111", HEX); isc.setIV(iv); var ssc = new ByteString("0000000000000000", HEX); isc.setMACSendSequenceCounter(ssc); // SW1/SW2 only, Plain -> SW1/SW2 // Prepare response from ICC var apdu = new ByteString("9000", HEX); var r = isc.unwrap(apdu, 0); // Test result assert(r.toString(16) == "9000"); // SW1/SW2 only, RPRO -> TLmac|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("8E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "00000000000000018000000000000000", HEX)); apdu = apdu.concat(mac); apdu = apdu.concat(new ByteString("9000", HEX)); var r = isc.unwrap(apdu, Card.RPRO); // Test result assert(r.toString(16) == "9000"); // SW1/SW2 only, RPRO with SW1SW2 -> TLsw|TLmac|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("990212348E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "00000000000000029902123480000000", HEX)); apdu = apdu.concat(mac); apdu = apdu.concat(new ByteString("9000", HEX)); var r = isc.unwrap(apdu, Card.RPRO); // Test result assert(r.toString(16) == "1234"); // Data | SW1/SW2, Plain -> TLplain|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("8004414243449000", HEX); var r = isc.unwrap(apdu, 0); // Test result assert(r.toString(16) == "414243449000"); // Data | SW1/SW2, RENC -> TLenc|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("860901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString( "4142434480000000", HEX), iv); apdu = apdu.concat(enc); apdu = apdu.concat(new ByteString("9000", HEX)); var r = isc.unwrap(apdu, Card.RENC); // Test result assert(r.toString(16) == "414243449000"); assert(isc.sendSequenceCounter.toString(16) == "0000000000000003"); // Data | SW1/SW2, RPRO -> TLplain|TLmac|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("810441424344", HEX); var macinp = new ByteString("0000000000000004", HEX); macinp = macinp.concat(apdu); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2)); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac); apdu = apdu.concat(new ByteString("9000", HEX)); var r = isc.unwrap(apdu, Card.RPRO); // Test result assert(r.toString(16) == "414243449000"); // Data | SW1/SW2, RPRO with SW1/SW2 -> TLplain|TLsw|TLmac|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("81044142434499021234", HEX); var macinp = new ByteString("0000000000000005", HEX); macinp = macinp.concat(apdu); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2)); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac); apdu = apdu.concat(new ByteString("9000", HEX)); var r = isc.unwrap(apdu, Card.RPRO); // Test result assert(r.toString(16) == "414243441234"); // Data | SW1/SW2, RENC|RPRO -> TLenc|TLmac|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("870901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString( "4142434480000000", HEX), iv); apdu = apdu.concat(enc); var macinp = new ByteString("0000000000000006", HEX); macinp = macinp.concat(apdu); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2)); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac); apdu = apdu.concat(new ByteString("9000", HEX)); var r = isc.unwrap(apdu, Card.RPRO|Card.RENC); // Test result assert(r.toString(16) == "414243449000"); // Data | SW1/SW2, RENC|RPRO with SW1/SW2 -> TLenc|TLsw|TLmac|SW1/SW2 // Prepare response from ICC var apdu = new ByteString("870901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString( "4142434480000000", HEX), iv); apdu = apdu.concat(enc); apdu = apdu.concat(new ByteString("99021234", HEX)); var macinp = new ByteString("0000000000000007", HEX); macinp = macinp.concat(apdu); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp.pad(Crypto.ISO9797_METHOD_2)); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac); apdu = apdu.concat(new ByteString("9000", HEX)); var r = isc.unwrap(apdu, Card.RPRO|Card.RENC); // Test result assert(r.toString(16) == "414243441234"); // Using AES with default policy var isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var iv = new ByteString("11111111111111111111111111111111", HEX); isc.setIV(iv); //Data | SW1/SW2, RENC|RPRO with SW1/SW2 -> TLenc|TLsw|TLmac|SW1/SW2 //Prepare response from ICC var apdu = new ByteString("871101", HEX); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "41424344800000000000000000000000", HEX), iv); apdu = apdu.concat(enc); apdu = apdu.concat(new ByteString("99021234", HEX)); var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); macinp = macinp.concat(apdu); macinp = macinp.concat(new ByteString("800000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac.left(8)); apdu = apdu.concat(new ByteString("9000", HEX)); // print("APDU " + apdu); var r = isc.unwrap(apdu, Card.RPRO|Card.RENC); // print("Received " + r); //Test result assert(r.toString(16) == "414243441234"); //Using AES with SSC_SYNC_POLICY var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_POLICY); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); var iv = new ByteString("00000000000000000000000000000000", HEX); //Data | SW1/SW2, RENC|RPRO with SW1/SW2 -> TLenc|TLsw|TLmac|SW1/SW2 //Prepare response from ICC var apdu = new ByteString("871101", HEX); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "41424344800000000000000000000000", HEX), nextssc); apdu = apdu.concat(enc); apdu = apdu.concat(new ByteString("99021234", HEX)); var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); macinp = macinp.concat(apdu); macinp = macinp.concat(new ByteString("800000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac.left(8)); apdu = apdu.concat(new ByteString("9000", HEX)); // print("APDU " + apdu); var r = isc.unwrap(apdu, Card.RPRO|Card.RENC); // print("Received " + r); //Test result assert(r.toString(16) == "414243441234"); //Using AES with SSC_SYNC_ENC_POLICY var isc = new IsoSecureChannel(crypto, IsoSecureChannel.SSC_SYNC_ENC_POLICY); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var nextssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); var iv = new ByteString("00000000000000000000000000000000", HEX); //Data | SW1/SW2, RENC|RPRO with SW1/SW2 -> TLenc|TLsw|TLmac|SW1/SW2 //Prepare response from ICC var apdu = new ByteString("871101", HEX); var niv = crypto.encrypt(kenc, Crypto.AES_CBC, nextssc, iv); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "41424344800000000000000000000000", HEX), niv); apdu = apdu.concat(enc); apdu = apdu.concat(new ByteString("99021234", HEX)); var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); macinp = macinp.concat(apdu); macinp = macinp.concat(new ByteString("800000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac.left(8)); apdu = apdu.concat(new ByteString("9000", HEX)); // print("APDU " + apdu); var r = isc.unwrap(apdu, Card.RPRO|Card.RENC); // print("Received " + r); //Test result assert(r.toString(16) == "414243441234"); //Using AES with default policy and TLV data var isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var iv = new ByteString("11111111111111111111111111111111", HEX); isc.setIV(iv); //Data | SW1/SW2, RENC|RPRO with SW1/SW2 -> TLenc|TLsw|TLmac|SW1/SW2 //Prepare response from ICC var apdu = new ByteString("8510", HEX); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "80021234800000000000000000000000", HEX), iv); apdu = apdu.concat(enc); apdu = apdu.concat(new ByteString("99021234", HEX)); var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); macinp = macinp.concat(apdu); macinp = macinp.concat(new ByteString("80000000000000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac.left(8)); apdu = apdu.concat(new ByteString("9000", HEX)); print("APDU " + apdu); var r = isc.unwrap(apdu, Card.RPRO|Card.RENC); print("Received " + r); //Test result assert(r.toString(16) == "800212341234"); //Using AES with default policy and plain data var isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E", HEX); var kenc = new Key(); kenc.setComponent(Key.AES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E57", HEX); var kmac = new Key(); kmac.setComponent(Key.AES, kmacval); isc.setMacKey(kmac); var ssc = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); var iv = new ByteString("11111111111111111111111111111111", HEX); isc.setIV(iv); //Data | SW1/SW2, RENC|RPRO with SW1/SW2 -> TLenc|TLsw|TLmac|SW1/SW2 //Prepare response from ICC var apdu = new ByteString("B304", HEX); var enc = crypto.encrypt(kenc, Crypto.AES_CBC, new ByteString( "80021234800000000000000000000000", HEX), iv); apdu = apdu.concat(new ByteString("80021234", HEX)); apdu = apdu.concat(new ByteString("99021234", HEX)); var macinp = new ByteString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7", HEX); macinp = macinp.concat(apdu); macinp = macinp.concat(new ByteString("800000000000", HEX)); var mac = crypto.sign(kmac, Crypto.AES_CMAC, macinp); apdu = apdu.concat(new ByteString("8E08", HEX)); apdu = apdu.concat(mac.left(8)); apdu = apdu.concat(new ByteString("9000", HEX)); print("APDU " + apdu); var r = isc.unwrap(apdu, Card.RPRO); print("Received " + r); //Test result assert(r.toString(16) == "800212341234");
setCRT()
Prototype
void setCRT(ByteString crt)
Description
Set a cryptographic reference template to be included in the body of the command APDU.
The CRT is included in the MAC if the tag is odd.
Arguments
Type | Name | Description |
---|---|---|
ByteString
|
crt | The cryptographic reference template or null |
Return
void
|
The method does not return a value |
Exceptions
Name | Value | Description |
---|---|---|
GPError | GPError.ARGUMENTS_MISSING | Too few arguments in call |
GPError | GPError.INVALID_ARGUMENTS | Too many arguments in call |
GPError | GPError.INVALID_TYPE | The argument must be of type ByteString |
Example
var isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D961" + "9DC1376E4A1A6E570131D961", HEX); var kenc = new Key(); kenc.setComponent(Key.DES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA11045" + "4A1A6E579DC1376E7CA11045", HEX); var kmac = new Key(); kmac.setComponent(Key.DES, kmacval); isc.setMacKey(kmac); var iv = new ByteString("1111111111111111", HEX); isc.setIV(iv); var crt = new ByteString("B803830103", HEX); isc.setCRT(crt); var ssc = new ByteString("FFFFFFFFFFFFFFFD", HEX); isc.setMACSendSequenceCounter(ssc); //Case 4s Command APDU CLA=00 INS=10 P1=20 P2=30 Lc=04 Data=41424344 Le=80 var apdu = new ByteString("00102030044142434480", HEX); // Case 4s Plain -> CLA'|INS|P1|P2|Lc'|TLplain|TLle|00 var r = isc.wrap(apdu, 0); // Test result assert(r.toString(16) == "081020300EB80383010380044142434496018000"); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFD"); // Case 4s CENC -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|00 var r = isc.wrap(apdu, Card.CENC); // Test result var exp = new ByteString("0810203013B803830103860901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString( "4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("96018000", HEX)); assert(r.equals(exp)); assert(isc.sendSequenceCounter.toString(16) == "FFFFFFFFFFFFFFFE"); // Case 4s CPRO -> CLA'|INS|P1|P2|Lc'|TLplain|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CPRO); // Test result var exp = new ByteString("0C10203018B8038301038104414243449701808E08", HEX); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, new ByteString( "FFFFFFFFFFFFFFFF0C10203080000000" + "81044142434497018080000000000000", HEX)); exp = exp.concat(mac).concat(new ByteString("00", HEX)); assert(r.equals(exp)); var crt = new ByteString("B903830103", HEX); isc.setCRT(crt); // Case 4s CENC|CPRO -> CLA'|INS|P1|P2|Lc'|TLenc|TLle|TLmac|00 var r = isc.wrap(apdu, Card.CENC|Card.CPRO); // Test result var exp = new ByteString("0C1020301DB903830103870901", HEX); var enc = crypto.encrypt(kenc, Crypto.DES_CBC, new ByteString( "4142434480000000", HEX), iv); exp = exp.concat(enc); exp = exp.concat(new ByteString("9701808E08", HEX)); var macinp = new ByteString("00000000000000000C10203080000000B903830103870901", HEX); macinp = macinp.concat(enc); macinp = macinp.concat(new ByteString("970180", HEX)); macinp = macinp.concat(new ByteString("8000000000", HEX)); var mac = crypto.sign(kmac, Crypto.DES_MAC_EMV, macinp); exp = exp.concat(mac).concat(new ByteString("00", HEX)); // print("Expected " + exp); // print("Received " + r); assert(r.equals(exp));
© Copyright 2003 - 2024 CardContact Systems GmbH , Minden, Germany