请看以下代码:
private void send_certificate (APDU apdu) {
if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
else{
apdu.setOutgoing();
apdu.setOutgoingLength((short)certificate.length);
apdu.sendBytesLong(certificate,(short)0,(short)certificate.length);
}
}
证书是javacard applet中的一个字节数组,其长度大于256.如何在不获取APDUException.BAD_LENGTH
的情况下发送它?
此外,在发送此字节数组时,如何从主机应用程序中检索此字节数组? 我在主机应用程序中尝试以下操作:
CommandAPDU card_cert;
ResponseAPDU resp4;
card_cert = new CommandAPDU(IDENTITY_CARD_CLA, SEND_CERTIFICATE, 0x00, 0x00);
resp4 = c.transmit(card_cert);
if(resp4.getSW()==0x9000) {
byte [] response = resp4.getData();
String certf= DatatypeConverter.printHexBinary(response);
System.out.println("CERTIFICATE:" + certf + "--"+response.length);
System.out.println(" signature to be verivied: " + DatatypeConverter.printHexBinary(card_signature));
CertificateFactory certFac = CertificateFactory.getInstance("X.509");
InputStream is = new ByteArrayInputStream(response);
X509Certificate cert = ( X509Certificate ) certFac .generateCertificate( is ) ;
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(cert.getPublicKey());
signature.update(card_signature);
if(card_signature !=null) {
boolean ok =signature.verify(card_signature);
if(ok==true)System.out.println("verification completed" );
}
}
当然,if(resp4.getSW()==0x9000)
之后没有任何内容执行,因为证书未成功发送到主机应用程序。如何实现这一目标?
在我的applet类实现ExtendedLength之后,我在send_certificate()方法中执行了以下操作:
private void send_certificate (APDU apdu) {
if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
else{ byte[] buffer = apdu.getBuffer();
short LE = apdu.setOutgoing();
short toSend = (short)certificate.length;
short cert_offset =0;
short len =240;
if (LE != toSend) {
apdu.setOutgoingLength(toSend);
}
while (toSend > 0) {
Util.arrayCopyNonAtomic(certificate, cert_offset, apdu.getBuffer(), (short)0, len);
apdu.sendBytes((short) 0, len);
toSend -= len;
cert_offset += len;
}
}
}
这不起作用:因响应代码28416而失败。
答案 0 :(得分:1)
您应该确保您的Java Card实现和阅读器都支持扩展长度。可能是这些实现已经抛出了阻碍使用全尺寸扩展长度的障碍:例如,实现可能(错误地)限制APDU的大小。
读者可能要求ATR指示延长的长度。 NFC芯片因未正确实现扩展长度而臭名昭着(而Android因其未启用功能而臭名昭着)。这可能不是您的问题,因为状态字似乎是由卡生成的。
Java Card的代码有错误,应该始终使用setOutgoingLength()
。在调用此方法时,您的代码似乎已抛出异常,因此我希望平台不支持您尝试发送的大小。除此之外,使用sendBytesLong
的初始代码看起来也是正确的。当然,您的Applet应该实现ExtendedLength
标记接口。
请注意,6F00
(您的状态代码,对于那些使用十六进制,而不是十进制)可能由卡上生成的任何未处理的运行时异常生成。因此,请确保在尝试解决问题时不会在其他位置创建问题。
遗憾的是,扩展长度是一个雷区。我们现在在2018年,智能卡世界似乎仍然无法发送32 / 64Ki -1字节或以上。是时候用我认为有意义的东西替换ISO / IEC 7816-4了。