This discussion is archived
1 2 3 Previous Next 40 Replies Latest reply: Jan 21, 2013 1:03 AM by PhHein Go to original post RSS
  • 15. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    I wrote a class that implements the ECPrivateKey interface:

    import javacard.framework.Util;
    import javacard.security.CryptoException;
    import javacard.security.ECPrivateKey;
    import javacard.security.KeyBuilder;
    
    public class PrivateKey implements ECPrivateKey
    {
         private ECPrivateKey privKey;  /** Key for decryption. */
         private byte[] keyArray;
         byte[] buffer;
         public PrivateKey(ECPrivateKey key,byte[] buff,byte[] keyarray)
         {
              privKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE,KeyBuilder.LENGTH_EC_FP_128,false);
              keyArray=keyarray;
              privKey=key;
              buffer=buff;
         }
         
         /*GETTERS*/
        public short getS(byte[] buffer, short offset) throws CryptoException 
         {return 0;}
        public byte getType() 
         {return 0;}
        public short getSize() 
         {return 0;}
        public short getG(byte[] buffer, short offset) throws CryptoException 
         {return 0;}
         public short getA(byte[] buffer, short offset) throws CryptoException
         {return 0;}
         public short getB(byte[] buffer, short offset) throws CryptoException
         {return 0;}
         public short getField(byte[] buffer, short offset) throws CryptoException
         {return 0;}
         public short getK() throws CryptoException 
         {return 0;}
         
         
         /*SETTERS & MISC*/
         public void setS(byte[] buffer, short offset, short length) throws CryptoException 
         {
              Util.arrayCopy(buffer,offset,keyArray,(short)0,length);
         }
    
         public void clearKey() 
         {}
    
         public boolean isInitialized() 
         {return false;}
         
         public void setA(byte[] buffer, short offset, short length) throws CryptoException 
         {
              privKey.setA(buffer,offset,length);
         }
         
         public void setB(byte[] buffer, short offset, short length) throws CryptoException
         {
              privKey.setB(buffer,offset,length);
         }
         
         public void setFieldFP(byte[] buffer, short offset, short length) throws CryptoException 
         {}
    
         public void setFieldF2M(short e1, short e2, short e3) throws CryptoException
         {}
         
         public void setFieldF2M(short e) throws CryptoException 
         {}
    
         public void setK(short K) 
         {}
         
         public void setG(byte[] buffer, short offset, short length) throws CryptoException 
         {}
    
         public void setR(byte[] buffer, short offset, short length) throws CryptoException 
         {}
    
         public short getR(byte[] buffer, short offset) throws CryptoException 
         {return 0;}
         
         public ECPrivateKey getPrivKey()
         {          
              return privKey;
         }
    
    }
    I think it'd be easier to instantiate an object of this class, that creates the private key and using it in the main program, but I dont know how to fill all the fields needed, G,K, A,B,fieldFP,R...
  • 16. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    Here is an ECC key agreement and signature test example. I did not test it yet.
    package com.javacardfolx.man.skynet.ecc.test;
    
    import javacard.framework.*;
    import javacard.security.*; 
    
    public class EccTest extends Applet {
         
        private byte[] scratch;
        private byte[] outBuffer;
        private byte[] q;
         
         private static final short VERSION_INFO_MAJOR_MINOR = (short)0x0001;
         
         private static final short MAX_COMPONENT_SIZE = (short)88;
         
         private short keyLength;
         private static final byte INS_SET_KEYLENGTH = (byte)0x01;     
         private static final byte INS_SET_p = (byte)0x02;
         private static final byte INS_SET_A = (byte)0x03;     
         private static final byte INS_SET_B = (byte)0x04;
         private static final byte INS_SET_P = (byte)0x05;
         private static final byte INS_SET_M = (byte)0x06;
         private static final byte INS_SET_T = (byte)0x07;
         private static final byte INS_SET_Q = (byte)0x08;
         private static final byte INS_SET_X = (byte)0x09;
         private static final byte OBJECT_DELETION = (byte)0x0A;
         private static final byte DEFINE_KEY = (short)0x0B;
         private static final byte DO_KA_TEST = 0x0C;
         private static final byte DO_SIG_TEST = 0x0D;
         
         private KeyPair keyPairECC;
         private KeyAgreement keyAgreement;
         private ECPrivateKey ecPrivateKey;
         private ECPublicKey ecPublicKey;
         private ECKey keyContext;
         private MessageDigest messageDigest;
         private Signature sig1;
         private Signature sig2;
    
        EccTest() {
             this.q = JCSystem.makeTransientByteArray(MAX_COMPONENT_SIZE, JCSystem.CLEAR_ON_DESELECT);
             
            scratch = JCSystem.makeTransientByteArray((short) 255, JCSystem.CLEAR_ON_DESELECT);  
            outBuffer = JCSystem.makeTransientByteArray((short) 20, JCSystem.CLEAR_ON_DESELECT);
        
            keyPairECC = new KeyPair(KeyPair.ALG_EC_FP, keyLength);
            ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
            ecPublicKey = (ECPublicKey) keyPairECC.getPublic();
            keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
            messageDigest = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
            keyContext = ecPrivateKey; // initially
            sig1 = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
            sig2 = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
        }
        
         public static void install(byte[] bArray, short bOffset, byte bLength) {
              new EccTest().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
         }
    
         public void process(APDU apdu) {
              short code = 0;
              apdu.setIncomingAndReceive(); // beware of T=0
              byte[] buf = apdu.getBuffer();
    
              if (selectingApplet()) {
                Util.setShort(buf, (short) 0, VERSION_INFO_MAJOR_MINOR);
                apdu.setOutgoingAndSend((short) 0, (short) 2);
                   return;
              }
              try {
                   switch (buf[ISO7816.OFFSET_INS]) {
                        case DEFINE_KEY:
                             if (buf[ISO7816.OFFSET_CDATA] == (byte) 0x01)
                                  keyContext = ecPublicKey;
                             else
                                  keyContext = ecPrivateKey;
                             break;
                        case INS_SET_KEYLENGTH: 
                             keyLength = buf[ISO7816.OFFSET_CDATA];
                             break;
                        case INS_SET_p: 
                             keyContext.setFieldFP(buf, ISO7816.OFFSET_CDATA,
                                       ISO7816.OFFSET_LC);
                             break;
         
                        case INS_SET_A: 
                             keyContext.setA(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             break;
         
                        case INS_SET_B: 
                             keyContext.setB(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             break;
         
                        case INS_SET_P: 
                             keyContext.setG(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             break;
         
                        case INS_SET_M: 
                             keyContext.setR(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             break;
         
                        case INS_SET_T: 
                             ((ECPrivateKey) keyContext).setS(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             break;
                        case INS_SET_Q: 
                             ((ECPublicKey) keyContext).setW(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             // needed for KeyAgreement test
                             Util.arrayCopyNonAtomic(buf, ISO7816.OFFSET_CDATA, q, (short) 0, (short) (buf[ISO7816.OFFSET_LC] & 0xFF));
                             break;
                        case INS_SET_X: 
                             keyContext.setR(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             break;
                        case OBJECT_DELETION:
                              if (JCSystem.isObjectDeletionSupported()) {
                                   JCSystem.requestObjectDeletion();
                              }
                        case DO_KA_TEST:
                             if(!ecPrivateKey.isInitialized())
                                  code = (short)0x0F00;
                             else
                                  code = checkKeyAgreement();
                        case DO_SIG_TEST:
                             if(!ecPrivateKey.isInitialized() || !ecPublicKey.isInitialized())
                                  code = (short)0x0E00;
                             else 
                                  code = checkSignAndVerify(buf);
                        default:
                             ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
                   }
              } catch (CryptoException ce) {
                   code = ce.getReason();
              } catch (SystemException se) {
                   code = (short)0xE000;
              } catch (NullPointerException ne) {
                   code = (short)0xE001;
              } catch (CardRuntimeException cre) {
                   code = (short)0xE002;
              } catch (ArithmeticException ae) {
                   code = (short)0xE003;
              } catch (ArrayIndexOutOfBoundsException aie) {
                   code = (short)0xE004;
              } catch (ArrayStoreException ase) {
                   code = (short)0xE005;
              } catch (ClassCastException cce) {
                   code = (short)0xE006;
              } catch (RuntimeException re) {
                   code = (short)0xE007;
              } catch (Exception ex) {
                   code = (short)0xE008;
              }
              Util.setShort(buf, (short) 0, code);
              apdu.setOutgoingAndSend((short) 0, (short) 2);
         }
         
        private short checkSignAndVerify(byte[] buf) {
              // sign
              sig1.init(ecPrivateKey, Signature.MODE_SIGN);
              short sLen = sig1.sign(buf, (short) 0, (short)(buf[ISO7816.OFFSET_LC] & (short)0x00FF), scratch, (short) 0);
              // verify
              sig2.init(ecPublicKey, Signature.MODE_VERIFY);
              // check if signature can be verified
              if (!sig2.verify(buf, (short) 0, (short)(buf[ISO7816.OFFSET_LC] & (short)0x00FF), scratch, (short) 0, (short) sLen))
                   return (short) 0xA000;
              else
                   return 0;
        }
    
         public short checkKeyAgreement() {
             short componentLength = (short) ((keyLength + 7) >> 3); // divide by 8
            short compareByteLength = 20;
            ecPrivateKey.getR(outBuffer, (short)0);
            // Takes ALG_EC_SVDP_DH as input and delivers SHA1(x)
            // Compare delivered SHA1(x) component with SHA1(reference x-coordinate)
            keyAgreement.init(ecPrivateKey);
            
            short temp = 0;
            if ((temp = keyAgreement.generateSecret(q, (short) 0, (short) (2 * componentLength + 1), scratch, (short) 0)) != 20)
                return (short)((short)0xC000 | temp);
            
            messageDigest.reset();
            //Generates a hash if the input data
            messageDigest.doFinal(outBuffer, (short)0, (short)componentLength, outBuffer, (short)0);
            if (Util.arrayCompare(outBuffer, (short) 0, scratch, (short) 0, (short) compareByteLength) != 0)
                return (short) 0xD000;
            else
                 return 0;
        }
    }
  • 17. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    thank you, but your applet doesn't get loaded on the smartcard:
    cm>  install -i 4543435445535441  -q C9#() 45434354455354 4543435445535441
     => 80 E6 0C 00 20 07 45 43 43 54 45 53 54 08 45 43    .... .ECCTEST.EC
        43 54 45 53 54 41 08 45 43 43 54 45 53 54 41 01    CTESTA.ECCTESTA.
        00 02 C9 00 00 00                                  ......
     (3905013 usec)
     <= 6A 80                                              j.
    Status: Wrong data
    jcshell: Error code: 6a80 (Wrong data)
    jcshell: Wrong response APDU: 6A80
    Unexpected error; aborting execution
    I tried removing/adding other previous applets I made and everything flows smoothly...Perhaps something wrong with the ECC functionalities, as I got the same error trying uploading my own ECC applet (which looks similar to yours but it only implements functionalities to generate the private key). I checked my hardware spec. and it says the SmartCard supports the ECC.
  • 18. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    Solved:

    when it throws an "unexpected error" you must look for unsafe code not caught;
    It has been enough adding a try-catch block in the constructor.

    EccTest() {
             try{
             this.q = JCSystem.makeTransientByteArray(MAX_COMPONENT_SIZE, JCSystem.CLEAR_ON_DESELECT);
             
            scratch = JCSystem.makeTransientByteArray((short) 255, JCSystem.CLEAR_ON_DESELECT);  
            outBuffer = JCSystem.makeTransientByteArray((short) 20, JCSystem.CLEAR_ON_DESELECT);
        
            keyPairECC = new KeyPair(KeyPair.ALG_EC_FP, keyLength);
            ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
            ecPublicKey = (ECPublicKey) keyPairECC.getPublic();
            keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
            messageDigest = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
            keyContext = ecPrivateKey; // initially
            sig1 = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
            sig2 = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
             }catch(CryptoException e){}
        }
  • 19. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    @ lexdabear
    Your code loads correctly and all the calls issue 9000.
    I have a couple of questions:

    1- since I don't know what could be a good A or B or G value, I used random numbers, and the applet did accept them all:
    cm>  /send 00020000#(1111)
     => 00 02 00 00 02 11 11                               .......
     (6041 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 00030000#(2222)
     => 00 03 00 00 02 22 22                               .....""
     (67415 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 00040000#(3333)
     => 00 04 00 00 02 33 33                               .....33
     (5868 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 00050000#(4444)
     => 00 05 00 00 02 44 44                               .....DD
     (114790 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 00060000#(5555)
     => 00 06 00 00 02 55 55                               .....UU
     (60357 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 00070000#(6666)
     => 00 07 00 00 02 66 66                               .....ff
     (121248 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 00080000#(7777)
     => 00 08 00 00 02 77 77                               .....ww
     (4187 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 00090000#(8888)
     => 00 09 00 00 02 88 88                               .......
     (71017 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 000d0000
     => 00 0D 00 00                                        ....
     (122451 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 000d0000#(8888)
     => 00 0D 00 00 02 88 88                               .......
     (4410 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    cm>  /send 000c0000#(8888)
     => 00 0C 00 00 02 88 88                               .......
     (121948 usec)
     <= E0 01 90 00                                        ....
    Status: No Error
    But I wonder how can I test if the signature works? I mean, i am not sending any text message to sign, sending the "sign" command the applet issues 9000 which means "ok", but ok to what?? I expected at least a sequence which represents the signature over a blank text. Am I interpreting your applet erroneously?
  • 20. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    The code does not load correctly. One of the calls in the constructor throws an exception. Most likely your card does not support ALG_EC_FP and/or ALG_EC_SVDP_DH and/or ALG_ECDSA_SHA.
  • 21. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    I have isolated the troubling code and tried substituting the ALG_EC_FP algorithm with ALG_EC_F2M
    try{
                 //keyPairECC = new KeyPair(KeyPair.ALG_EC_FP, keyLength);
                 keyPairECC = new KeyPair(KeyPair.ALG_EC_F2M, keyLength);
                 ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
                  ecPublicKey = (ECPublicKey) keyPairECC.getPublic();
              }catch(CryptoException e){err = e.getReason();}
    but i still get the following:
    cm>  install -i 4543435445535441  -q C9#() 45434354455354 4543435445535441
     => 80 E6 0C 00 20 07 45 43 43 54 45 53 54 08 45 43    .... .ECCTEST.EC
        43 54 45 53 54 41 08 45 43 43 54 45 53 54 41 01    CTESTA.ECCTESTA.
        00 02 C9 00 00 00                                  ......
     (3743010 usec)
     <= 6A 80                                              j.
    Status: Wrong data
    jcshell: Error code: 6a80 (Wrong data)
    jcshell: Wrong response APDU: 6A80
    Unexpected error; aborting execution
  • 22. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    You commented out the instantiation of KeyPair and then try to access get methods??
  • 23. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    I wanted to use a different algorithm...
    Now I put it back to

    try{
                 keyPairECC = new KeyPair(KeyPair.ALG_EC_F2M, keyLength);
                 ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
                  ecPublicKey = (ECPublicKey) keyPairECC.getPublic();
              }catch(CryptoException e){err = e.getReason();}
    and i get:
    /send 00020000#(1111)
     => 00 02 00 00 02 11 11                               .......
     (100977 usec)
     <= E0 01 6F 00                                        ..o.
    Status: No precise diagnosis
    Do you still think my card does not support ECC?
  • 24. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    As mentioned, I did not test this. Since I made the effort to show how ECC works, I can anticipate that you will analyse the applet on your own..

    keyLength is not initialized yet. Move the KeyPair part from the constructor to key length initialization:
                   
         case INS_SET_KEYLENGTH: // resets ECC keys with new key length
                           keyPairECC = new KeyPair(KeyPair.ALG_EC_FP, keyLength);
                           ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
                           ecPublicKey = (ECPublicKey) keyPairECC.getPublic();
                             keyLength = buf[ISO7816.OFFSET_CDATA];
                             break;
    With the latest JCOP Tools 3.2.7 you could have debugged it in the constructor.
  • 25. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    you're right, I will be working on it, thank you for all the hints. Now the applet loads correctly in the case of ECC F2M.

    The case INS_SET_X and the INS_SET_M are equivalent aren't they?
  • 26. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    skynet_man wrote:
    The case INS_SET_X and the INS_SET_M are equivalent aren't they?
    Yes
  • 27. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    I think that the getters of public and private key cannot be called before all the EC parameters are set, therefore I guess that in the part:
     case INS_SET_KEYLENGTH: 
                             keyLength= KeyBuilder.LENGTH_EC_F2M_113;
                             try{ keyPairECC = new KeyPair(KeyPair.ALG_EC_F2M, keyLength);
                               ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
                                     ecPublicKey = (ECPublicKey)   keyPairECC.getPublic();
                             }catch(CryptoException ex)
                             { code = (short)ex.getReason();}
    the two get function call should be deleted from here and called only once all the parameters are set, right after the call to
    keyPairECC.genKeyPair(); which generates both priv and pub key, so you can get them both.

    don't you agree?
  • 28. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    hi here my working code for signing through ECC, i hope it'll be helpful for the future forum's visitors:

    package ecc_test;
    
    import javacard.framework.*;
    import javacard.security.*; 
    import javacard.framework.APDU;
    import javacard.framework.ISO7816;
    import javacard.framework.Applet;
    import javacard.framework.ISOException;
    import javacard.framework.SystemException;
    import javacard.framework.Util;
    import javacard.security.CryptoException;
    import javacard.security.DESKey;
    import javacard.security.Key;
    import javacard.security.KeyBuilder;
    import javacardx.crypto.Cipher;
     
    public class EccTest extends Applet {
         
        private byte[] scratch;
        private byte[] outBuffer;
        private byte[] q;
         
         private static final short VERSION_INFO_MAJOR_MINOR = (short)0x0113;
         
         private static final short MAX_COMPONENT_SIZE = (short)88;
         
         private short keyLength;
         private static final byte INS_PARAMETERS      = (byte)0x01;     
         private static final byte GET_PARAM           = (byte)0x02;
         private static final byte DO_SIG_TEST           = (byte)0x03;
         
         private KeyPair keyPairECC;
         private KeyAgreement keyAgreement;
         private ECPrivateKey ecPrivateKey;
         private ECPublicKey ecPublicKey;
         private MessageDigest messageDigest;
         private Signature sig1;
         private Signature sig2;
     
        EccTest() {
             
             this.q = JCSystem.makeTransientByteArray(MAX_COMPONENT_SIZE, JCSystem.CLEAR_ON_DESELECT);      
            scratch = JCSystem.makeTransientByteArray((short) 255, JCSystem.CLEAR_ON_DESELECT);  
            outBuffer = JCSystem.makeTransientByteArray((short) 20, JCSystem.CLEAR_ON_DESELECT);
            keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH, false);
            messageDigest = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
            sig1 = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
            sig2 = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
        }
        
         public static void install(byte[] bArray, short bOffset, byte bLength) {
              new EccTest().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
         }
     
         public void process(APDU apdu) {
              short code = 0;
              apdu.setIncomingAndReceive(); // beware of T=0
              byte[] buf = apdu.getBuffer();
     
              if (selectingApplet()) {
                Util.setShort(buf, (short) 0, VERSION_INFO_MAJOR_MINOR);  //sets the buffer with the applet version no.
                apdu.setOutgoingAndSend((short) 0, (short) 2);
                   return;
              }
              
              
                   switch (buf[ISO7816.OFFSET_INS]) {
                        case INS_PARAMETERS: //01
                             
                             /*PARAMETERS*/
                             byte[]valA= {(byte)0x00,(byte)0x30,(byte)0x88 ,(byte)0x25,(byte)0x0C,(byte)0xA6,(byte)0xE7 ,(byte)0xC7,(byte)0xFE,(byte)0x64,(byte)0x9C ,(byte)0xE8,(byte)0x58,(byte)0x20,(byte)0xF7};
                             byte[] valB={(byte)0x00,(byte)0xE8,(byte)0xBE,(byte)0xE4,(byte)0xD3,(byte)0xE2,(byte)0x26,(byte)0x07,(byte)0x44,(byte)0x18,(byte)0x8B,(byte)0xE0,(byte)0xE9,(byte)0xC7,(byte)0x23}; 
                             byte[] valG={(byte)0x04,(byte)0x00,(byte)0x9D,(byte)0x73,(byte)0x61,(byte)0x6F,(byte)0x35,(byte)0xF4,(byte)0xAB,(byte)0x14,(byte)0x07,(byte)0xD7,(byte)0x35,(byte)0x62,(byte)0xC1,(byte)0x0F,(byte)0x00,(byte)0xA5,(byte)0x28,(byte)0x30,(byte)0x27,(byte)0x79,(byte)0x58,(byte)0xEE,(byte)0x84,(byte)0xD1,(byte)0x31,
                                              (byte)0x5E,(byte)0xD3,(byte)0x18,(byte)0x86};
                             byte[] valN={(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0xD9,(byte)0xCC,(byte)0xEC,(byte)0x8A,(byte)0x39,(byte)0xE5,(byte)0x6F};
                             byte[] valW={(byte)0x10,(byte)0xE7,(byte)0x23,(byte)0xAB,(byte)0x14,(byte)0xD6,(byte)0x96,
                                            (byte)0xE6,(byte)0x76,(byte)0x87,(byte)0x56,(byte)0x15,(byte)0x17,(byte)0x56,
                                            (byte)0xFE,(byte)0xBF,(byte)0x8F,(byte)0xCB,(byte)0x49,(byte)0xA9};
                             byte[] valS={(byte)0x10,(byte)0xE7,(byte)0x23,(byte)0xAB,(byte)0x14,(byte)0xD6,(byte)0x96,
                                             (byte)0xE6,(byte)0x76,(byte)0x87,(byte)0x56,(byte)0x15,(byte)0x17,(byte)0x56,
                                             (byte)0xFE};
                             short f2m =  (short)0x09;
                             short k =    (short)0x02;
                             keyLength= 113;
                             
                             /*SETTERS*/
                             try {
                                  
                             keyPairECC = new KeyPair(KeyPair.ALG_EC_F2M, keyLength);
                             ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
                           ecPublicKey = (ECPublicKey)   keyPairECC.getPublic();
                           ecPrivateKey.setFieldF2M((short)f2m);
                             ecPrivateKey.setA(valA,(short)0,(short)valA.length);
                             ecPublicKey.setA(valA,(short)0,(short)valA.length);
                             ecPrivateKey.setB(valB, (short)0, (short)valB.length);
                             ecPublicKey.setB(valB, (short)0, (short)valB.length);
                             ecPrivateKey.setG(valG, (short)0, (short)valG.length);
                             ecPublicKey.setG(valG, (short)0, (short)valG.length);
                             ecPrivateKey.setR(valN, (short)0, (short)valN.length);
                             ecPublicKey.setR(valN, (short)0, (short)valN.length);
                             ecPrivateKey.setS(valS,(short)0,(short)valS.length);
                             ecPublicKey.setW(valW,(short)0,(short)valW.length);
                             ecPrivateKey.setS(buf, ISO7816.OFFSET_CDATA, ISO7816.OFFSET_LC);
                             ecPrivateKey.setK(k);
                             ecPublicKey.setK(k);
                             
                             /*kEY GENERATION*/
                             keyPairECC.genKeyPair();
                             } 
                             catch (CryptoException ce)           {code = ce.getReason();}
                             catch (SystemException se)           {code = (short)0xE000;} 
                             catch (NullPointerException ne) {code = (short)0xE001;}
                             catch (CardRuntimeException cre){code = (short)0xE002;}
                             catch (ArithmeticException ae)  {code = (short)0xE003;}
                             catch (ArrayIndexOutOfBoundsException aie) {code = (short)0xE004;}
                             catch (ArrayStoreException ase) {code = (short)0xE005;}
                             catch (ClassCastException cce)  {code = (short)0xE006;}
                             catch (RuntimeException re)      {code = (short)0xE007;}
                             catch (Exception ex)                {code = (short)0xE008;}
                             Util.setShort(buf, (short) 0, code);
                             apdu.setOutgoingAndSend((short) 0, (short) 2);
                        break;
                        
                        case GET_PARAM:     //0x02
                             keyLength= 113;
                           keyPairECC = new KeyPair(KeyPair.ALG_EC_F2M, keyLength);
                             ecPrivateKey = (ECPrivateKey) keyPairECC.getPrivate();
                           ecPublicKey = (ECPublicKey)   keyPairECC.getPublic();
                             keyPairECC.genKeyPair();
                             getValues(buf,apdu);
                             
                             /*
                              * expected parameters for keylength = 113
                              a = 00 30 88 25 0C A6 E7 C7 FE 64 9C E8 58 20 F7
                              b = 00 E8 BE E4 D3 E2 26 07 44 18 8B E0 E9 C7 23
                              G = 04 00 9D 73 61 6F 35 F4 AB 14 07 D7 35 62 C1 
                                  0F 00 A5 28 30 27 79 58 EE 84 D1 31 5E D3 18 86
                              S = 10E723AB 14D696E6 76875615 1756FEBF 8FCB49A9
                              n = 010000 00000000 00D9CCEC 8A39E56F
                              */
                        break;
                             
                        case DO_SIG_TEST: //0x03
                             code=0;
                             if(!ecPrivateKey.isInitialized() || !ecPublicKey.isInitialized())
                                  code = (short)0xE000;
                             else 
                                  code = checkSignAndVerify(buf,apdu);
                             Util.setShort(buf, (short) 0, code);
                             apdu.setOutgoingAndSend((short) 0, (short) 2);     
                             break;
                        default:
                             ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
                   }
         }
         
         
         
       void getValues(byte[] buf, APDU apdu)
       {
         byte[] tmp= new byte[200];
         short[] dim= new short[6];
         short dimTot=0;     
         byte[] stuff={(byte)0xff};
         dim[0]=ecPublicKey.getA(tmp,(short)0);
         dimTot = dim[0];
         Util.arrayCopy(stuff,(short)0,tmp,(short)dimTot,(short)1);
         ++dimTot;
         dim[1]=ecPublicKey.getB(tmp,(short)dimTot);
         dimTot += dim[1]; 
         Util.arrayCopy(stuff,(short)0,tmp,(short)dimTot,(short)1);
         ++dimTot;
         dim[2]=ecPublicKey.getG(tmp,(short)dimTot);
         dimTot += dim[2]; 
         Util.arrayCopy(stuff,(short)0,tmp,(short)dimTot,(short)1);
         ++dimTot;
         dim[3]=ecPublicKey.getR(tmp,(short)dimTot);
         dimTot += dim[3];
         Util.arrayCopy(stuff,(short)0,tmp,(short)dimTot,(short)1); 
         ++dimTot;
         dim[4]=ecPublicKey.getW(tmp,(short)dimTot);
         dimTot += dim[4];
         Util.arrayCopy(stuff,(short)0,tmp,(short)dimTot,(short)1); 
         ++dimTot;
         Util.setShort(tmp, (short)dimTot, (short)ecPublicKey.getSize());
         dimTot+=2;
         Util.arrayCopy(tmp,(short)0,buf,(short)0,(short)dimTot);
         apdu.setOutgoingAndSend((short) 0, (short)dimTot);
         }
         
         
        private short checkSignAndVerify(byte[] buf,APDU apdu) {
              // sign
              sig1.init(ecPrivateKey, Signature.MODE_SIGN);
              short sLen = sig1.sign(buf, (short) 0, (short)(buf[ISO7816.OFFSET_LC] & (short)0x00FF), scratch, (short) 0);
              
              // verify
              sig2.init(ecPublicKey, Signature.MODE_VERIFY);
              
              
              // check if signature can be verified
              if (!sig2.verify(buf, (short) 0, (short)(buf[ISO7816.OFFSET_LC] & (short)0x00FF), scratch, (short) 0, (short) sLen))
                   return (short) 0xA000;
              else
                   return (short)sLen;
        }
    }
    
    Marco
  • 29. Re: Elliptic curve cryptography (ECC)
    843851 Newbie
    Currently Being Moderated
    I tried the code... the initialization succeeds...

    But the Applet breaks at the line
    keyPairECC.genKeyPair();
    Any ideas?