The exclusive promotional activities on JCOP J3H145 card and Feitian R301 Smartcard Reader are in full swing. Please check this page for details.

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: 15
Joined: Tue Mar 01, 2016 3:56 am
Points :161
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 :28
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 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 = "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]);
    }
        
}
Last edited by ThanhLong on Tue Aug 20, 2019 4:26 am, edited 1 time in total.

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