Отправка байта [] через javacard apdu - PullRequest
0 голосов
/ 27 мая 2018

Я отправляю байт [] из хост-приложения в апплет javacard.Но когда я пытаюсь получить его как byte [] через буфер команд [ISO7816.OFFSET_CDATA], мне говорят, что я не могу преобразовать байт в байт [].Как я могу отправить байт [] через команду APDU из хост-приложения и извлечь его как байт [] на другом конце (апплет javacard).Похоже, буфер [ISO7816.OFFSET_CDATA] возвращает байт.См. Мои комментарии о том, где происходит ошибка.

Моя идея заключается в следующем: хост-приложение отправляет запрос в виде байта [] для подписи апплетом javacard.Обратите внимание, что подпись требует, чтобы вызов был байтом [].Javacard подписывается следующим образом:

private void sign(APDU apdu) {
    if(!pin.isValidated()) ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
    else{
        byte [] buffer = apdu.getBuffer();
        byte numBytes = buffer[ISO7816.OFFSET_LC];
        byte byteRead =(byte)(apdu.setIncomingAndReceive());
        if ( ( numBytes != 20 ) || (byteRead != 20) )
             ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        byte [] challenge = buffer[ISO7816.OFFSET_CDATA];// error point cannot convert from byte to byte []
        byte [] output = new byte [64];
        short length = 64;
        short x =0;     
        Signature signature =Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
        signature.init(privKey, Signature.MODE_SIGN);
        short sigLength = signature.sign(challenge, offset,length, output, x); // challenge must be a byte []
        //This sequence of three methods sends the data contained in
        //'serial' with offset '0' and length 'serial.length'
        //to the host application.
        apdu.setOutgoing();
        apdu.setOutgoingLength((short)output.length);
        apdu.sendBytesLong(output,(short)0,(short)output.length);
    }
}

Вызов отправляется хост-приложением, как показано ниже:

byte [] card_signature=null;
SecureRandom random = SecureRandom . getInstance( "SHA1PRNG" ) ;
byte [] bytes = new byte [ 20 ] ;
random . nextBytes ( bytes) ;
CommandAPDU challenge;
ResponseAPDU resp3;
challenge =  new CommandAPDU(IDENTITY_CARD_CLA,SIGN_CHALLENGE, 0x00, 0x20,bytes);
resp3= c.transmit(challenge);
if(resp3.getSW()==0x9000) {
    card_signature = resp3.getData();
    String s= DatatypeConverter.printHexBinary(card_signature);
    System.out.println("signature: " + s);
} else System.out.println("Challenge signature error " + resp3.getSW());

1 Ответ

0 голосов
/ 27 мая 2018

Как правило, вы отправляете байты через интерфейс APDU.Java или Java Card byte[] - это конструкция, которая может содержать эти байты.Вот тут и вступает в силу буфер APDU: это байтовый массив, который содержит байты, отправленные через интерфейс APDU - или, по крайней мере, часть из них после вызова setIncomingAndReceive().

. Таким образом, проблема заключается в в пределах буфер APDU;вместо того, чтобы звонить:

short sigLength = signature.sign(challenge, offset,length, output, x);

, поэтому вы можете просто позвонить:

short sigLength = signature.sign(buffer, apdu.getOffsetCdata(), CHALLENGE_SIZE, buffer, START);

, где CHALLENGE_SIZE равно 20, а START просто равно нулю.

Тогда выможно использовать:

apdu.getOutgoingAndSend(START, sigLength);

, чтобы отправить обратно подписанный вызов.


Если вам нужно сохранить вызов на более позднем этапе, вам следует создать байтовый массив в ОЗУ, используя JCSystem.makeTransientByteArray() во время построения апплета, а затем используйте Util.arrayCopy() для перемещения значений байтов в буфер вызова.Тем не менее, поскольку проблема генерируется автономной системой, в этом нет никакой необходимости.Оффкартная система должна удерживать вызов, а не карточку.


Вам больше не следует использовать ISO7816.OFFSET_CDATA;он не вернет правильный результат, если вы будете использовать ключи большего размера, которые генерируют сигнатуры большего размера и, следовательно, требуют использования APDU расширенной длины.

...