java.security.cert.CertificateException: Не удалось проанализировать сертификат: java.io.IOException: Пустой ввод - PullRequest
0 голосов
/ 26 мая 2018

В моем апплете javacard есть сертификат, который хост-приложение запрашивает для проверки вызовов из хост-приложения, подписанного апплетом карты:

  1. Хост-приложение вычисляет вызовы для апплета javacardподписать следующим образом.

            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. Апплет javacard подписывает вызовы хост-приложения и отправляет обратно подпись следующим образом:

    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. Для проверки подписи апплета javacard хост запрашивает сертификат апплета javacard у javacard.Сертификат (в виде байтового массива) составляет 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);
            }
    
        }
    
  4. Затем хост-приложение получает сертификат в байтах и ​​создает его.Кроме того, он пытается проверить подписанные запросы с помощью сертификата следующим образом:

    //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

Возможно ли, что мойподход к отправке сертификата на хост приложения неверен?Кроме того, могу ли я получить сертификат в хост-приложении неверным способом?Я не смог получить свое решение здесь: Не удалось разобрать сертификат: java.io.IOException: Пустой ввод X509Сертификат

...