0

I have a certificate in my javacard applet which the host application requests to verify challenges from the host application signed by the card applet:

  1. The host application computes challenges for the javacard applet to sign as follows.

            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());
    
  2. The javacard applet signs the host application challenges and sends back the signature as follows:

    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);
    }
    }
    
  3. To verify the javacard applet signature, the host requests the javacard applet certificate from the javacard. The certificate (as a byte array) is 256 bytes and I gather it can only be sent in blocks of lenghth 240. The javacard applet sends the certificate as follows:

    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);
            }
    
        }
    
  4. The host application then receives the certificate in bytes and constructs the certificate. In addition, it attempts to verify signed challenges with the certificate as follows:

    //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" );
    
            }
    
        }
    

I get the error below:

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

Is it possible that my approach to sending the certificate to the host application is wrong? Also, could I be retreiving the certficate in the host application in a wrong way? I could not get my solution here: Could not parse certificate: java.io.IOException: Empty input X509Certificate

4
  • The code is incomplete. Please include all the code that defines and uses resp2 in point 4, which is where the exception is actually thrown. Commented May 26, 2018 at 11:05
  • That was supposed to be resp4. I have just changed it and now I get a certificate with a reasonable length printed out. However, the error still persists. Commented May 26, 2018 at 12:37
  • I still see another resp2 in your code. Is that also a mistake? You should isolate your code into small methods to avoid this kind of wrong variable error at compile time. Commented May 26, 2018 at 12:40
  • Oopse! changed that to resp3. And the error is still there. Commented May 26, 2018 at 13:53

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.