How to verify aadhar XML signature with the help of public key certificate in Java?

833 views Asked by At

I am working on Aadhaar Paperless Offline e-kyc, trying to validate aadhaar XML signature using public key certificate. But I'm not sure is this the right way to do. Below is the java code for the reference.

public static void validateXMLSignature() throws Exception {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder db = dbf.newDocumentBuilder();

    ClassLoader classLoader = AadhaarXMLSignatureValidation.class.getClassLoader();

    
    File file1 = new File("path-to-xml-file/aadhaar.xml");
    Document document = db.parse(file1);
    document.normalizeDocument();

    // Find Signature element
    NodeList nl =
        document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
    if (nl.getLength() == 0) {
        throw new Exception("Cannot find Signature element");
    }

    FileInputStream fin = new FileInputStream("path-to-certificate-file/certificate.cer");
    CertificateFactory f = CertificateFactory.getInstance("X.509");
    X509Certificate certificate = (X509Certificate)f.generateCertificate(fin);
    PublicKey publicKey = certificate.getPublicKey();

    // Create a DOM XMLSignatureFactory that will be used to unmarshal the
    // document containing the XMLSignature
    XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

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

    // unmarshal the XMLSignature
    XMLSignature signature = fac.unmarshalXMLSignature(valContext);

    // Validate the XMLSignature (generated above)
    boolean coreValidity = signature.validate(valContext);

    //    Check core validation status
    if (!coreValidity) {
        System.err.println("Signature failed core validation");
    } else {
        System.out.println("Signature passed core validation");
    }
}

can anyone tell me what I'm missing? Here is the link to Aadhaar Paperless Offline e-kyc tutorial https://uidai.gov.in/ecosystem/authentication-devices-documents/about-aadhaar-paperless-offline-e-kyc.html

2

There are 2 answers

0
Dharmik Joshi On

You can try using below method to extract X509Certificate from the certificate string.

private static X509Certificate getCertificateFromFile(String aadhaarCertificateString) throws GeneralSecurityException {
    CertificateFactory certFactory = CertificateFactory.getInstance(X509_CERTIFICATE_TYPE);
    InputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(aadhaarCertificateString));
    return (X509Certificate) certFactory.generateCertificate(inputStream);
}
0
SidPro On

i also faced some issues while validating aadhaar XML signature. just sharing working code snippet here.

public static final String PEM_FILE_BEGIN = "\r\n-----BEGIN CERTIFICATE-----\r\n";

public static final String PEM_FILE_END = "\r\n-----END CERTIFICATE-----\r\n";

important is to append BEGIN and END format in public key certificate and it's already base64 string so no need to decode the same.

public class AadhaarPaperlessOfflineEKYC {


public boolean verify() {

    String filePath = "pathTo/offlineaadhaar.xml";
    boolean verificationResult = false;

    try {

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);

        Document signedDocument = dbf.newDocumentBuilder().parse(new File(filePath));

        NodeList signatureNodeList = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
        NodeList X509CertificateNodeList = signedDocument.getElementsByTagName("X509Certificate");

        if (signatureNodeList.getLength() == 0 || X509CertificateNodeList.getLength() == 0) {
            throw new IllegalArgumentException("Cannot find Signature element");
        }

        String publicKeyFile = X509CertificateNodeList.item(0).getTextContent();
        publicKeyFile = Constants.PEM_FILE_BEGIN + publicKeyFile + Constants.PEM_FILE_END;

        XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

        DOMValidateContext valContext = new DOMValidateContext(getCertificateFromString(publicKeyFile).getPublicKey(), signatureNodeList.item(0));
        XMLSignature signature = fac.unmarshalXMLSignature(valContext);

        verificationResult = signature.validate(valContext);

    } catch (Exception e) {
        log.error("Error while verifying digital signature: " + e);
        e.printStackTrace();
    }

    return verificationResult;
}


private static X509Certificate getCertificateFromString(String aadhaarCertificateString) throws GeneralSecurityException {
    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
    InputStream inputStream = new ByteArrayInputStream(aadhaarCertificateString.getBytes());
    return (X509Certificate) certFactory.generateCertificate(inputStream);
}