====== DES Sample Code ====== [[http://javacardos.com/javacardforum/download/file.php?id=542| Download Sample Code ]] [[http://javacardos.com/javacardforum/viewtopic.php?f=31&t=736| Discussion]] /* * @file DESSample.java * @version v1.0 * Package AID: 4A617661436172644F53 * Applet AID: 4A617661436172644F5302 * @brief The ALgorithm of DES Sample Code in JavaCard API Specification * @comment The purpose of this example is only used to show the usage of API functions and there is no practical significance. * @copyright Copyright(C) 2016 JavaCardOS Technologies Co., Ltd. All rights reserved. */ package JavaCardOS.Sample.Algorithm; import javacard.framework.*; import javacard.security.KeyBuilder; import javacard.security.*; import javacardx.crypto.*; public class DESSample extends Applet { private static final byte INS_SET_DES_KEY = (byte)0x20; private static final byte INS_SET_DES_ICV = (byte)0x21; private static final byte INS_DO_DES_CIPHER = (byte)0x22; private byte desKeyLen; private byte[] desKey; private byte[] desICV; private Cipher desEcbCipher; private Cipher desCbcCipher; private Key tempDesKey2; private Key tempDesKey3; public DESSample() { desKey = new byte[32]; desICV = new byte[8]; desKeyLen = 0; //Create a DES ECB/CBS object instance of the DES algorithm. desEcbCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false); desCbcCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false); //Creates uninitialized TDES cryptographic keys for signature and cipher algorithms. tempDesKey3 = KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_DES3_3KEY, false); JCSystem.requestObjectDeletion(); } public static void install(byte[] bArray, short bOffset, byte bLength) { new DESSample().register(bArray, (short) (bOffset + 1), bArray[bOffset]); } public void process(APDU apdu) { if (selectingApplet()) { return; } byte[] buf = apdu.getBuffer(); short len = apdu.setIncomingAndReceive(); switch (buf[ISO7816.OFFSET_INS]) { case INS_SET_DES_KEY: //SET_DES_KEY setDesKey(apdu, len); break; case INS_SET_DES_ICV: //SET_DES_ICV setDesICV(apdu, len); break; case INS_DO_DES_CIPHER: //DO_DES_CIPHER doDesCipher(apdu, len); break; default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } } //Set the key of TDES Encrypt/Decrypt private void setDesKey(APDU apdu, short len) { byte[] buffer = apdu.getBuffer(); byte keyLen = 0; switch (buffer[ISO7816.OFFSET_P1]) { case (byte)0x01: // The length of key is 16 bytes if (len != 16) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } keyLen = (byte)16; break; case (byte)0x02: if (len != 24) // The length of key is 24 bytes { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } keyLen = (byte)24; break; default: ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); break; } JCSystem.beginTransaction(); //Copy the incoming TDES Key value to the global variable 'desKey' Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, desKey, (short)0, len); desKeyLen = keyLen; JCSystem.commitTransaction(); } //Set DES ICV, ICV is the initial vector private void setDesICV(APDU apdu, short len) { if (len != 8) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } //Copy the incoming ICV value to the global variable 'desICV' Util.arrayCopy(apdu.getBuffer(), ISO7816.OFFSET_CDATA, desICV, (short)0, (short)8); } //Get the key that set into the 'desKey' in setDesKey() function, and return the DESKey object. //The plain text length of input key data is 8 bytes for DES, 16 bytes for 2-key triple DES and 24 bytes for 3-key triple DES. private Key getDesKey() { Key tempDesKey = null; switch (desKeyLen) { case (byte)16: tempDesKey = tempDesKey2; break; case (byte)24: tempDesKey = tempDesKey3; break; default: ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); break; } //Set the 'desKey' key data value into the internal representation ((DESKey)tempDesKey).setKey(desKey, (short)0); return tempDesKey; } //DES algorithm encrypt and decrypt private void doDesCipher(APDU apdu, short len) { //In Des algorithm the byte length to be encrypted/decrypted must be a multiple of 8 if (len <= 0 || len % 8 != 0) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } byte[] buffer = apdu.getBuffer(); Key key = getDesKey(); byte mode = buffer[ISO7816.OFFSET_P1] == (byte)0x00 ? Cipher.MODE_ENCRYPT : Cipher.MODE_DECRYPT; Cipher cipher = buffer[ISO7816.OFFSET_P2] == (byte)0x00 ? desEcbCipher : desCbcCipher; //Initializes the 'cipher' object with the appropriate Key and algorithm specific parameters. //DES algorithms in CBC mode expect a 8-byte parameter value for the initial vector(IV) if (cipher == desCbcCipher) { cipher.init(key, mode, desICV, (short)0, (short)8); } else { cipher.init(key, mode); } //This method must be invoked to complete a cipher operation. Generates encrypted/decrypted output from all/last input data. cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0); apdu.setOutgoingAndSend((short)0, len); } } The test script of DES is as follows: Download Test Script //The test script of DES //Copyright(C) JavaCardOS Technologies Co., Ltd. All rights reserved. //DES Select Applet 00A404000B4A617661436172644F530200; //TDES-CBC Encrypt //set Key 802002001810E976F89D2561A110E976F89D2561A110E976F89D2561A1; //set IV 802100000830E91111589CB432; //CBC Encrypt //expect:3C9C65A69E27BB0B9000 802200010841E47B250441B4CA; //set Key 80200200181FC43761574676981FC43761574676981FC4376157467698; //set IV 8021000008B7B2CE02BFAEDFFF; //CBC Encrypt //expect:A22511500C94F0B3AEA0B25F30CB3F839000 8022000110C2EF8033D8D87B5A57C7AE00E6D0AEF5; //3DEC-CBC Decrypt // set Key 80200200187CB5F79EC8897C387CB5F79EC8897C387CB5F79EC8897C38; //set IV 8021000008A25B018DA1AC6A81; //CBC Decrypt //expect:7F34DBAA1FA3848D8EF325ED4E291F13D9C6C8A8B10EA21C0ACADF9D8642413B9000 8022010120FD9B328DCC0C86DD36FB6A559E94720D4C4C47D4620C4274119139370C1399A9; //3DES-ECB Encrypt //set Key 80200200184CDA838AA42AD02A4CDA838AA42AD02A4CDA838AA42AD02A; //ECB Encrypt //expect:0DEAC65F762C8A819000 8022000008869300AFABCF8C8B; // set Key 8020020018f4d04345e01c68f4f4d04345e01c68f4f4d04345e01c68f4; //EBC Decrypt //expect:86104538adf59381f490f78eff7c32f137d3085e2a9d7780de94cecaa6c0f7b29000 8022010020251b7467867536fa8590da6b5bd30266536de9c72c32ec0abfa74a02e25828ce;