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
This is an old revision of the document!
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;