1 2 3 Previous Next 40 Replies Latest reply: Jan 21, 2013 3:03 AM by PhHein Go to original post RSS
      • 15. Re: Elliptic curve cryptography (ECC)
        843851
        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
          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
            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
              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
                @ 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
                  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
                    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
                      You commented out the instantiation of KeyPair and then try to access get methods??
                      • 23. Re: Elliptic curve cryptography (ECC)
                        843851
                        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
                          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
                            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
                              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
                                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
                                  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
                                    I tried the code... the initialization succeeds...

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