Отправка данных подписи в ответном APDU — Java Card

Я хотел бы подписать некоторые данные (массив байтов MESSAGE) на моей карте Java, а затем вернуть подпись в ответном APDU. Мой код работает нормально (или, по крайней мере, я так думаю и возвращает 9000) без строки apdu.sendBytes(BAS, sSignLen), но когда я раскомментирую ее, я получаю неизвестную ошибку ( 0xC000002B (Неизвестная ошибка.)).

Когда я пытаюсь отправить другие данные в ответном APDU, он работает безупречно.

apdu.setIncomingAndReceive();
Util.arrayCopyNonAtomic(MESSAGE, (short) 0, buffer, (short) 0, (short) MESSAGE.length);
apdu.setOutgoingAndSend((short) 0, (short) MESSAGE.length);

Вот мой код. Что я делаю неправильно или упускаю? Благодарю вас!

public class TestApplet extends Applet {

    ...

    private final static byte SIGN = (byte) 0x01;

    ...

    private final static byte[] MESSAGE = new byte[] { 'M', 'e', 's', 's', 'a', 'g', 'e' };

    final static short BAS = 0;

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

        byte buffer[] = apdu.getBuffer();

        ...

        switch (buffer[ISO7816.OFFSET_INS]) {
        case SIGN:
            try {
                ECDSAKeyPair = Secp256k1Domain.getKeyPairParameter();
                ECDSAKeyPair.genKeyPair();

                ECDSAPublicKey = (ECPublicKey) ECDSAKeyPair.getPublic();
                ECDSAPrivateKey = (ECPrivateKey) ECDSAKeyPair.getPrivate();

                ECDSASignature = Signature.getInstance(Signature.ALG_ECDSA_SHA, false);

                short signLen = 0;

                byte[] signatureArray = new byte[70];

                ECDSASignature.init(ECDSAPrivateKey, Signature.MODE_SIGN);
                signLen = ECDSASignature.sign(MESSAGE, BAS, (short) MESSAGE.length, signatureArray, BAS);

                apdu.setIncomingAndReceive();
                Util.arrayCopyNonAtomic(signatureArray, (short) 0, buffer, (short) 0, (short) signatureArray.length);
                apdu.setOutgoingAndSend((short) 0, (short) signatureArray.length);
            } catch (CryptoException c) {
                short reason = c.getReason();
                ISOException.throwIt((short) ((short) (0x9C00) | reason));
            }

            break;

        ...

        return;
    }
}

person bp14    schedule 08.05.2015    source источник


Ответы (1)


Вероятно, signLen больше, чем значение Ne (неправильное название Le в спецификациях JavaCard). Кстати, вы также злоупотребляете значением Le, чтобы оно означало (short) MESSAGE.length. Ne указывает максимальное количество байтов, которые, как ожидается, будут отправлены обратно.

person Maarten Bodewes    schedule 08.05.2015
comment
Действительно, я использовал Le вместо (short) MESSAGE.length. Я обновил код. Благодарю вас! Я также думал, что проблема как-то связана с размерами данных. Как теперь мне сообщить карте, что ответ (то есть подпись) будет больше, чем значение Ne, то есть как мне установить для Ne значение signLen, чтобы я мог правильно получить ответный APDU? @Мартен Бодевес - person bp14; 09.05.2015
comment
Нельзя, не спросив карты/вашего приложения. Но большинство читателей позволяют Ne быть 256 байт (Le, кодировка Ne, тогда должна быть 00). Поскольку Ne — это максимальный размер, вы всегда можете установить Le равным 00 для любой команды, которая ожидает данные ответа. - person Maarten Bodewes; 09.05.2015
comment
Теперь это работает. Перед подписанием я создаю массив, который является моим выходным буфером, а после подписания копирую его содержимое в буфер. Я не знаю, почему буфер не может действовать как мой выходной буфер для подписи. Неважно. - person bp14; 10.05.2015
comment
Это должно быть возможно, но без дополнительного кода я не могу сказать. Рад, что это у вас получилось... - person Maarten Bodewes; 10.05.2015