SSE4E GPError GPSystem ByteString ByteBuffer TLV TLVList Card Atr Key Crypto Application GPApplication GPSecDomain ASN1 CardFile IsoSecureChannel ApplFactory GPXML JsScript CardSim X509 CRL KeyStore CMSSignedData CMSGenerator XMLSignature OCSPQuery LDAP SOAP URLConnection PKCS11Provider PKCS11Session PKCS11Object OutlineNode OpenSCDP |
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
Constants
Properties
ConstructorPrototypeIsoSecureChannel(Crypto crypto) IsoSecureChannel(Crypto crypto, Number policy) DescriptionInstantiate 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
Exceptions
Examplevar crypto = new Crypto(); var isc = new IsoSecureChannel(crypto); setEncKey()Prototypevoid setEncKey(Key kenc) DescriptionSet the key to be used for encryption of command-APDUs and decryption of response-APDUs. Arguments
Return
Exceptions
Examplevar kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX); var kenc = new Key(); kenc.setComponent(Key.DES, kencval); isc.setEncKey(kenc); setMacKey()Prototypevoid setMacKey(Key kmac) DescriptionSet the key to be used for calculating and verifying the message authentication code (MAC). Arguments
Return
Exceptions
Examplevar kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", HEX); var kmac = new Key(); kmac.setComponent(Key.DES, kmacval); isc.setMacKey(kmac); setMACSendSequenceCounter()Prototypevoid setMACSendSequencCounter(ByteString ssc) DescriptionSet 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
Return
Exceptions
Examplevar ssc = new ByteString("FFFFFFFFFFFFFFF6", HEX); isc.setMACSendSequenceCounter(ssc); setEncryptionSendSequenceCounter()Prototypevoid setEncryptionSendSequencCounter(ByteString ssc) DescriptionSet 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
Return
Exceptions
Example// see setMACSendSequenceCounter() for an example. setIV()Prototypevoid setIV(ByteString iv) DescriptionSet the initial vector for DES/CBC encryption and decryption. The default value used without using this method is '0000000000000000'. Arguments
Return
Exceptions
Examplevar iv = new ByteString("1111111111111111", HEX); isc.setIV(iv); setMacLength()Prototypevoid setMacLength(Number maclen) DescriptionSet 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
Return
Exceptions
Exampleisc.setMacLength(8); wrap()PrototypeByteString wrap(ByteString apduToWrap, Number usageQualifier) DescriptionWrap 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
Return
Exceptions
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("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C102030800000000000000000000000871101", 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("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70C1120308000000000000000000000008510", 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()PrototypeByteString unwrap(ByteString apduToUnwrap, Number usageQualifier) DescriptionUnwrap 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
Return
Exceptions
Examplevar isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX); var kenc = new Key(); kenc.setComponent(Key.DES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", 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()Prototypevoid setCRT(ByteString crt) DescriptionSet 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
Return
Exceptions
Examplevar isc = new IsoSecureChannel(crypto); var kencval = new ByteString("7CA110454A1A6E570131D9619DC1376E4A1A6E570131D961", HEX); var kenc = new Key(); kenc.setComponent(Key.DES, kencval); isc.setEncKey(kenc); var kmacval = new ByteString("0131D9619DC1376E7CA110454A1A6E579DC1376E7CA11045", 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("FFFFFFFFFFFFFFFF0C1020308000000081044142434497018080000000000000", 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 - 2010 CardContact Software & System Consulting, Minden, Germany |