Smart Card Solution
User Manual
- R502 Manual
JavaCard API Samples
- Algorithm
Java Card Specification
Knowledge Sharing
Smart Card Solution
User Manual
JavaCard API Samples
Java Card Specification
Knowledge Sharing
Download Sample Code Discussion
/* * @file AESSample.java * @version v1.0 * Package AID: 4A617661436172644F53 * Applet AID: 4A617661436172644F5301 * @brief The ALgorithm of AES 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 AESSample extends Applet { private static final byte INS_SET_AES_KEY = (byte)0x10; private static final byte INS_SET_AES_ICV = (byte)0x11; private static final byte INS_DO_AES_CIPHER = (byte)0x12; private byte aesKeyLen; private byte[] aesKey; private byte[] aesICV; private Cipher aesEcbCipher; private Cipher aesCbcCipher; private Key tempAesKey1; private Key tempAesKey2; private Key tempAesKey3; public AESSample() { aesKey = new byte[32]; aesICV = new byte[16]; aesKeyLen = 0; //Create a AES ECB/CBS object instance of the AES algorithm. aesEcbCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false); aesCbcCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); //Create uninitialized cryptographic keys for AES algorithms tempAesKey1 = KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128, false); tempAesKey2 = KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_192, false); tempAesKey3 = KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false); JCSystem.requestObjectDeletion(); } public static void install(byte[] bArray, short bOffset, byte bLength) { new AESSample().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_AES_KEY: // SET_AES_KEY setAesKey(apdu, len); break; case INS_SET_AES_ICV: // SET_AES_ICV setAesICV(apdu, len); break; case INS_DO_AES_CIPHER: //DO_AES_CIPHER doAesCipher(apdu, len); break; default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } } //Set the key of AES Encrypt/Decrypt private void setAesKey(APDU apdu, short len) { byte[] buffer = apdu.getBuffer(); byte keyLen = 0; switch (buffer[ISO7816.OFFSET_P1]) { case (byte)0x01: if (len != 16) // The length of key is 16 bytes { 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; case (byte)0x03: if (len != 32) //The length of key is 32 bytes { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } keyLen = (byte)32; break; default: ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); break; } JCSystem.beginTransaction(); //Copy the incoming AES Key value to the global variable 'aesKey' Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, aesKey, (short)0, len); aesKeyLen = keyLen; JCSystem.commitTransaction(); } //Set AES ICV, ICV is the initial vector private void setAesICV(APDU apdu, short len) { if (len != 16) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } //Copy the incoming ICV value to the global variable 'aesICV' Util.arrayCopy(apdu.getBuffer(), ISO7816.OFFSET_CDATA, aesICV, (short)0, (short)16); } //Sets the Key data, and return the AESKey object. The plaintext length of input key data is 16/24/32 bytes. private Key getAesKey() { Key tempAesKey = null; switch (aesKeyLen) { case (byte)16: tempAesKey = tempAesKey1; break; case (byte)24: tempAesKey = tempAesKey2; break; case (byte)32: tempAesKey = tempAesKey3; break; default: ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); break; } //Set the 'aesKey' key data value into the internal representation ((AESKey)tempAesKey).setKey(aesKey, (short)0); return tempAesKey; } //AES algorithm encrypt and decrypt private void doAesCipher(APDU apdu, short len) { //The byte length to be encrypted/decrypted must be a multiple of 16 if (len <= 0 || len % 16 != 0) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } byte[] buffer = apdu.getBuffer(); Key key = getAesKey(); byte mode = buffer[ISO7816.OFFSET_P1] == (byte)0x00 ? Cipher.MODE_ENCRYPT : Cipher.MODE_DECRYPT; Cipher cipher = buffer[ISO7816.OFFSET_P2] == (byte)0x00 ? aesEcbCipher : aesCbcCipher; //Initializes the 'cipher' object with the appropriate Key and algorithm specific parameters. //AES algorithms in CBC mode expect a 16-byte parameter value for the initial vector(IV) if (cipher == aesCbcCipher) { cipher.init(key, mode, aesICV, (short)0, (short)16); } 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 AES is as follows: Download Test Script
//The test script of AES //Copyright(C) JavaCardOS Technologies Co., Ltd. All rights reserved. //AES Select Applet 00A404000B4A617661436172644F530100; //AES-CBC-256Key //set Key CBC-256 Key Length 80100300209AF0BF0D5D711B9E01C59ED55A015C8AB2D3980010B72CBBBA6E2C91F8ADC604; //set ICV 80110000101C64F340DD29C891B4826509A1FF64E8; //CBC encrypt //expect: E2E6C4AB4D212BB52A292B6368137D3E9000 8012000110C9C9332182CFC8AB48908A972D283582; //AES-CBC-256Key //set Key CBC-256 Key Length 8010030020B57260D2B78CF4B37F315000B7720F796A3E379E6934BB21EEB6449C803F3080; //set ICV 80110000103DCBD02A91EA65D1A2E23A53584AA18A; //CBC decrypt //expect:722D19DB28EF9088CB5FE90784C16A3E336156D29CC4421A398B9C22C63E2F074FADA2B9D95AF7BBE2F246000E20AEB03BAFBE61E2768E92FDF537B29ADA75FF93BDBE4DE2A8F053229B6C5062F8F23D71546689B0F48622B59A6BA30EF151D53B3616B9FEF7AE9A95CE56EABB292E9BAF3B380B915BBFD3AB3238AF99F56E4EED4682D146DA18F92902D1A085EE9E609000 80120101902D5D6440C517EBC13EFC8E2471918C3C34620A287D9C5A84CBD77CDCC134E56614A880F0A897F317F6A523BAB1C9FAAEA9A368B3EF0FA7A73AFAC4FA89745B620A07A2D03B47A8A24FABDF1AD39BD90F91CA4FE2B5C667B42ECE36D657E38481D721D0C8C65094CA11B7CB2C1F30AFC7B482C79D16EA21126FFBDD5973A9EB2C42A014C090DA3FF80370EDD9DCB0073E; //AES-ECB-192Key //set Key 801002001800CF30D306C95D3851B85D11786917BA3C28F8FB0E349524; //ECB encrypt //expect:1108C33BCAB8B43FB229AFDACEBB7859A498371191DEBCD1E40916E2C72835E41B3F536A27D35429FED70B2973862F1C9000 801200003012A4D1CDB906E044B14CC2BC2D6DE6FBAE708568CC248266331195E0ECAEA825DED581F79473A2DE40846DC3003F8CB9; //AES-ECB-192Key //set Key 8010020018DCC25F4F162E0F9B5A2617F6341AF37AA41C3EE4C1F27848; //ECB decrypt //expect:475161225A00DBBD3CDEB304BB5F8FCCD40B266DB5BC164E23F646EB542D6BA988099087CDC1B98749F61D3EDFFAAAA50564D6BBCF49C9F3267E86877521A18C1897DA808BD356E65261B2F208CE065B9000 801201005006E99C9EBAB3D08F7EE117838078B3C7AF419F797B7672E2DBC2850695695878BAC232736FEE0827F3C4A051DE0BF70EA7ECDFF169A6EC53E78491EACD0D879E397A6E97796DB79B17DFC197125A427B;