Could not parse certificate: java.io.IOException: Empty input X509Certificate
Asked Answered
A

5

22

I am getting the error given below when parsing the signature. Anybody has idea why the error is showing?

Note that:

  1. Using the same certificate I signed my own XML and verified which is working fine. That mean there is no issue with certificate.

  2. Client provided signed document not able to validate.

Errors:

Exception in thread "main" javax.xml.crypto.MarshalException: Cannot create X509Certificate
at org.jcp.xml.dsig.internal.dom.DOMX509Data.unmarshalX509Certificate(DOMX509Data.java:225)
at org.jcp.xml.dsig.internal.dom.DOMX509Data.<init>(DOMX509Data.java:116)
at org.jcp.xml.dsig.internal.dom.DOMKeyInfo.<init>(DOMKeyInfo.java:116)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.<init>(DOMXMLSignature.java:150)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshal(DOMXMLSignatureFactory.java:173)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshalXMLSignature(DOMXMLSignatureFactory.java:137)
at com.signing.ValidateSignedXML.main(ValidateSignedXML.java:126)
Caused by: java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Empty input
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:104)
at java.security.cert.CertificateFactory.generateCertificate(CertificateFactory.java:339)
at org.jcp.xml.dsig.internal.dom.DOMX509Data.unmarshalX509Certificate(DOMX509Data.java:223)
... 6 more
Caused by: java.io.IOException: Empty input
at sun.security.provider.X509Factory.engineGenerateCertificate(X509Factory.java:101)

Adding the code here for reference

package com.signing;

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.Iterator;

import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ValidateSignedXML {

    /**
     * @param args
     * @throws Exception 
     */
/**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        // Load the KeyStore and get the signing key and certificate.
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream("C:\\Program Files\\Java\\jre1.8.0_31\\bin\\newstore8.jks"), "changeit7".toCharArray());


        KeyStore.PrivateKeyEntry keyEntry =
            (KeyStore.PrivateKeyEntry) ks.getEntry
                ("newkey8", new KeyStore.PasswordProtection("changeit7".toCharArray()));
        X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");


        //Load the signed document.
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().parse
            (new FileInputStream("C:\\src\\com\\signing\\signed.xml"));


        // Find Signature element.
        NodeList nl =
            doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
        if (nl.getLength() == 0) {
            throw new Exception("Cannot find Signature element");
        }else{
            /*System.out.println("---- Start of Print Tag ----\n");
            for(int k=0;k<nl.getLength();k++){
                 printTags((Node)nl.item(k));
             }
            System.out.println("---- End of Print Tag ----\n");*/
        }

        // Create a DOMValidateContext and specify a KeySelector
        // and document context.
        DOMValidateContext valContext = new DOMValidateContext
            (new X509KeySelector(), nl.item(0));

        // Unmarshal the XMLSignature.
        XMLSignature signatures = fac.unmarshalXMLSignature(valContext);

        // Validate the XMLSignature.
        boolean coreValidity = signatures.validate(valContext);

        System.out.println("Signature Validate :"+coreValidity);

        // Check core validation status.
        if (coreValidity == false) {
            String validateError;
            validateError = "Signature core validation status:false";
            boolean sv = signatures.getSignatureValue().validate(valContext);
            validateError = validateError + " | Signature validation status:" + sv;
            if (sv == false || true) {
                validateError = validateError + " | References: ";
                // Check the validation status of each Reference.
                Iterator g = signatures.getSignedInfo().getReferences().iterator();
                for (int j = 0; g.hasNext(); j++) {

                    Reference r = (Reference) g.next();
                    boolean refValid = r.validate(valContext);
                    validateError = validateError + "{ref[" + r.getURI() + "] validity status: " + refValid + "}";
                }
            }
            throw new Exception(validateError);
        } else {
            System.out.println("Signature passed core validation");
        }

    }

}
Awash answered 7/7, 2015 at 17:30 Comment(4)
Thanks for replying,Yes I added the code in question itself. Its failing when unmarshal happening only for client signed xml.But if I use any unsigned xml file with same certificate,do sign and validate it is giving above error.Awash
look [here][1] [1]: #10594500 I think it will solve your problem.Ergograph
1.Thanks for replying but it's related with SSL connection which I doesnt need,2.This is earlier comment edit "But if I use any unsigned xml file with same certificate,do sign and validate it is working." typo issue.Awash
The certificate is empty in the XML. What's does the XML look like? How was it created?Yerxa
S
33

It's been a while since this post but I came here looking for this issue. In my case, the key was that the certificate was in a Base64-String.getBytes[] instead of a DECODED-Base64-String.getBytes[].

Hope it helps someone :)

Swindell answered 11/5, 2016 at 6:36 Comment(3)
Hi, can you clarify this a bit more?Chammy
Yeah, sure! The issue in my case was that I was trying to parse to a X509Certificate from a String that it wasn't a X509Certificate. It was a Base64 string that contains the data of the certificate so in order to parse it, I had to decode the string previously and then parse it to a X509.Swindell
To clarify this further, I used Base64.getDecoder().decode(certString) successfully when I got this error message.Grijalva
C
4

Error can be as simple as not having the BEGIN and END tags in your certificate set.

-----BEGIN CERTIFICATE-----
your cert data here
-----END CERTIFICATE-----
Calceiform answered 19/12, 2019 at 17:23 Comment(0)
A
2

After going through so many blogs nothing helped as such. Finally we confirmed the way client is doing his encryption and used the same jars used for our verification. I am not sure if this is correct answer or not but may help somebody who is trying hard to resolve this issue. It may give you some clue if not able to resolve above error after going through many sites. So try to use same jars which used for client encryption and get the compatible private key for your public key and add to pk12 file. Convert pk12 to jks which you can use for encryption and verification too which resolved our issue. Some process too

#**Create PKCS12 keystore from private key and public certificate.**
openssl pkcs12 -export -name myservercert -in selfsigned.crt -inkey server.key -out keystore.p12
#**Convert PKCS12 keystore into a JKS keystore**
keytool -importkeystore -destkeystore mykeystore.jks -srckeystore keystore.p12 -srcstoretype pkcs12 -alias myservercer

Good luck guys.

Awash answered 20/7, 2015 at 15:8 Comment(1)
None of this addresses an empty certificate in the XML.Yerxa
B
0

In my case, the x509 certificate in java String was one liner as below:

String x509Cert = "-----BEGIN CERTIFICATE-----<cert-data>-----END CERTIFICATE-----";

I had to create expected String by adding \r a carriage return and \n a line feed character for begin & end certs, like below:

"-----BEGIN CERTIFICATE-----\r\n<cert-data>\r\n-----END CERTIFICATE-----";

Psuedo Code:

1. Get cert data substring between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.

2. Create String by adding System.lineSeparator() such that
a. -----BEGINE CERTIFICATE-----
b. System.lineSeparator()
c. cert data from pt 1.
d. System.lineSeparator()
e. -----END CERTIFICATE-----

Brindabrindell answered 2/5, 2024 at 9:19 Comment(0)
F
-3

The error occurs when the content of the certificate is not correct. Reference: enter link description here

Fiasco answered 25/10, 2023 at 12:49 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.