我的javacard小程序中有一个证书,主机应用程序请求验证来自卡小程序签名的主机应用程序的质询:
主机应用程序计算javacard applet的挑战,如下所示进行签名。
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, 0x00,bytes ,20 );
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());
javacard applet签署主机应用程序挑战并发回签名如下:
private void sign(APDU apdu) {
if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
else{
byte[] buffer = apdu.getBuffer();
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(buffer, offset,length, output, x);
//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);
}
}
要验证javacard applet签名,主机会从javacard请求javacard applet证书。证书(作为字节数组)是256字节,我收集它只能以长度为240的块发送.javacard小程序发送证书如下:
private void send_certificate (APDU apdu) {
if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
else{
apdu.setOutgoing();
apdu.setOutgoingLength((short)240);
apdu.sendBytesLong(certificate,(short)0,(short)240);
}
}
然后,主机应用程序以字节为单位接收证书并构造证书。此外,它还尝试使用证书验证签名的质询,如下所示:
//Get certificate
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);
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" );
}
}
我收到以下错误:
signature: 802800001438BBAE2CE7AD2498B0A8DA91634230A5D8324DBD4039F8376404AB1B7FF1B37DF63D22AFB2B6ABE37B31E8276B28427FA56FCF38EDF05FBC1EEF50C81A1C4F88560048D1C0E6D20B13000B384E0AE3AFED2751927F
CERTIFICATE:8030000000F0308201BD30820167A003020102020500B7D56095300D06092A864886F70D01010505003064310B3009060355040613024245310D300B06035504070C0447656E7431193017060355040A0C104B61486F2053696E742D4C696576656E31143012060355040B0C0B56616B67726F65702049543115301306035504030C0C4A616E20566F7373616572743020170D3130303232343039343330325A180F35313739303130393139323934325A3064310B3009060355040613024245310D300B06035504070C0447656E7431193017060355040A0C104B61486F2053696E742D4C696576656E31143012060355040B0C0B56
Exception in thread "main" java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Empty input
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:110)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
at be.msec.client.Client.main(Client.java:133)
Caused by: java.io.IOException: Empty input
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:106)
... 2 more
我将证书发送到主机应用程序的方法有可能是错误的吗?另外,我是否可能以错误的方式在主机应用程序中检索证书?我无法在此处获得我的解决方案:Could not parse certificate: java.io.IOException: Empty input X509Certificate