2016-01-12 5 views
2

Я хочу реализовать алгоритм ECDSA на Java-карте (JCOP 2.4.2). Это мой исходный код:Алгоритм ECDSA на JCOP 2.4.2 Java-карта

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?

+0

Откуда вы выбрали свой параметр ECC, пожалуйста, обратитесь к [NIST] (http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf) для кривой P-192, Похоже, что ваши параметры неверны. Если вы все еще не в состоянии выяснить, пожалуйста, дайте мне знать. –

+0

не комментировать эту строку ... "// objECDSAPubKey = (ECPublicKey) KeyBuilder.buildKey (KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_192, true);" в противном случае он будет всегда нулевым, и вы будете продолжать получать 0x6F00. –

+0

Есть ли что-нибудь в ответах, приянка? Если нет, можете ли вы выбрать и принять его, поскольку вопрос остается открытым иначе. Вы можете принять, щелкнув знак V слева от ответа. –

ответ

2

Я не эксперт по JCOP, но у меня есть опыт работы с ISO7816:

StatusWord 0x6F00 означает «Общая ошибка». Я предполагаю, что генерируется исключение CryptoException, но значение «причины» составляет от 1 до 5 (согласно documentation). Невозможно вернуть произвольные значения в качестве статусного слова ISO7816.

Поэтому я хотел бы предложить, чтобы отправить причину с помощью apdu.sendBytes (...), то вы знаете, что на самом деле это проблема

Лучший способ будет отладить код

1

Поскольку вы указываете, что ваш звонок на KeyBuilder.buildKey(...) терпит неудачу, я бы предположил, что этот вызов вызывает CryptoException с кодом причины NO_SUCH_ALGORITHM. Поскольку вы не обрабатываете это исключение в своем коде, это приводит к тому, что слово состояния 0x6F00 перенастраивается на карту (0x6F00 обычно возвращается в случае необработанных исключений).

Таким образом, CryptoException указывает, что запрошенный ключевой алгоритм не поддерживается. Так как вы используете следующие параметры

KeyBuilder.buildKey(
    KeyBuilder.TYPE_EC_FP_PRIVATE, // key type 
    KeyBuilder.LENGTH_EC_FP_192, // key length 
    true);       // key encryption 

это может означать, что

  • карта не поддерживает EC_FP (эллиптическая кривая над большим простым полем) ключа типа/алгоритма,
  • карта не поддерживают длину ключа 192, или
  • карта не поддерживает шифрование ключа.

Как политики безопасности криптографический модуль FIPS 140-2 для обоих JCOP 2.4.2 R2 и JCOP 2.4.2 R3 показывают, что генерация ключа пара ECDSA поддерживается для P-192 (кроме Р-224 и Р-256), я предположил бы, что на карту не поддерживает шифрование ключей. Таким образом, вы могли бы вместо того, чтобы попытаться

KeyBuilder.buildKey(
    KeyBuilder.TYPE_EC_FP_PRIVATE, // key type 
    KeyBuilder.LENGTH_EC_FP_192, // key length 
    false);       // key encryption 
1

Я вижу два разных вопроса:

  • JCOP (ошибочно) требует, чтобы установить параметры секретного ключа, а также;
  • Базовая точка G представляется в сжатом формате, который может не поддерживаться, вместо этого требуется преобразовать в 49-разрядную несжатую точку.

Кроме того, следует отметить, что:

  • вы действительно должны сначала создать открытый ключ с помощью KeyBuilder (в настоящее время закомментирована);
  • нет причин иметь параметр S там (семя не имеет никакого значения - по крайней мере, я полагаю, что это не закрытый ключ с таким размером);
  • вы действительно должны обернуть генерацию ключей оператором try/catch и (в конце) преобразовать в ISOException с действительным словом состояния;
  • Имеющий отладчик имеет жизненно важное значение.