title: ECDSA Signature in Javacard
body: <p>I'm implementing the signing code using ECDSA in Javacard.</p>
  
  <p>My code outputs 0x0003(NO_SUCH_ALGORITHM) in exception part which means this card does not support the algorithm. I don't understand that because my vendor told me that it supports ECC. I concluded I don't know how to sign with ECDSA and I want to know that.</p>
  
  <p>Here is my full source code</p>
  
  <pre><code>package MyECDSA;
  
  import javacard.framework.*;
  import javacard.security.*;
  import javacardx.crypto.*;
  
  public class MyECDSA extends Applet{
  
  private byte[] PLAINTEXT ;
  private ECPrivateKey            objECDSAPriKey=null;    // Object for ECDSA Private Key
  private ECPublicKey             objECDSAPubKey=null;    // Object for ECDSA Public Key
  private KeyPair                 objECDSAKeyPair=null;   // Object for ECDSA Key Pair
  private Signature               objECDSASign=null;      // Object for ECDSA Signature
  
  final static short  BAS     =  0;
  
  public static void install(byte[] bArray, short bOffset, byte bLength){
      new MyECDSA(bArray, bOffset, bLength);
  }
  
  private MyECDSA(byte bArray[], short bOffset, byte bLength){    
  
      PLAINTEXT       = new byte[0x100] ;         // Data file
  
      Util.arrayFillNonAtomic(PLAINTEXT,  BAS, (short)0x100, (byte)0);
  
      register();
  }
  
  //======================================================================================
  public void process(APDU apdu){
      byte buf[] = apdu.getBuffer();
  
      switch(buf[1])
      {
          //--------------------------------------------------------
          case (byte)0xA4:                    break;  
  
          case (byte)0x46:
              // Create ECDSA Keys and Pair
              try {
                  // &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; Here is the problem &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;
                  objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
                  //objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_F2M, KeyBuilder.LENGTH_EC_F2M_193);          
              }
              catch(CryptoException c)
              {    
                  short reason = c.getReason();   
                  ISOException.throwIt(reason);
              }
              ISOException.throwIt((short)0x9999);        // for check
  
              // Generate Key pair
              objECDSAKeyPair.genKeyPair();
  
              // Create Signature Object
              objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
  
              objECDSAPriKey = (ECPrivateKey)objECDSAKeyPair.getPrivate();
              objECDSAPubKey = (ECPublicKey)objECDSAKeyPair.getPublic();  
  
          break;
  
          case (byte)0x2E:                        
              short       Le              = apdu.setOutgoing();   
              short   sSignLen=0 ;
  
              // Init with Private Key
              objECDSASign.init(objECDSAPriKey, Signature.MODE_SIGN);
  
              // Sign Data
              sSignLen = objECDSASign.sign(PLAINTEXT, BAS, Le, buf, BAS);
  
              apdu.setOutgoingLength(sSignLen);
              apdu.sendBytes(BAS, sSignLen);
  
          break;      
          //--------------------------------------------------------
          default:
              ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
      }
  
      return; 
  }
  
  }
  </code></pre>
  
  <p>And APDU Command is as follows</p>
  
  <pre><code>[  Card  ] &lt;==  00A4040007D4106509900090
  [  Card  ] ==&gt;  9000
  
  [  Card  ] &lt;==  0046000000
  [  Card  ] ==&gt;  0003
  </code></pre>
  
  <p>My Development Environment is as follows.</p>
  
  <ul>
  <li>OS : Windows 7</li>
  <li>JCDK Ver 2.2.1</li>
  <li>JDK Ver 1.4.2</li>
  <li>Chip : NXP</li>
  <li>Terminal : ACR122 NFC Contactless Smart Card Reader</li>
  </ul>
  
  <hr>
  
  <p>I've changed my code to set domain parameters. But the card still outputs the same result(0x0003). Here is my full source code.</p>
  
  <pre><code>package MyECDSA;
  
  import javacard.framework.*;
  import javacard.security.*;
  import javacardx.crypto.*;
  
  public class MyECDSA extends Applet{
  
  private byte[] PLAINTEXT ;
  private ECPrivateKey            objECDSAPriKey=null;    // Object for ECDSA Private Key
  private ECPublicKey             objECDSAPubKey=null;    // Object for ECDSA Public Key
  private KeyPair                 objECDSAKeyPair=null;   // Object for ECDSA Key Pair
  private Signature               objECDSASign=null;      // Object for ECDSA Signature
  
  final static short  BAS     =  0;
  
  final static byte[] SecP192r1_P = {     // 24
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
      (byte)0xFE,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
  final static byte[] SecP192r1_A = {     // 24
      (byte)0xFC,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
      (byte)0xFE,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
  final static byte[] SecP192r1_B = {     // 24
    (byte)0xB1,(byte)0xB9,(byte)0x46,(byte)0xC1,(byte)0xEC,(byte)0xDE,(byte)0xB8,(byte)0xFE,
    (byte)0x49,(byte)0x30,(byte)0x24,(byte)0x72,(byte)0xAB,(byte)0xE9,(byte)0xA7,(byte)0x0F,
    (byte)0xE7,(byte)0x80,(byte)0x9C,(byte)0xE5,(byte)0x19,(byte)0x05,(byte)0x21,(byte)0x64};
  final static byte[] SecP192r1_S = {     // 20
    (byte)0xD5,(byte)0x96,(byte)0x21,(byte)0xE1,(byte)0xEA,(byte)0x20,(byte)0x81,(byte)0xD3,
    (byte)0x28,(byte)0x95,(byte)0x57,(byte)0xED,(byte)0x64,(byte)0x2F,(byte)0x42,(byte)0xC8,
    (byte)0x6F,(byte)0xAE,(byte)0x45,(byte)0x30};
  final static byte[] SecP192r1_G = {     // 25
    (byte)0x12,(byte)0x10,(byte)0xFF,(byte)0x82,(byte)0xFD,(byte)0x0A,(byte)0xFF,(byte)0xF4,
    (byte)0x00,(byte)0x88,(byte)0xA1,(byte)0x43,(byte)0xEB,(byte)0x20,(byte)0xBF,(byte)0x7C,
    (byte)0xF6,(byte)0x90,(byte)0x30,(byte)0xB0,(byte)0x0E,(byte)0xA8,(byte)0x8D,(byte)0x18,(byte)0x03};
  final static byte[] SecP192r1_N = {     // 24
    (byte)0x31,(byte)0x28,(byte)0xD2,(byte)0xB4,(byte)0xB1,(byte)0xC9,(byte)0x6B,(byte)0x14,
    (byte)0x36,(byte)0xF8,(byte)0xDE,(byte)0x99,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
    (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
  final static short  SecP192r1_H =  1;
  
  //======================================================================================
  public static void install(byte[] bArray, short bOffset, byte bLength){
      new MyECDSA(bArray, bOffset, bLength);
  }
  
  private MyECDSA(byte bArray[], short bOffset, byte bLength){    
  
      PLAINTEXT       = new byte[0x100] ;         // Data file
  
      Util.arrayFillNonAtomic(PLAINTEXT,  BAS, (short)0x100, (byte)0);
  
      register();
  }
  
  //======================================================================================
  public void process(APDU apdu){
      byte buf[] = apdu.getBuffer();
  
      switch(buf[1])
      {
          //--------------------------------------------------------
          case (byte)0xA4:                    break;  
  
          case (byte)0x46:
  
              // Create ECDSA Keys and Pair
              try {
          // &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; Here is the problem &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;
                  objECDSAPriKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_192, false);
                  ISOException.throwIt((short)0x8888);        // for check
                  objECDSAPubKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC,  KeyBuilder.LENGTH_EC_FP_192, false);
  
                  // set EC Domain Parameters
                  objECDSAPubKey.setFieldFP(SecP192r1_P, BAS, (short)24);
                  objECDSAPubKey.setA(SecP192r1_A, BAS, (short)24);
                  objECDSAPubKey.setB(SecP192r1_B, BAS, (short)24);
                  objECDSAPubKey.setG(SecP192r1_G, BAS, (short)25);
                  objECDSAPubKey.setK(SecP192r1_H);
                  objECDSAPubKey.setR(SecP192r1_N, BAS, (short)24);
  
                  objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
              }
            catch(CryptoException c)
            {    
              short reason = c.getReason();   
              ISOException.throwIt(reason);       // for check
            }
  
              // On-Card Key Generation Process
              objECDSAKeyPair.genKeyPair();
  
              // Obtain Key References
              objECDSAPriKey = (ECPrivateKey)objECDSAKeyPair.getPrivate();
              objECDSAPubKey = (ECPublicKey)objECDSAKeyPair.getPublic();  
  
              // Create Signature Object
              objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
  
          break;
  
          case (byte)0x2E:                        
              short       Le              = apdu.setOutgoing();   
              short   sSignLen=0 ;
  
              // Init with Private Key
              objECDSASign.init(objECDSAPriKey, Signature.MODE_SIGN);
  
              // Sign Data
              sSignLen = objECDSASign.sign(PLAINTEXT, BAS, Le, buf, BAS);
  
              apdu.setOutgoingLength(sSignLen);
              apdu.sendBytes(BAS, sSignLen);
  
          break;      
          //--------------------------------------------------------
          default:
              ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
      }
  
      return; 
  }
  
  }
  </code></pre>