Site Tools


javacard-api-samples:ecc

ECC Sample Code

Download Sample Code Discussion

/*
 * @file  ECCSample.java
 * @version v1.0
 * Package AID: 4A617661436172644F53 
 * Applet AID:  4A617661436172644F5304
 * @brief The ALgorithm of ECC 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.ECPrivateKey;
import javacard.security.ECPublicKey;
import javacard.security.KeyBuilder;
import javacard.security.*;
import javacardx.crypto.*;
 
public class ECCSample extends Applet
{
    private static final byte INS_ECC_GEN_KEYPAIR         = (byte)0x41;
    private static final byte INS_ECC_GENA                  = (byte)0x42;
    private static final byte INS_ECC_GENP                  = (byte)0x43;
    private static final byte INS_ECC_GENS                  = (byte)0x44;
    private static final byte INS_ECC_GENW                  = (byte)0x45;
    private static final byte INS_ECC_SETS                  = (byte)0x46;
    private static final byte INS_ECC_SETW                  = (byte)0x47;
    private static final byte INS_ECC_SIGN                 = (byte)0x48;
    private static final byte INS_ECC_VERIFY               = (byte)0x49;
 
 
    private byte[] tempBuffer;
 
    private byte[] flags;
    private static final short FLAGS_SIZE = (short)5;
 
    private short eccKeyLen;
    private Signature ecdsa;
    private KeyPair eccKey;
 
    public ECCSample()
    {
        //Create a transient byte array to store the temporary data
        tempBuffer = JCSystem.makeTransientByteArray((short)256, JCSystem.CLEAR_ON_DESELECT);
        flags = JCSystem.makeTransientByteArray(FLAGS_SIZE, JCSystem.CLEAR_ON_DESELECT);
 
        //Create a ECC(ALG_ECDSA_SHA) object instance
        ecdsa = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
 
        JCSystem.requestObjectDeletion();
    }
 
    public static void install(byte[] bArray, short bOffset, byte bLength) 
    {
        new ECCSample().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_ECC_GEN_KEYPAIR:
            // GEN_KEYPAIR
            GenEccKeyPair(apdu, len);
            break;
        case INS_ECC_GENA:
            // ECC_GENA
            getEccKeyA(apdu, len);
            break;
        case INS_ECC_GENP:
            // ECC_GENP
            getEccKeyP(apdu, len);
            break;
        case INS_ECC_GENS:
            // ECC_GENS
            getEccKeyS(apdu, len);
            break;
        case INS_ECC_GENW: 
            // ECC_GENW
            getEccKeyW(apdu, len);
            break;
        case INS_ECC_SETS://PrivateKey
            // ECC_SETS
            setEccKeyS(apdu, len);
            break;
        case INS_ECC_SETW://PublicKey
            // ECC_SETW
            setEccKeyW(apdu, len);
            break;
        case INS_ECC_SIGN:
            // ECC_SIGN
            Ecc_Sign(apdu, len);
            break;
        case INS_ECC_VERIFY:
            //ECC_VERIFY
            Ecc_Verify(apdu, len);
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
 
    //According to the different key length specified in the incoming APDU , generate ECC key pair and store in the  global variable 'eccKey'
    private void GenEccKeyPair(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        short keyLen = (short)0;
        switch (buffer[ISO7816.OFFSET_P1])
        {
        case (byte)0x01: // 192
            //Constructs a KeyPair instance for the specified algorithm and keylength;
            eccKey = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
            keyLen = (short)24;
            break;
        case (byte)0x02:
            //Here, the KeyBuilder.LENGTH_EC_FP_256 only be used in JavaCard API 3.0.4
            eccKey = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256);
            keyLen = (short)32;
            break;
        case (byte)0x03: // 384
            //Here, the KeyBuilder.LENGTH_EC_FP_384 only be used in JavaCard API 3.0.4
            eccKey = new KeyPair(KeyPair.ALG_EC_FP,KeyBuilder.LENGTH_EC_FP_384); 
            keyLen = (short)48;
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            break;
        }
        //(Re)Initializes the key objects encapsulated in this 'eccKey' KeyPair instance with new key values.
        eccKey.genKeyPair();
        eccKeyLen = keyLen;
    }
 
    //Returns the first coefficient 'A' of the curve of the key.
    private void getEccKeyA(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        ((ECPrivateKey)eccKey.getPrivate()).getA(buffer, (short)0);
        apdu.setOutgoingAndSend((short)0, eccKeyLen);
    }
 
    //Returns the field specification parameter value of the key.
    private void getEccKeyP(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        ((ECPrivateKey)eccKey.getPrivate()).getField(buffer, (short)0);
        apdu.setOutgoingAndSend((short)0, eccKeyLen);
    }
 
    //Returns the coefficient 'S' of the curve of the key.
    private void getEccKeyS(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        short length = ((ECPrivateKey)eccKey.getPrivate()).getS(buffer, (short)0);
        apdu.setOutgoingAndSend((short)0, length);
    }
 
    //Returns the coefficient 'W' of the curve of the key.
    private void getEccKeyW(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        short length = ((ECPublicKey)eccKey.getPublic()).getW(buffer,(short)0);
        apdu.setOutgoingAndSend((short)0, length);
    }
 
    //Set the value of ECC private key(SetS)
    private void setEccKeyS(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        switch (buffer[ISO7816.OFFSET_P1])
        {          
        case (byte)0x01: // 192 key
            if (len != 24)
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            eccKeyLen = 24;
            //Constructs a KeyPai instance for the ALG_EC_FP algorithm and keylength is 192;
            eccKey = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
            break;
        case (byte)0x02:
            if (len != 32)
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            eccKeyLen = 32;
            //Constructs a KeyPai instance for the ALG_EC_FP algorithm and keylength is 256;
            //Here, the KeyBuilder.LENGTH_EC_FP_256 only be used in JavaCard API 3.0.4        
            eccKey = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256);
            break;
        case (byte)0x03: // 384 key
            if (len != 48)
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            eccKeyLen = 48;
            //Constructs a KeyPai instance for the ALG_EC_FP algorithm and keylength is 384;
            //Here, the KeyBuilder.LENGTH_EC_FP_384 only be used in JavaCard API 3.0.4 
            eccKey = new KeyPair(KeyPair.ALG_EC_FP,KeyBuilder.LENGTH_EC_FP_384); 
            break;
        default:
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
            break;
        }
        //In tempBuffer, the offset from 0 to 1 positions stored ECC private key, including 0 to 0 store the private key length, 130 to 255 store the private key data
        Util.setShort(tempBuffer, (short)0, len);
        Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, tempBuffer, (short)2, len);
    }
    //Set the value of ECC public key(SetW)
    private void setEccKeyW(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        switch (buffer[ISO7816.OFFSET_P1])
        {
        case (byte)0x01: // 192 key
            if (len != 24*2+1)
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            eccKeyLen = 24;
            //Constructs a KeyPair instance for the ALG_EC_FP algorithm and keylength is 192;
            eccKey = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
            break;
        case (byte)0x02:
            if (len != 32*2+1)
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            eccKeyLen = 32;
            //Constructs a KeyPai instance for the ALG_EC_FP algorithm and keylength is 256;
            //Here, the KeyBuilder.LENGTH_EC_FP_256 only be used in JavaCard API 3.0.4 
            eccKey = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256);
            break;
        case (byte)0x03: // 384 key
            if (len != 48*2+1)
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            eccKeyLen = 48;
            //Constructs a KeyPai instance for the ALG_EC_FP algorithm and keylength is 384;
            //Here, the KeyBuilder.LENGTH_EC_FP_384 only be used in JavaCard API 3.0.4 
            eccKey = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_384); 
            break;
        default:
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
            break;
        }
        //In tempBuffer, the offset from 128 to 255 positions stored ECC public key, including 128 to 129 store the public key length, 130 to 255 store the private key data
        Util.setShort(tempBuffer, (short)128, len);
        Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, tempBuffer, (short)130, len);
    }
 
    //ECC signature
    private void Ecc_Sign(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        //(Re)Initializes the key objects encapsulated in this KeyPair instance with new key values.
        eccKey.genKeyPair();
        short eccPriKeyLen = Util.getShort(tempBuffer, (short)0);
        //Returns a reference to the private key component of this  ECC KeyPair object.
        ((ECPrivateKey)eccKey.getPrivate()).setS(tempBuffer, (short)2, eccPriKeyLen);
        //Initializes the Signature object with the ecdsa Key
        ecdsa.init(eccKey.getPrivate(), Signature.MODE_SIGN);
        //Generates the signature of all input data.
        short lenTmp = ecdsa.sign(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0);
 
        apdu.setOutgoingAndSend((short)0, lenTmp);
    }
 
    //Verify the ECC signature, the format of APDU data field is : the signature data and the data to be verified
    private void Ecc_Verify(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();  
        short signLen = buffer[ISO7816.OFFSET_P1];
        //(Re)Initializes the key objects encapsulated in 'eccKey' KeyPair instance with new key values. 
        eccKey.genKeyPair();
        short eccPubKeyLen = Util.getShort(tempBuffer, (short)128);
        // Sets the point of the curve comprising the public key.
        ((ECPublicKey)eccKey.getPublic()).setW(tempBuffer, (short)130, eccPubKeyLen);
        short plainLen = (short)(len - signLen);
        short tmpOff = (short)(ISO7816.OFFSET_CDATA + signLen);
        //Initializes the Signature object with the appropriate Key
        ecdsa.init(eccKey.getPublic(), Signature.MODE_VERIFY);
        //Verify the signature of input data against the passed in ECC signature.
        boolean ret = ecdsa.verify(buffer, (short)tmpOff, plainLen, buffer, ISO7816.OFFSET_CDATA, signLen);
        buffer[(short)0] = ret ? (byte)1 : (byte)0;
        apdu.setOutgoingAndSend((short)0, (short)1);
    }
 
}

The test script of ECC is as follows: Download Test Script

//The test script of ECC
//Copyright(C) JavaCardOS Technologies Co., Ltd. All rights reserved.
 
//ECC Select Applet
00A404000B4A617661436172644F530400;
//generate ECC 192 key pair
80410100;
//getEccKeyS
80440000;
//getEccKeyW
80450000;
//ECC 192Key
//set private Key S 
8046010018D0F9D631D35D30A6E48983131BC6448F15AE7593D4C22F25;
//set public key W
80470100310442A2DE80594BE0318232749834AD2DE6340B16FC3C2B2F77AE97D1F3C08AAA01C7E2645A12EE5CC698BD649183E5CA3E;
//ECC sign 
//The ECC signature results are random, even if the private key and the plaintext are the same, the signature result is also different.
804800000101;
//ECC verify
804938003930360219008F079FD3B1CEF3C1F9881C762CF30DCFA563AAE159A5B48C021900D77839556EDAC3C87BEFFDDB426666E57D6A56F45BCC341D01;
javacard-api-samples/ecc.txt · Last modified: 2017/05/13 02:43 (external edit)