Skip to Main Content

Java Programming

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

Code failing to validate SAML Response on digest

jason.lyleFeb 1 2017 — edited Feb 1 2017

I am attempting to write some java code to verify the XML digital signature of a SAML response. I have verified the SAML response with other tools, so I know it is valid (excluding timing issues, not a factor to the digital signature). Below is the code I have used that I believe should be able to do this validation as well as the signature I am trying to validate.

When I run the code, I get the following output

Signature 0:
..Signature failed core validation
....signature validation status: true
....ref[0, #id14167335278088961501144300] validation status: false

Signature 1:
..Signature passed core validation
....signature validation status: true
....ref[0, #id141673352781342501524143644] validation status: true

I have no idea why the digest for reference id14167335278088961501144300 is not validating. Can anyone shed some light on what I am doing wrong?

Note: I am loading the XSD from a URL in this example so I don't have to include 4 XSD files in my question. However, because of this, the program can take a minute to run. I know this slowdown can be eliminated with local XSD files, it just is not feasible to do that way with the posted code.

XMLDSigVerifier.java:

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Iterator;

import javax.xml.XMLConstants;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.test.dsig.X509KeySelector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

import sun.security.provider.X509Factory;

public class XMLDSigVerifier {
  
public static void main (String[] args) throws ParserConfigurationException, SAXException, IOException, KeyStoreException, MarshalException, XMLSignatureException, NoSuchAlgorithmException, CertificateException {
  
//Get XML as a string, will be parameter in final version
  
String sigString = new String(Files.readAllBytes(Paths.get("src/signature.xml")), StandardCharsets.UTF_8);
  
InputSource is = new InputSource();
  is
.setCharacterStream(new StringReader(sigString));

  
//Get X509Certificate as a string, will be parameter in final version
  
String samlCertString= "-----BEGIN CERTIFICATE-----MIIDpDCCAoygAwIBAgIGAVjUwdcaMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi02NjI2ODExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMTYxMjA2MTUyOTIzWhcNMjYxMjA2MTUzMDIzWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNjYyNjgxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvLvIOJ11216IzuqZAbTiAoJy6WYxWuGXeUn4rpYkXLGOO0OoDahzhyquCQgLQC8mGlxCAq8gETQcdL+SX7lOlavHcNYiaYUD9IipMV0Kqt8TgfLO8UuYLb2jNNaQp+0tbcYv4SHpC4nXTndlo2nk3cJVELvXYfvjqKzDvtMwACy37Vc01GZbFQXhSEfBt9J2aQzLPFzH/RxKeOjzKW0kxWgYpfP0NZPtwkHrsdZaqpaR+039v5bckVSQvs0ZMz1Ionv+keWzM6YpQg7sF/OsvN05u0tkrGYDq1BoM9yH1h11bXrVhLvdOjo4bSVjeiAZ2LNOTurGO4JfH+CqT15c5wIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQC8jLBoAM35/6pwtUJ86BhYKvtjB6t3k+5uFRUx8rBWYL5atirRPF73W4f6AIkIp36zkS0os0RHuFK0bG2FPnjQj+FpErd8zji8PVFQ2LZ0WPNLYP7g7BWxAoNct2q0Iw3TACY6h722Cq6WS9ZP4O2iv3kkpo4A7JZvuf4yGGY2nVfx5nLZAmcEA9bZmHhcgmPLs2FBYpLYPs/5P4nd2HeiTJW+F6M75g9E4wG+sf3q2zqzh+AmV5kHffWnGx2MPdUmyFPU80zcDzEpodVU73YUxJIJScwjjXzytuQSB2FcM0TMqwYUq2qGVAPhBw4nnAxeScbMyMbFVDrNyMeejDhq-----END CERTIFICATE-----";
  X509Certificate samlCert
;

  samlCert
= parseCertificate(samlCertString);

  
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

  ks
.load(null, null);
  ks
.setCertificateEntry("a", samlCert);

  
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// File xsd = new File("src/saml-schema-protocol-2.0.xsd");
// Schema schema = schemaFactory.newSchema(xsd);
  
Schema schema = schemaFactory.newSchema(new URL("http://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd"));
  
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  dbf
.setNamespaceAware(true);
  dbf
.setSchema(schema);
  
DocumentBuilder builder = dbf.newDocumentBuilder();
  
Document doc = builder.parse(is);

  
NodeList signatureNodeList = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
  
Node signatureNode;

  
for (int sigIndex = 0; sigIndex < signatureNodeList.getLength(); sigIndex++) {
  signatureNode
= signatureNodeList.item(sigIndex);

  
if (sigIndex > 0) {
  
System.out.println("");
  
}
  
System.out.println("Signature " + sigIndex + ":");

  
DOMValidateContext valContext = new DOMValidateContext(new X509KeySelector(ks), signatureNode);
  valContext
.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);

  
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM");
  
XMLSignature signature = factory.unmarshalXMLSignature(valContext);
  
boolean coreValidity = signature.validate(valContext);

  
//Check Validity
  
if (coreValidity == false) {
  
System.err.println("..Signature failed core validation");
  
try {
  
//Sleep because of eclipse bug
  
Thread.sleep(5);
  
} catch (InterruptedException e) {
  e
.printStackTrace();
  
}
  
} else {
  
System.out.println("..Signature passed core validation");
  
}

  
//Check validity Parts
  
//Validity Part 1: Check Signature Validation
  
boolean sv = signature.getSignatureValue().validate(valContext);
  
System.out.println("....signature validation status: " + sv);

  
//Validity Part 2: Check References 
  
Iterator<?> i = signature.getSignedInfo().getReferences().iterator();
  
for (int j = 0; i.hasNext(); j++) {
  
Reference ref = (Reference) i.next();
  
boolean refValid = ref.validate(valContext);
  
System.out.println("....ref[" + j + ", " + ref.getURI() + "] validation status: " + refValid);
  
}
  
}
  
}

  
public static X509Certificate parseCertificate(String certStr) throws CertificateException{

  
byte [] decoded = Base64.decode(
  certStr
  
.replaceAll(X509Factory.BEGIN_CERT, "")
  
.replaceAll(X509Factory.END_CERT, "")
  
);

  
return (X509Certificate)CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(decoded));
  
}
}

signature.xml

<?xml version="1.0" encoding="UTF-8"?><saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://apps.surdellpartners.com/ords/kohls_wmj/workamajig/okta/acs/" ID="id14167335278088961501144300" IssueInstant="2017-01-27T18:21:53.483Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exk8y9z9v7FSYL34Y0h7</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#id14167335278088961501144300"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>7HyoOBjYlu8fbvSMNIY4O0fc6BhrkAUaPrF9EYWq/wE=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>dOhPiIwGvLJac40XW4x5Xn5soIzImitr/HAxRojDwSbAbfRp9t/VuRFT2Rat5oGgV3tWHedN7VBNpSGzBfZsYMBB/s/WYH0EQisTuS8i

Comments

InoL

Sounds like

Oscar Gordillo

Hello. I already applied the last PSE (PATCH_VERSION : 2020.11.12) and the problem is still happening.

Bozo

Have you installed APEX from apex_20.2.zip (All languages) or apex_20.2.en.zip (English language only)?
I had APEX 19.2 (All languages) then upgraded to APEX 20.2 (English language only) and that caused some NLS problems in my Apps. I removed 20.2 and installed again from All languages zip file, it solved problem.

User_WOO9D

Hey how is everything!
I have the same problem. When I change the language from English to Portuguese. I have the last path of apex 20.2. Has anyone managed to find the solution to this problem?

image.png

Oscar Gordillo

In my case, I opened a SR and after reviewing, the APEX dev team fixed it in a PSE, and after applying everything worked fine. So, apply the last PSE and if it is the same it should solve the problem.

jort2

I'm getting the same error in 23.1.4. The error begun when I tried to change NLS_COMP and NLS_SORT, but even after reverting the changes the error continues.

And I'm getting the error in every APEX application, not only in the one I changed.

jort2

Solved. Our DBA rebooted the server and now it works again

1 - 7

Post Details

Added on Feb 1 2017
0 comments
2,851 views