Our Online Store have the new products: RFID antenna board. Currently it can work with JC10M24R and JCOP4 card chips.
Compared with normal cards, the antenna board module has a smaller size and fixed holes, which is easy to integrate in the IOT(Internet Of Things) project.

AES sample code

Algorithm School

Moderator: UNKNwYSHSA

Valks
Posts: 16
Joined: Wed Oct 12, 2016 11:45 pm
Points :176
Contact:

AES sample code

Post by Valks » Mon Oct 24, 2016 11:24 pm

I am getting started with AES algorithm. Is there any guide or sample code for me to refer to?
thanks very much.

JCaberham
Posts: 26
Joined: Mon Nov 30, 2015 3:02 am
Points :208
Contact:

Re: AES sample code

Post by JCaberham » Tue Oct 25, 2016 2:32 am

FYR

Code: Select all

package crypto_aes;

import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;

public class CryptoAES extends javacard.framework.Applet
{

     //globals
     AESKey aesKey;
     Cipher cipherAES;
     RandomData random;
     static byte a[];
     final short dataOffset = (short) ISO7816.OFFSET_CDATA;

     //constructor
     private CryptoAES (byte bArray[], short bOffset, byte bLength)
     {
          aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
          cipherAES = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
          a = new byte[ (short) 128];
          random.generateData(a, (short)0, (short)128);
          aesKey.setKey(a, (short) 0);
          register(bArray, (short) (bOffset + 1), bArray[bOffset]);
     }

     //install
     public static void install(byte bArray[], short bOffset, byte bLength)
     {
          new CryptoAES (bArray, bOffset, bLength);
     }

     public void process(APDU apdu)
     {
          byte[] buf = apdu.getBuffer();
          if (selectingApplet())
          {
               return;
          }
          if (buf[ISO7816.OFFSET_CLA] != 0) ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
         
          if (buf[ISO7816.OFFSET_INS] != (byte) (0xAA)) ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
         
          switch (buf[ISO7816.OFFSET_P1])
          {
          case (byte) 0x01:
               doAES(apdu);
               return;
          default:
               ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
          }
     }


     private void doAES(APDU apdu)
     {
         
          byte b[] = apdu.getBuffer();
         
          short incomingLength = (short) (apdu.setIncomingAndReceive());
          if (incomingLength != 24) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

          //perform encryption and append results in APDU Buffer a[] automatically
         
          cipherAES.init(aesKey, Cipher.MODE_ENCRYPT);
          cipherAES.doFinal(b, (short) dataOffset, incomingLength, a, (short) (dataOffset + 24));
          cipherAES.init(aesKey, Cipher.MODE_DECRYPT);
          cipherAES.doFinal(b, (short) (dataOffset + 24), incomingLength, a, (short) (dataOffset + 48));

          // Send results
          apdu.setOutgoing();
          apdu.setOutgoingLength((short) 72);
          apdu.sendBytesLong(b, (short) dataOffset, (short) 72);
     }

Valks
Posts: 16
Joined: Wed Oct 12, 2016 11:45 pm
Points :176
Contact:

Re: AES sample code

Post by Valks » Tue Oct 25, 2016 4:37 am

Thanks so much JCaberham.
I will try this code out.

tay00000
Posts: 161
Joined: Tue Sep 27, 2016 10:58 am
Points :2324
Contact:

Re: AES sample code

Post by tay00000 » Mon Oct 31, 2016 10:34 am

Code: Select all

a = new byte[ (short) 128];
random.generateData(a, (short)0, (short)128);


Not sure if you actually need so much bytes since AES is only 16 bytes for 128-bit key and 32 bytes for 256-bit key and in rare circumstances where AES-192 is used that will be 24 bytes. By creating so many bytes, it eats into system resource and when you run generateData for the RNG, it takes even longer (just by a bit more for most cases) to access the RNG's pool of random bytes and in some instances, some card's RNG have a smaller RNG pool and the RNG have to go through a few cycles to fill it's pool of random data then give you the random data. Best to only use what you need.

Also, it is best to generateData() into a transient array and not a permanent array to alleviate wear leveling on the EEPROM/Flash memory as every bit of longevity of the card really matters. Also the thing most people don't do is to leave the data buffer dirty with existing key data. It is best to make it a habit to run a Util.arrayFillNonAtomic() with zero bytes to wipe the buffer if it once contains key data to ensure it does not leak key bytes by some bad accidents. It ever happened before and it leaves a bad stinging taste if you accidentally send out key data bytes by accident.

Also for the doFinal() and update() method, just to add on, you can accept a return of processed bytes. One example ...

Code: Select all

// Buffers of short data type
short[] shortBuff = JCSystem.makeTransientShortArray((short) 1, JCSystem.MEMORY_TYPE_TRANSIENT_RESET);

... some other codes ...

cipherAES.doFinal(b, (short) (dataOffset + 24), incomingLength, a, (short) (dataOffset + 48));

// You do not need to calculate how many bytes to send out as this uses a short buffer object to hold the number of output bytes
apdu.setOutgoing();
apdu.setOutgoingLength((short) (shortBuff[0] & 0xFF));
apdu.sendBytesLong(b, (short) dataOffset, (short) (shortBuff[0] & 0xFF));

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: Google [Bot] and 13 guests

JavaCard OS : Disclaimer