尝试创建RSA 2048密钥对时出现Javacard错误

时间:2017-03-30 07:41:58

标签: javacard key-pair

我正在开发一段代码,我需要在其中创建一个RSA密钥对。

我的Java卡是FM1280-ID006卡,其信息表中写有它支持java卡2.2.2规范。当我尝试创建RSA密钥对时

KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_2048)

并将其安装在上面的卡上,没有任何异常情况发生,我已成功完成(90 00)。

但是当我调用方法genKeyPair()时,卡片中出现了一些我不明白的原因。我使用GPShell如下:

send_apdu -sc 1 -APDU 8000000000 // initialize
Command --> 8000000000
Wrapped command --> 8000000000
send_APDU() returns 0x8010002F (A communications error with the smart card has been detected. Retry the operation.)

值得一提的是,在创建1024个密钥对时,不会发生密钥对创建的问题

KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_1024)

它已成功创建并由RSA密码使用,依此类推:

send_apdu -sc 1 -APDU 8000000000 // initialize
Command --> 8000000000
Wrapped command --> 8000000000
Response <-- 9000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 3432 ms

我的卡是否支持KeyPair 2048,因为信息表说支持javacard 2.2.2?

附录1:Java代码:

package net.sourceforge.globalplatform.jc.hasincard;

import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;

import java.security.acl.Owner;
import java.util.Random;


public class HasinCardApplet extends Applet {

   final static byte APPLET_CLA = (byte)0x80;
   final static byte INITIALIZE = (byte)0x00;
   final static byte INSERT_MESSAGE = (byte)0x01;
   final static byte CHECK_MESSAGE = (byte)0x02;
   final static byte GET_HASH = (byte)0x03;
   final static byte GET_SIGN = (byte)0x04;
   final static byte VERIFY_SIGN = (byte)0x05;
   final static byte VERIFY_PIN = (byte)0x06;
   final static byte CHANGE_PIN = (byte)0x07;
   final static byte UNLOCK_PIN = (byte)0x08;
   final static byte TEST = (byte)0x09;

   final static short SW_MESSAGE_NOT_INSERTED = (short)0x6300;
   final static short SW_KEY_IS_INITIALIZED = (short)0x6301;
   final static short SW_HASH_NOT_SET = (short)0x6302;
   final static short SW_SIGN_NOT_SET = (short)0x6303;
   final static short SW_CARD_IS_LOCKED = (short)0x6304;
   final static short SW_VERIFICATION_FAILED = (short)0x6305;
   final static short SW_PIN_VERIFICATION_REQUIRED = (short)0x6306;
   final static short SW_NEW_PIN_TOO_LONG = (short)0x6307;
   final static short SW_NEW_PIN_TOO_SHORT = (short)0x6308;
   final static short SW_PUK_VERIFICATION_REJECTED = (short)0x6309;
   final static short SW_PUK_VERIFICATION_FAILED = (short)0x630A;

   final static byte PIN_TRY_LIMIT = (byte)3;
   final static byte MAX_PIN_SIZE = (byte)16;
   final static byte MIN_PIN_SIZE = (byte)4;
   final static byte PUK_LEN = (byte)16;
   final static byte PUK_TRY_LIMIT = (byte)3;

   private static byte[] Message;
   private static byte[] Hash;
   private static byte[] Sign;
   private short message_len = 0;
   private short hash_len = 0;
   private short sign_len = 0;
   private static boolean key_initialization_flag = false;
   private static boolean insert_message_flag = false;
   private static boolean hash_set_flag = false;
   private static boolean sign_set_flag = false;
   MessageDigest mDigest;
   KeyPair rsaKey;
   Cipher rsaCipher;
   OwnerPIN userPin;
   RandomData rnd;
   byte[] PUK;
   boolean init_flag;
   byte puk_try_count;

   private HasinCardApplet (byte[] bArray,short bOffset,byte bLength)
   {
       Message         = new byte[512];
       Hash            = new byte[512];
       Sign            = new byte[512];
       userPin         = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
       rsaKey          = new KeyPair(KeyPair.ALG_RSA,KeyBuilder.LENGTH_RSA_2048);
       rsaCipher       = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
       mDigest         = MessageDigest.getInstance(MessageDigest.ALG_SHA_256,false);
       rnd             = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
       PUK             = new byte[PUK_LEN];
       generate_random(PUK, (byte) 16);
       init_flag       = false;
       puk_try_count   = (byte) 0;

       byte[] InstParam                = new byte[(byte)64];
       byte iLen                       = bArray[bOffset];
       bOffset                         = (short) (bOffset+iLen+1);
       byte cLen                       = bArray[bOffset];
       bOffset                         = (short) (bOffset+cLen+1);
       byte aLen                       = bArray[bOffset];
       Util.arrayCopy(bArray,(short) (bOffset +1),InstParam,(short)0,(short)aLen);
       byte CPassLen = InstParam[0];
       byte IPassLen = InstParam[CPassLen+1];
       userPin.update(InstParam,(short)1,CPassLen);

       register();

   }

   public static void install(byte[] bArray, short bOffset, byte bLength)
   {
       new HasinCardApplet(bArray, bOffset, bLength);
   }

   public boolean select()
   {
       Util.arrayFillNonAtomic(Message, (short) 0, (short)512, (byte) 0x00);
       Util.arrayFillNonAtomic(Hash, (short) 0, (short)512, (byte) 0x00);
       Util.arrayFillNonAtomic(Sign, (short) 0, (short)512, (byte) 0x00);
       return true;
   }

   public void deselect()
   {

   }

   public void process(APDU apdu)
   {
      if (selectingApplet())
      {
          if(!init_flag) {
              send_puk(apdu);
          }
          return;
      }

      byte[] buffer = apdu.getBuffer();
      if (buffer[ISO7816.OFFSET_CLA] == APPLET_CLA) {

          switch (buffer[ISO7816.OFFSET_INS]) {

              case VERIFY_PIN:
                  verify_pin(apdu);
                  break;

              case CHANGE_PIN:
                  change_pin(apdu);
                  break;

              case UNLOCK_PIN:
                  unlock_pin(apdu);
                  break;

              case INITIALIZE:
                  initialize();
                  break;

              case INSERT_MESSAGE:
                  insert_message(apdu);
                  break;

              case CHECK_MESSAGE:
                  check_message(apdu);
                  break;

              case GET_HASH:
                  hash_message();
                  get_hash(apdu);
                  break;

              case GET_SIGN:
                  hash_message();
                  sign_message();
                  get_sign(apdu);
                  break;

              case VERIFY_SIGN:
                  verify_sign(apdu);
                  break;

              case TEST:
                  test(apdu);
                  break;

              default:
                  ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
          }
      } else {
          ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
      }
   }

   private void initialize() {
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       if(key_initialization_flag) {
           ISOException.throwIt(SW_KEY_IS_INITIALIZED);
       }
       rsaKey.genKeyPair();
       key_initialization_flag = true;
       init_flag = true;
   }

   private void insert_message(APDU apdu) {
       byte[] buffer = apdu.getBuffer();
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       if(buffer[ISO7816.OFFSET_P1] == (byte) 0x01) {
           // reset Message
           message_len = 0;
       }
       short LC = apdu.setIncomingAndReceive();
       Util.arrayCopy(buffer, (short) (ISO7816.OFFSET_CDATA), Message, message_len, LC);
       message_len = (short) (message_len + LC);
       insert_message_flag = true;
   }

   private void check_message(APDU apdu) {
       byte[] buffer = apdu.getBuffer();
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       if(insert_message_flag) {
           apdu.setIncomingAndReceive();
           Util.arrayCopy(Message, (short) 0, buffer, (short) 0, message_len);
           apdu.setOutgoingAndSend((short) 0, message_len);
       } else {
           ISOException.throwIt(SW_MESSAGE_NOT_INSERTED);
       }
   }

   private void hash_message() {
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       if(insert_message_flag) {
           mDigest.reset();
           hash_len = mDigest.doFinal(Message, (short) 0, message_len, Hash, (short) 0);
           hash_set_flag = true;
       } else {
           ISOException.throwIt(SW_MESSAGE_NOT_INSERTED);
       }
   }

   private void sign_message() {
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       if(insert_message_flag) {
           rsaCipher.init(rsaKey.getPrivate(), Cipher.MODE_ENCRYPT);
           sign_len = rsaCipher.doFinal(Hash, (short) 0, hash_len, Sign, (short) 0);
           sign_set_flag = true;
       } else {
           ISOException.throwIt(SW_MESSAGE_NOT_INSERTED);
       }
   }

   private void get_hash(APDU apdu) {
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       if(hash_set_flag) {
           byte[] buffer = apdu.getBuffer();
           Util.arrayCopy(Hash, (short) 0, buffer, (short) 0, hash_len);
           apdu.setOutgoingAndSend((short) 0, hash_len);
       } else {
           ISOException.throwIt(SW_HASH_NOT_SET);
       }
   }

   private void get_sign(APDU apdu) {
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       if(sign_set_flag) {
           byte[] buffer = apdu.getBuffer();
           Util.arrayCopy(Sign, (short) 0, buffer, (short) 0, sign_len);
           apdu.setOutgoingAndSend((short) 0, sign_len);
       } else {
           ISOException.throwIt(SW_SIGN_NOT_SET);
       }
   }

   private void verify_sign(APDU apdu) {
       byte[] buffer = apdu.getBuffer();
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       apdu.setIncomingAndReceive();
       rsaCipher.init(rsaKey.getPublic(), Cipher.MODE_DECRYPT);
       short LC = rsaCipher.doFinal(Sign, (short) 0, sign_len, buffer, (short)0);
       apdu.setOutgoingAndSend((short)0,LC);
   }

   private void verify_pin(APDU apdu) {
       byte[] buffer = apdu.getBuffer();
       if(userPin.getTriesRemaining() == (byte)0)
           ISOException.throwIt(SW_CARD_IS_LOCKED);
       short LC = (byte)(apdu.setIncomingAndReceive());
       if ( userPin.check(buffer, ISO7816.OFFSET_CDATA, (byte)LC) == false )
           ISOException.throwIt(SW_VERIFICATION_FAILED);
   }

   private void change_pin(APDU apdu) {
       byte[] buffer = apdu.getBuffer();
       if(userPin.getTriesRemaining() == (byte)0)
           ISOException.throwIt(SW_CARD_IS_LOCKED);
       if ( ! userPin.isValidated() )
           ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
       short LC = (byte)(apdu.setIncomingAndReceive());
       if(LC > MAX_PIN_SIZE)
           ISOException.throwIt(SW_NEW_PIN_TOO_LONG);
       if(LC < MIN_PIN_SIZE)
           ISOException.throwIt(SW_NEW_PIN_TOO_SHORT);
       userPin.update(buffer, (short) ISO7816.OFFSET_CDATA, (byte)LC);
   }

   private void unlock_pin(APDU apdu){
       if(puk_try_count >= PUK_TRY_LIMIT){
           ISOException.throwIt(SW_PUK_VERIFICATION_REJECTED);
       }
       byte[] buffer = apdu.getBuffer();
       apdu.setIncomingAndReceive();
       if (Util.arrayCompare(PUK, (short) 0, buffer, (short) (ISO7816.OFFSET_CDATA), (short) PUK_LEN) == 0) {
           userPin.resetAndUnblock();
           puk_try_count = (byte) 0;
           return;
       } else {
           puk_try_count = (byte)(puk_try_count + (byte)1);
           ISOException.throwIt(SW_PUK_VERIFICATION_FAILED);
       }
   }

   private void generate_random(byte[] buffer,byte len){
       rnd.generateData(buffer, (short) 0, (short) len);
   }

   private void send_puk(APDU apdu){
       apdu.setIncomingAndReceive();
       byte[] buffer = apdu.getBuffer();
       Util.arrayCopy(PUK,(short)0,buffer,(short)0,(short)PUK_LEN);
       apdu.setOutgoingAndSend((short) 0, (short) PUK_LEN);
   }

}

附录2:GPShell 1.4.4 APDU:

mode_211
enable_trace
establish_context
enable_trace
enable_timer
card_connect
command time: 15 ms
select -AID E0E1E2E3E4E501
Command --> 00A4040007E0E1E2E3E4E501
Wrapped command --> 00A4040007E0E1E2E3E4E501
Response <-- 26759506800664A82A242E481CD645C59000
command time: 78 ms
send_apdu -sc 1 -APDU 80060000083132333400000000 // verify userPin
Command --> 80060000083132333400000000
Wrapped command --> 80060000083132333400000000
Response <-- 9000
send_APDU() returns 0x80209000 (9000: Success. No error.)
command time: 16 ms
send_apdu -sc 1 -APDU 8000000000 // initialize
Command --> 8000000000
Wrapped command --> 8000000000
send_APDU() returns 0x8010002F (A communications error with the smart card has been detected. Retry the operation.)

0 个答案:

没有答案