首页 文章

在javacard apdu上发送一个byte []

提问于
浏览
0

我从主机应用程序发送一个byte []到javacard applet . 但是当我尝试通过命令缓冲区[ISO7816.OFFSET_CDATA]将其作为byte []检索时,我被告知我无法将字节转换为字节[] . 如何通过命令APDU从主机应用程序发送byte []并在另一端(javacard applet)将其检索为byte [] . 看来缓冲区[ISO7816.OFFSET_CDATA]返回字节 . 请参阅我对错误发生位置的评论 .

我的想法如下:主机应用程序将质询作为字节[]发送,由javacard小程序签名 . 请注意,签名要求挑战为byte [] . 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 回答

  • 2

    通常,您通过APDU接口发送字节 . Java或Java卡 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);
    

    发回签名的挑战 .


    如果您需要在稍后阶段保留挑战,那么您应该在构建Applet期间使用 JCSystem.makeTransientByteArray() 在RAM中创建一个字节数组,然后使用 Util.arrayCopy() 将字节值移动到挑战缓冲区中 . 但是,由于挑战是由offcard系统产生的,因此似乎没有任何需要 . offcard系统应该保持挑战,而不是卡 .


    你不应该再使用 ISO7816.OFFSET_CDATA 了;如果您使用更大的密钥大小生成更大的签名,因此它将不会返回正确的结果,因此需要使用扩展长度的APDU .

相关问题