Christmas is coming soon! To thank for the support from all our dear customers, Christmas promotional activity is going on in JavaCardOS online store. For more activities details, please check this post.

ECDSA signature

Algorithm School

Moderator: UNKNwYSHSA

mikegigom
Posts: 15
Joined: Fri Nov 27, 2015 1:38 am
Points :101
Contact:

ECDSA signature

Post by mikegigom » Mon May 30, 2016 4:29 am

I have created an EC key pair and I tried to use the same data and EC private key to generate ECDSA signature. But I found that each signature is different from the previous one. Why the value is different? What can I do to make the signature same?

Code: Select all

Signature sig1 = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
     
sig1.init(myECPrivateKey);
     
short signatureLength = sig1.sign(inputData, (short) 0, inputDataLength, signatureBuffer, (short) 0);

sendManyBytes(apdu, signatureBuffer, (short) 0, signatureLength);


Usiger
Posts: 14
Joined: Tue Mar 01, 2016 3:56 am
Points :147
Contact:

Re: ECDSA signature

Post by Usiger » Mon May 30, 2016 5:26 am

There is a step in the process of generating ECDSA signature - generate a random number, which causes different results.

mikegigom
Posts: 15
Joined: Fri Nov 27, 2015 1:38 am
Points :101
Contact:

Re: ECDSA signature

Post by mikegigom » Tue May 31, 2016 5:42 am

Usiger wrote:There is a step in the process of generating ECDSA signature - generate a random number, which causes different results.


Is there anyway to use the same random number so that I can get the same ECDSA signature?

corleoner
Posts: 15
Joined: Fri Dec 11, 2015 2:22 am
Points :90
Contact:

Re: ECDSA signature

Post by corleoner » Tue May 31, 2016 11:23 pm

If you use the same random data, there will be security issue. I mean, this method is NOT secure.

ThanhLong
Posts: 1
Joined: Tue Dec 19, 2017 5:05 am
Points :12
Contact:

Re: ECDSA signature

Post by ThanhLong » Tue Dec 19, 2017 5:21 am

I use ECDSA_SHA256 with sec256p-r1 domain parameter to sign, verify => Verify is OK
and then verify again on https://javacardos.com/tools/ecdsa_sign_verify.html with the same private, public, (r,s)
But the result is invalid.
I don't know why.
I use Java 3.0.5
My applet as follow :

Code: Select all

/**
 *
 */
package com.mksmart.ECDSAproject;

import javacard.framework.*;
import javacard.security.CryptoException;
import javacard.security.ECKey;
import javacard.security.ECPrivateKey;
import javacard.security.ECPublicKey;
import javacard.security.KeyBuilder;
import javacard.security.KeyPair;
import javacard.security.MessageDigest;
import javacard.security.RandomData;
import javacard.security.Signature;
import javacardx.annotations.*;
import javacardx.crypto.Cipher;

/**
 * Applet class
 *
 * @author <user>
 */
@StringPool(value = {
       @StringDef(name = "Package", value = "com.mksmart.ECDSAproject"),
       @StringDef(name = "AppletName", value = "ECDSAapplet")},
       // Insert your strings here
   name = "ECDSAappletStrings")
public class ECDSAapplet extends Applet {
   
   final static byte[] SecP256r1_P = {
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,
      (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
      (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(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[] SecP256r1_A = {
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,
      (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
      (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFC};
   
   final static byte[] SecP256r1_B = {
      (byte)0x5A,(byte)0xC6,(byte)0x35,(byte)0xD8,(byte)0xAA,(byte)0x3A,(byte)0x93,(byte)0xE7,
      (byte)0xB3,(byte)0xEB,(byte)0xBD,(byte)0x55,(byte)0x76,(byte)0x98,(byte)0x86,(byte)0xBC,
      (byte)0x65,(byte)0x1D,(byte)0x06,(byte)0xB0,(byte)0xCC,(byte)0x53,(byte)0xB0,(byte)0xF6,
      (byte)0x3B,(byte)0xCE,(byte)0x3C,(byte)0x3E,(byte)0x27,(byte)0xD2,(byte)0x60,(byte)0x4B};
   
   final static byte[] SecP256r1_S = {
      (byte)0xC4,(byte)0x9D,(byte)0x36,(byte)0x08,(byte)0x86,(byte)0xE7,(byte)0x04,(byte)0x93,
      (byte)0x6A,(byte)0x66,(byte)0x78,(byte)0xE1,(byte)0x13,(byte)0x9D,(byte)0x26,(byte)0xB7,
      (byte)0x81,(byte)0x9F,(byte)0x7E,(byte)0x90};
   
   // Uncompress form
   final static byte[] SecP256r1_G = {
      (byte)0x04,(byte)0x6B,(byte)0x17,(byte)0xD1,(byte)0xF2,(byte)0xE1,(byte)0x2C,(byte)0x42,(byte)0x47,
      (byte)0xF8,(byte)0xBC,(byte)0xE6,(byte)0xE5,(byte)0x63,(byte)0xA4,(byte)0x40,(byte)0xF2,
      (byte)0x77,(byte)0x03,(byte)0x7D,(byte)0x81,(byte)0x2D,(byte)0xEB,(byte)0x33,(byte)0xA0,
      (byte)0xF4,(byte)0xA1,(byte)0x39,(byte)0x45,(byte)0xD8,(byte)0x98,(byte)0xC2,(byte)0x96,
      (byte)0x4F,(byte)0xE3,(byte)0x42,(byte)0xE2,(byte)0xFE,(byte)0x1A,(byte)0x7F,(byte)0x9B,
        (byte)0x8E,(byte)0xE7,(byte)0xEB,(byte)0x4A,(byte)0x7C,(byte)0x0F,(byte)0x9E,(byte)0x16,
        (byte)0x2B,(byte)0xCE,(byte)0x33,(byte)0x57,(byte)0x6B,(byte)0x31,(byte)0x5E,(byte)0xCE,
        (byte)0xCB,(byte)0xB6,(byte)0x40,(byte)0x68,(byte)0x37,(byte)0xBF,(byte)0x51,(byte)0xF5};
   
   final static byte[] SecP256r1_N = {
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,
      (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
      (byte)0xBC,(byte)0xE6,(byte)0xFA,(byte)0xAD,(byte)0xA7,(byte)0x17,(byte)0x9E,(byte)0x84,
      (byte)0xF3,(byte)0xB9,(byte)0xCA,(byte)0xC2,(byte)0xFC,(byte)0x63,(byte)0x25,(byte)0x51};
   
   final static short  SecP256r1_H =  1;
   
   private byte[]                PLAINTEXT;
   private ECPrivateKey         objECDSAPriKey         = null;
   private ECPublicKey            objECDSAPubKey         = null;
   private KeyPair               objECDSAKeyPair         = null;
   private Signature            objECDSASign            = null;
   private ECKey               objECKey            = null;
   private short               objECDSAPubKeyLen;
   private short               objECDSAPriKeyLen;
   
   private byte[]               TEMP_ARR;
   private static short         TEMP_ARR_LEN         = (short)256;
   
   private final static byte      ECDSA_GEN_KEY_PAIR      = (byte)0x46;
   private final static byte      ECDSA_GET_PUBLIC_KEY   = (byte)0x47;
   private final static byte      ECDSA_GET_PRIVATE_KEY   = (byte)0x48;
   private final static byte      ECDSA_SIGN            = (byte)0x49;
   private final static byte      ECDSA_VERIFY         = (byte)0x4A;
   private final static byte      ECDSA_SET_PRIVATE_KEY   = (byte)0x4B;
   private final static byte      ECDSA_SET_PUBLIC_KEY   = (byte)0x4C;
   
    /**
     * Installs this applet.
     *
     * @param bArray
     *            the array containing installation parameters
     * @param bOffset
     *            the starting offset in bArray
     * @param bLength
     *            the length in bytes of the parameter data in bArray
     */
    public static void install(byte[] bArray, short bOffset, byte bLength) {
        new ECDSAapplet().register();
    }

    /**
     * Only this class's install method should create the applet object.
     */
    public ECDSAapplet() {
       PLAINTEXT   = JCSystem.makeTransientByteArray((short)0x100, JCSystem.CLEAR_ON_DESELECT);
        TEMP_ARR    = JCSystem.makeTransientByteArray(TEMP_ARR_LEN, JCSystem.CLEAR_ON_DESELECT);
    }

    /**
     * Processes an incoming APDU.
     *
     * @see APDU
     * @param apdu
     *            the incoming APDU
     */
    @Override
    public void process(APDU apdu) {
        //Insert your code here
       
       byte[] buf = apdu.getBuffer();
//       ISOException.throwIt((short)0x9FAA);
       if ((buf[ISO7816.OFFSET_CLA] == 0) &&
                (buf[ISO7816.OFFSET_INS] == (byte) (0xA4))) {
            return;
        }
       switch(buf[ISO7816.OFFSET_INS]){
       case (byte)0xA4:{
          ISOException.throwIt((short)0x9FAA);
          break;
       }
       // Generate Key pair
       case (byte)ECDSA_GEN_KEY_PAIR:{   
          apdu.setIncomingAndReceive();
          ECDSAGenKeyPair(apdu, buf);
          break;
       }
       // Get Public Key
       case (byte)ECDSA_GET_PUBLIC_KEY:{
          ECDSAGetPubKey(apdu, buf);
          break;
       }   
       // Get Private Key
       case (byte)ECDSA_GET_PRIVATE_KEY:{
          ECDSAGetPriKey(apdu, buf);
          break;
       }
       // Signature
       case (byte)ECDSA_SIGN:{
          PLAINTEXT[0] = (byte)0x61;
          apdu.setIncomingAndReceive();
          ECDSASignature(apdu,buf,buf,ISO7816.OFFSET_CDATA,apdu.getIncomingLength());
          break;
       }
       // Verify
       case (byte)ECDSA_VERIFY:{
          PLAINTEXT[0] = (byte)0x61;
          apdu.setIncomingAndReceive();
          short DataLen = buf[ISO7816.OFFSET_LC];
          ECDSAVerify(apdu,buf,buf,(short)(ISO7816.OFFSET_CDATA + apdu.getIncomingLength() - 1),(short)1);
          break;
       }
       
       // Set Private key
       case ECDSA_SET_PRIVATE_KEY:{
          apdu.setIncomingAndReceive();
          ECDSASetPrivKey(buf);
          break;
       }
       
       // Set Public key
       case ECDSA_SET_PUBLIC_KEY:{
          apdu.setIncomingAndReceive();
          ECDSASetPubKey(buf);
          
          break;
       }
       default :{
          ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
          break;
       }
       }
    } 
    private void ECDSAGenKeyPair(APDU apdu,byte[] buf){
       try{
          if (objECDSAPriKey != null){
              objECDSAPriKey.clearKey();
              objECDSAPubKey.clearKey();
          }
         objECDSAPriKey = (ECPrivateKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false);
         objECDSAPubKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false);      
         objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false);
         
         objECDSASign = Signature.getInstance(MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_ECDSA, Cipher.PAD_NULL, false);               
         objECDSAPubKey.setFieldFP(SecP256r1_P, (short)0, (short)SecP256r1_P.length);
         objECDSAPubKey.setA(SecP256r1_A, (short)0, (short)ECDSADomainParameter.SecP256r1_A.length);
         objECDSAPubKey.setB(SecP256r1_B, (short)0, (short)SecP256r1_B.length);
         objECDSAPubKey.setG(SecP256r1_G, (short)0, (short)SecP256r1_G.length);
         objECDSAPubKey.setR(SecP256r1_N, (short)0, (short)SecP256r1_N.length);
         objECDSAPubKey.setK(SecP256r1_H);
         
         objECDSAPriKey.setFieldFP(SecP256r1_P, (short)0, (short)ECDSADomainParameter.SecP256r1_P.length);
         objECDSAPriKey.setA(SecP256r1_A, (short)0, (short)SecP256r1_A.length);
         objECDSAPriKey.setB(SecP256r1_B, (short)0, (short)SecP256r1_B.length);
         objECDSAPriKey.setG(SecP256r1_G, (short)0, (short)SecP256r1_G.length);
         objECDSAPriKey.setR(SecP256r1_N, (short)0, (short)SecP256r1_N.length);
         objECDSAPriKey.setK(SecP256r1_H);      
         
         objECDSAKeyPair = new KeyPair(objECDSAPubKey,objECDSAPriKey);
         objECDSAKeyPair.genKeyPair();
      }
      catch(CryptoException ex){
         short reason = ex.getReason();
         ISOException.throwIt(reason);             
      }
      ISOException.throwIt(ISO7816.SW_NO_ERROR);
    }
   
    private void ECDSAGetPubKey(APDU apdu,byte[] buf){
       try{
          objECDSAPubKey = (ECPublicKey)objECDSAKeyPair.getPublic();   
          objECDSAPubKeyLen = objECDSAPubKey.getW(buf, ISO7816.OFFSET_CDATA);
       }
      catch(CryptoException ex){
         ISOException.throwIt(ex.getReason());
      }
      apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA,objECDSAPubKeyLen);
    }
   
    private void ECDSAGetPriKey(APDU apdu,byte[] buf){
       try{
          objECDSAPriKey = (ECPrivateKey)objECDSAKeyPair.getPrivate();
           objECDSAPriKeyLen = objECDSAPriKey.getS(buf, ISO7816.OFFSET_CDATA);
       }
       catch(CryptoException ex){
          ISOException.throwIt(ex.getReason());
       }
       apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA,objECDSAPriKeyLen);
    }
   
    private void ECDSAVerify(APDU apdu,byte[] buf,byte[] PlainText,short PlainTextOffset,short PlainTextLen){
      short Signlen = buf[ISO7816.OFFSET_LC];
      boolean VerifyResult=false;
      objECDSASign.init(objECDSAPubKey, Signature.MODE_VERIFY);
      VerifyResult = objECDSASign.verify(PlainText,PlainTextOffset, PlainTextLen, buf, ISO7816.OFFSET_CDATA ,Signlen);
      if (VerifyResult){
         ISOException.throwIt(ISO7816.SW_NO_ERROR);
      }
      else{
         ISOException.throwIt(ISO7816.SW_DATA_INVALID);
      }
    }
   
    private void ECDSASignature(APDU apdu,byte[] buf,byte[] PlainText,short PlainTextOffset,short PlainTextLen){
      short sSignLen=0;   
      byte result=0;
      try{
         objECDSASign.init(objECDSAPriKey, Signature.MODE_SIGN);
         sSignLen = objECDSASign.sign(PlainText, PlainTextOffset,PlainTextLen, buf, ISO7816.OFFSET_CDATA);
      }
      catch(CryptoException ex){
         ISOException.throwIt(ex.getReason());
      }
      apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, sSignLen);
    }
   
    private void ECDSASetPrivKey(byte[] buf){
       objECDSAPriKey.setS(buf, ISO7816.OFFSET_CDATA, buf[ISO7816.OFFSET_LC]);
    }
   
    private void ECDSASetPubKey(byte[] buf){
       objECDSAPubKey.setW(buf, ISO7816.OFFSET_CDATA, buf[ISO7816.OFFSET_LC]);
    }
       
}

listade
Posts: 5
Joined: Wed Sep 12, 2018 4:46 am
Points :40
Contact:

Re: ECDSA signature

Post by listade » Fri Sep 14, 2018 4:06 am

I have same problem with SECP_256k1. :(

Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 2 guests

JavaCard OS : Disclaimer