Our express partner will perform scheduled system maintenance from 19th Jan to 3rd Feb, so during this time, all the orders in our webshop will be handled from 4th Feb.
Sorry for any inconvenience caused.

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: 2
Joined: Tue Dec 19, 2017 5:05 am
Points :44
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 26 guests

JavaCard OS : Disclaimer