ECDSA Signature in Javacard

只谈情不闲聊 提交于 2019-12-10 17:53:11

问题


I'm implementing the signing code using ECDSA in Javacard.

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.

Here is my full source 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 {
                // <<<<<<<<<<<<<<<< Here is the problem >>>>>>>>>>>>>>>>>
                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; 
}

}

And APDU Command is as follows

[  Card  ] <==  00A4040007D4106509900090
[  Card  ] ==>  9000

[  Card  ] <==  0046000000
[  Card  ] ==>  0003

My Development Environment is as follows.

  • OS : Windows 7
  • JCDK Ver 2.2.1
  • JDK Ver 1.4.2
  • Chip : NXP
  • Terminal : ACR122 NFC Contactless Smart Card Reader

I've changed my code to set domain parameters. But the card still outputs the same result(0x0003). Here is my full source 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 {
        // <<<<<<<<<<<<<<<< Here is the problem >>>>>>>>>>>>>>>>>
                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; 
}

}

回答1:


There are no default EC domain parameters in Java Card. It is required to create the KeyPair using an ECPublicKey and a ECPrivateKey for which the domain parameters are set (so the point W and secret S may be kept empty). After that it is possible to call genKeyPair(), at least if the card has support for F(2m) or F(p) Elliptic Curve cryptography and the key size that is specified.


ADDED

Note that NXP JCOP chips may require these parameters set for the public and the private key. The parameters should have either the key size (for separate values) or an uncompressed Elliptic Curve point. The value of G in the question seems to be a compressed point. Only the cofactor (for setH) should just have the value 1.

Note that only the chips with an asymmetric coprocessor may support elliptic curves; not all cards are created / configured equally. Contact your vendor for details.




回答2:


If an attempt to create instance of the particular algorithm (KeyPair.ALG_EC_FP & KeyBuilder.LENGTH_EC_FP_192 in your case) fails with NO_SUCH_ALGORITHM, it is either not supported by your card completely (e.g., old hardware) or disabled.

Project JCAlgTester allows you to obtain complete list of the supported algorithms for your particular card. Database of results for multiple different cards is also available (but is better to check your particular card directly by uploading JCAlgTester applet).



来源:https://stackoverflow.com/questions/24467612/ecdsa-signature-in-javacard

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!