smartcard - JCOP 2.4.2 Java 卡上的 ECDSA 算法

标签 smartcard javacard apdu ecdsa jcop

我想在 Java Card (JCOP 2.4.2) 上实现 ECDSA 算法。这是我的源代码:

package hashPack;

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, true);
                }
            catch(CryptoException c)
            {    
              short reason = c.getReason();   
              ISOException.throwIt(reason);       // for check
            }     // for check*/
                   // objECDSAPubKey = (ECPublicKey)KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC,      KeyBuilder.LENGTH_EC_FP_192, true);

                    // 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);


                // 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; 
    }
}

我正在使用此脚本脚本代码运行此源代码:

#/term SCComm:2
/mode trace=on
/atr
/card
/select |ecdsa
/send 00A4040007D4106509900090
/send 0046000000
/send 002E00000A30313233343031323334

当我调用 /send 0046000000 来签署纯文本消息时,我收到响应代码 6F00

你能帮我找出问题所在吗?

如何在 JCOP 卡上正确实现该算法?

最佳答案

我不是 JCOP 方面的专家,但我有 ISO7816 方面的经验:

状态字 0x6F00 表示“一般错误”。我想抛出一个 CryptoException ,但“reason”的值在 1-5 之间(根据 documentation )。 不可能以 ISO7816 状态字的形式返回任意值。

因此我建议使用 apdu.sendBytes(...) 发送原因,然后你就知道真正的问题是什么

最好的方法是调试代码

关于smartcard - JCOP 2.4.2 Java 卡上的 ECDSA 算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34741881/

相关文章:

javacard - 如何发送OTA消息?

android - 通过 Android isoDep.transceive 成功 'Unknown' 后,Google 钱包状态为 'Compute Crytographic Checksum'

credit-card - APDU 命令中的持卡人姓名(ICC 卡)

smartcard - 在 JCIDE 中发送 APDU 时遇到错误

android - NFC SWP 小程序选择返回 6999

java - Java Card 上的椭圆曲线 - 是否可以在 Java Card 上使用外部库?

javacard - UICC : How to change ARA?

smartcard - "acr38 card tools"和 "opensc"有什么区别?

python - 智能卡 PKCS11 AES key 生成失败

nfc - 如何在 DESfire Ev1 卡上使用 ISO7816 选择命令?