Page 1 of 2

The ALgorithm of DES Sample Code

Posted: Sat Jul 09, 2016 5:58 am
by JavaCardOS
The following code is the ALgorithm of DES Sample Code in JavaCard API Specification.

You can copy and use it directly or you can download the JCIDE project from the attachment and build it.


Code: Select all

/*
 * @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);
    }

}



Note:
The purpose of this example is only used to show the usage of DES algorithm .

Re: The ALgorithm of DES Sample Code

Posted: Sat Oct 29, 2016 4:54 am
by initialdhi
how I can decrypt byte from this applet in java application (terminal application) ?

Re: The ALgorithm of DES Sample Code

Posted: Sun Oct 30, 2016 10:16 pm
by UNKNwYSHSA

Re: The ALgorithm of DES Sample Code

Posted: Mon Oct 31, 2016 10:15 am
by tay00000

Code: Select all

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();


This can be optimized by using the setKey() function.

Code: Select all

tempDesKey2.setKey(buffer, ISO7816.OFFSET_CDATA);


All it needs is 1 line of code versus the above 5 lines of codes to set a key. I would also highly recommend not to use JCSystem's transaction mechanism whenever not needed as I am currently coding for NXP JCOP 2.4.3 smart card and it doesn't handle beginTransaction/commitTransaction for key data especially RSA 2048 bit keys (off-topic but related). In the end, setKey() itself should be able to handle the data since the data buffer is directly handed over to the Key object which if you measure the time would take more time for the original code than the code I presented. Also, you don't need the desKeyLen anymore since all you need to do is check input against 8/16/24 bytes of input with a single if statement via ...

Code: Select all

if((short) (buffer[ISO7816.OFFSET_LC] & 0xFF) == 16 || (short) (buffer[ISO7816.OFFSET_LC] & 0xFF) == 24) {
    tempDesKey2.setKey(buffer, ISO7816.OFFSET_CDATA);     
}


You would have effectively speed up the entire process of checking the key length and also loading the key into the DESKey object with only 3 lines of codes versus the many lines. Also, not to forget to wipe buffer via Util.arrayFillNonAtomic() with (byte) 0x00 since it contains key material - just for safety's sake.

Transaction mechanism is a weird thing and should not be used too often. I get different results from different cards and what I can tell is NXP JCOP 2.4.3 seems to not like the calling of commit or begin transaction and usually throw me exceptions when the Feitian A22CR and Feitian's C21C simply don't mind the transactions. Just some food for thought.

Hope it helps :) .

Re: The ALgorithm of DES Sample Code

Posted: Mon Oct 31, 2016 10:04 pm
by UNKNwYSHSA
You means JCOP 2.4.3 raises exception when you use JCSystem.xxxTransaction()? And A22CR do nothing?

Re: The ALgorithm of DES Sample Code

Posted: Mon Oct 31, 2016 10:09 pm
by tay00000
Yes. I think this belongs to another topic for the transaction problem.

Re: The ALgorithm of DES Sample Code

Posted: Mon Oct 31, 2016 10:19 pm
by UNKNwYSHSA
JCOP 2.4.3:
Mybe the data size in transaction exceeds transaction size?
A22CR:
How you know that? Can you show me the test code?

Re: The ALgorithm of DES Sample Code

Posted: Mon Oct 31, 2016 10:23 pm
by UNKNwYSHSA
You can create a new post where we can discuss the topic.
Our discussion is already out of this post topic. :D

Re: The ALgorithm of DES Sample Code

Posted: Thu May 30, 2019 5:02 am
by TobyCao
I just fix one bug. :D

  1.   public ThirdDemo()
  2.  
  3.     {
  4.  
  5.         desKey = new byte[32];
  6.  
  7.         desICV = new byte[8];
  8.  
  9.         desKeyLen = 0;
  10.  
  11.       //Create a DES ECB/CBS object instance of the DES algorithm.
  12.  
  13.         desEcbCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);
  14.  
  15.         desCbcCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false);
  16.  
  17.       //Creates uninitialized TDES cryptographic keys for signature and cipher algorithms.
  18.  
  19.         [b]tempDesKey2 = KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_DES3_2KEY, false);[/b]
  20.  
  21.         tempDesKey3 = KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_DES3_3KEY, false);
  22.  
  23.         JCSystem.requestObjectDeletion();
  24.  
  25.     }

Re: The ALgorithm of DES Sample Code

Posted: Fri Dec 27, 2019 1:57 am
by Shrutiii
Hi!
Excellent ! I got useful information here. Thank you!