【问题标题】:Sending a byte [] over javacard apdu通过 javacard apdu 发送一个字节 []
【发布时间】:2018-05-27 12:56:21
【问题描述】:

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

我的想法如下: 主机应用程序将质询作为字节 [] 发送,以由 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());

【问题讨论】:

    标签: digital-signature javacard apdu


    【解决方案1】:

    通常,您通过 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);
    

    发回签名的挑战。


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


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

    【讨论】:

    • @MartinPaljak RAM 到 RAM 复制不需要 - 原子性仅适用于写入持久内存。在某些运行时它实际上可能会更慢。如果我在 RAM 到 RAM 的 Applet 代码中看到它,我不会眨眼。
    猜你喜欢
    • 1970-01-01
    • 2021-05-26
    • 2018-06-13
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多