Узнайте причину CryptoException в JavaCard

Я пытаюсь внедрить ECDSA в JavaCard (Eclipse 4.4.2, JC 2.2.1). Моя карта - Gemalto IDCore 3010, или, по крайней мере, так должно быть (после проверки кода ATR похоже, что это WM GX4 72 DHS TSA...).

В любом случае, если я не окружу строку objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192) с помощью try and catch, я получу неизвестную ошибку (send_APDU() возвращает 0x80206F00 (Unknown Ошибка ISO7816: 0x6F00)), но когда я его окружаю, он не возвращает ошибки (send_APDU() возвращает 0x80209000 (9000: Успех. Нет ошибки.)). Однако он должен перейти в блок catch, потому что остальные три строки в блоке try не выполняются.

Как я могу визуализировать сообщение об ошибке? Если я использую ISOException.throwIt(reason), я получаю сообщение Ошибка связи с интеллектуальной картой. Повторите попытку. несколько раз.

В этом потоке предлагается byte Reason = c. getReason(), но он не будет работать, даже если я приведу правую сторону к байту.

Благодарю вас!

Вот соответствующая часть моего кода.

public class ECDSATestApplet extends Applet {

    private final static byte CLS = (byte) 0xE0;
    private final static byte NOOP = (byte) 0x00;
    private final static byte GEN = (byte) 0x01;

    ...

    private final static byte[] HELLO_WORLD = new byte[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!' };

    private ECPrivateKey objECDSAPriKey = null;
    private ECPublicKey objECDSAPubKey = null;
    private KeyPair objECDSAKeyPair = null;
    private Signature objECDSASign = null;

    final static short BAS = 0;

    private ECDSATestApplet() {
    }

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

    public void process(APDU apdu) {
        if (this.selectingApplet())
            return;

        byte buffer[] = apdu.getBuffer();

        if (buffer[ISO7816.OFFSET_CLA] != CLS)
            ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);

        switch (buffer[ISO7816.OFFSET_INS]) {
        case NOOP:
            break;

        case GEN:
            try {
                // ------- ERROR LINE -------
                objECDSAKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
//              objECDSASign = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);
//              objECDSAKeyPair.genKeyPair();
//              objECDSAPriKey = (ECPrivateKey) objECDSAKeyPair.getPrivate();
//              objECDSAPubKey = (ECPublicKey) objECDSAKeyPair.getPublic();
                apdu.setIncomingAndReceive();
                Util.arrayCopyNonAtomic(HELLO_WORLD, (short) 0, buffer, (short) 0, (short) HELLO_WORLD.length);
                apdu.setOutgoingAndSend((short) 0, (short) HELLO_WORLD.length);
            } catch (CryptoException c) {
                short reason = c.getReason();
//              ISOException.throwIt(reason);
            }

            break;
        }
        return;
    }
}

person bp14    schedule 06.04.2015    source источник
comment
Что происходит, когда вы используете byte reason = c.getReason() ? Возвращает ли он какую-либо ошибку? когда? в процессе установки? или во время выполнения?   -  person Ebrahim Ghasemi    schedule 06.04.2015
comment
Причина — это число от 0 до 5. Читатель может запутаться, если ваша карта, например, возвращает 0x0001 в качестве слова состояния. Вместо этого попробуйте бросить ISOException.throwIt((short) (0x9C00 + причина)) .   -  person vojta    schedule 06.04.2015
comment
В моем предыдущем комментарии должно быть от 1 до 5, извините.   -  person vojta    schedule 07.04.2015
comment
@vojta Это может сбить с толку читателя: читателя или приложение на компьютере?   -  person TheGoodUser    schedule 07.04.2015
comment
@TheGoodUser Для читателя, правда. Читатели могут попытаться обработать слово состояния, как они иногда делают с 61xx или 6Cxx, к сожалению. В вашем апплете вы должны использовать только слова состояния из интервала, установленного ISO7816 (или стандартом ETSI для SIM-карт).   -  person vojta    schedule 07.04.2015
comment
@vojta Я написал апплет javacard, который возвращает 0x0001 при ответе на команду APDU Select и загружает его на две разные карты. Теперь, когда я выбираю свой апплет на карте A, он успешно возвращает 0x0001, а когда я выбираю тот же апплет на второй карте и использую тот же считыватель, передача завершается неудачно. Поэтому я думаю, что иногда это также связано с картой. т.е. все сбои при использовании SW=0x0001 связаны не только со считывателем. Правильно?   -  person TheGoodUser    schedule 07.04.2015
comment
@TheGoodUser Да, вы правы. Я просто хотел сказать, что неразумно использовать слова состояния вне интервала, указанного в стандартах (ISO, ETSI), потому что это может вызвать некоторые загадочные ошибки, зависящие от ридеров (мой опыт) и карт (ваш опыт).   -  person vojta    schedule 07.04.2015
comment
@Abraham Я получаю эту ошибку: unsupported String type constant. и это: unsupported parameter type String of invoked method <init>(java.lang.String) of class java.lang.Error.. Eclipse предлагает мне добавить приведение к «байту». @vojta С твоей версией я получаю это: unsupported int type constant..   -  person bp14    schedule 07.04.2015
comment
@bp14 Очистите и перестройте весь проект...   -  person vojta    schedule 07.04.2015
comment
@bp14 Извините, это должно работать: ISOException.throwIt((short) ((short) (0x9C00) | причина))   -  person vojta    schedule 07.04.2015
comment
Спасибо! У меня 9C03, так что нет такого алгоритма. Просто чтобы быть уверенным, я также проверил KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_512), и это сработало, поэтому похоже, что карта не поддерживает ECDSA.   -  person bp14    schedule 07.04.2015
comment
@ bp14, а как насчет ECC через F2M, вы пробовали? Смарт-карты обычно поддерживают только один из этих вариантов EC.   -  person vojta    schedule 07.04.2015
comment
Это тоже не работает. Я проверил например это: new KeyPair(KeyPair.ALG_EC_F2M , KeyBuilder.LENGTH_EC_F2M_113), и код ошибки снова 9C03.   -  person bp14    schedule 08.04.2015
comment
@vojta Если вы поместите этот код в качестве ответа, я могу его принять. ISOException.throwIt((short) ((short) (0x9C00) | reason))   -  person bp14    schedule 11.04.2015


Ответы (1)


Возможны две причины ваших неприятностей:

  1. Ваше слово состояния не соответствует словам состояния, рекомендованным ISO7816. Пытаться

    ISOException.throwIt((short) ((short) (0x9C00) | reason));
    

    вместо

    ISOException.throwIt(reason);
    
  2. Вы забыли установить параметры своей эллиптической кривой перед созданием новой пары ключей. Вы должны сгенерировать пару ключей EC следующим образом:

    KeyPair keyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_192);
    ECPrivateKey privKey = (ECPrivateKey) keyPair.getPrivate();
    ECPublicKey pubKey = (ECPublicKey) keyPair.getPublic();
    initDomainParams(pubKey);
    initDomainParams(privKey);
    keyPair.genKeyPair();
    

    куда

    private void initDomainParams(ECKey key) {
        key.setFieldFP(F, (short)0, (short)F.length);
        key.setA(A, (short)0, (short)A.length);
        key.setB(B, (short)0, (short)B.length);
        key.setG(G, (short)0, (short)G.length);
        key.setR(R, (short)0, (short)R.length);
    }
    

    с параметрами F, A, B, G, R эллиптической кривой, которую вы выбрали для своей подписи. См. список рекомендуемых кривых здесь: http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf

person vojta    schedule 07.04.2015