Skip to content

Instantly share code, notes, and snippets.

@kjunichi
Created August 20, 2024 09:00
Show Gist options
  • Save kjunichi/1f6bb2677fe517c3930cc2e04cd89e83 to your computer and use it in GitHub Desktop.
Save kjunichi/1f6bb2677fe517c3930cc2e04cd89e83 to your computer and use it in GitHub Desktop.
SAMLValidation
import java.nio.file.Paths;
import java.security.Key;
import java.security.KeyException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Iterator;
import javax.xml.crypto.AlgorithmMethod;
import javax.xml.crypto.KeySelector;
import javax.xml.crypto.KeySelectorException;
import javax.xml.crypto.KeySelectorResult;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.XMLStructure;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class Main {
public void execute() throws Exception {
System.out.println("start");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
//Document document = builder.parse(Paths.get("test2.1.xml").toFile());
//Document document = builder.parse(Paths.get("test3.1.xml").toFile());
Document document = builder.parse(Paths.get("test3.xml").toFile());
//document.getDocumentElement().setIdAttributeNS(null, "ID", true);
//document.getDocumentElement().setIdAttribute("ID",true);
// 署名要素(Signature)の特定
Element sigNode = (Element) document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature").item(0);
String svalue = (String) sigNode.getElementsByTagName("SignatureValue").item(0).getTextContent();
System.out.println("svalue = "+svalue);
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
//sigNode.setIdAttribute("ID", true);
DOMValidateContext valContext = new DOMValidateContext(new RawX509KeySelector(), sigNode);
NodeList anl = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Assertion");
valContext.setIdAttributeNS((Element)anl.item(0), null, "ID");
System.out.println("valCon");
// unmarshal the XMLSignature
XMLSignature signature = fac.unmarshalXMLSignature(valContext);
// Validate the XMLSignature (generated above)
boolean coreValidity = signature.validate(valContext);
System.out.println("coreValidity = "+ coreValidity);
if(!coreValidity) {
boolean sv = signature.getSignatureValue().validate(valContext);
System.out.println("signature validation status: "+sv);
Iterator i = signature.getSignedInfo().getReferences().iterator();
for(int j =0;i.hasNext();j++) {
System.out.println("j = " +j);
boolean refValid = ((javax.xml.crypto.dsig.Reference) i.next()).validate(valContext);
System.out.println("ref[]"+j+"] validity status: "+ refValid);
}
}
System.out.println("end");
}
public static void main(String[] args) {
Main m = new Main();
try {
m.execute();
} catch (Exception e) {
System.out.println(e);
}
}
private static class KeyValueKeySelector extends KeySelector {
public KeySelectorResult select(KeyInfo keyInfo,
KeySelector.Purpose purpose,
AlgorithmMethod method,
XMLCryptoContext context)
throws KeySelectorException {
if (keyInfo == null) {
throw new KeySelectorException("Null KeyInfo object!");
}
System.out.println("keyInfo != null");
SignatureMethod sm = (SignatureMethod) method;
List<XMLStructure> list = keyInfo.getContent();
for (int i = 0; i < list.size(); i++) {
System.out.println("i = "+i);
XMLStructure xmlStructure = list.get(i);
if (xmlStructure instanceof X509Data) {
System.out.println(xmlStructure);
for(Object x509Content: ((X509Data)xmlStructure).getContent()) {
X509Certificate cert = (X509Certificate)x509Content;
System.out.println(cert.getPublicKey().toString());
return new SimpleKeySelectorResult(cert.getPublicKey());
}
}
if (xmlStructure instanceof KeyValue) {
System.out.println("xmlStructure instanceof KeyValue");
PublicKey pk = null;
try {
pk = ((KeyValue) xmlStructure).getPublicKey();
} catch (KeyException ke) {
throw new KeySelectorException(ke);
}
// make sure algorithm is compatible with method
if (algEquals(sm.getAlgorithm(), pk.getAlgorithm())) {
return new SimpleKeySelectorResult(pk);
}
} else {
System.out.println("");
}
}
System.out.println("Dame");
throw new KeySelectorException("No KeyValue element found!");
}
static boolean algEquals(String algURI, String algName) {
if (algName.equalsIgnoreCase("DSA") &&
algURI.equalsIgnoreCase("http://www.w3.org/2009/xmldsig11#dsa-sha256")) {
return true;
} else if (algName.equalsIgnoreCase("RSA") &&
algURI.equalsIgnoreCase("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256")) {
return true;
} else {
System.out.println("alg Ng");
return false;
}
}
}
public static class RawX509KeySelector extends KeySelector {
public KeySelectorResult select(KeyInfo keyInfo,
KeySelector.Purpose purpose,
AlgorithmMethod method,
XMLCryptoContext context)
throws KeySelectorException {
if (keyInfo == null) {
throw new KeySelectorException("Null KeyInfo object!");
}
// search for X509Data in keyinfo
Iterator<?> iter = keyInfo.getContent().iterator();
while (iter.hasNext()) {
XMLStructure kiType = (XMLStructure) iter.next();
if (kiType instanceof X509Data) {
X509Data xd = (X509Data) kiType;
Object[] entries = xd.getContent().toArray();
X509CRL crl = null;
// Looking for CRL before finding certificates
for (int i = 0; (i < entries.length && crl == null); i++) {
if (entries[i] instanceof X509CRL) {
crl = (X509CRL) entries[i];
}
}
Iterator<?> xi = xd.getContent().iterator();
while (xi.hasNext()) {
Object o = xi.next();
// skip non-X509Certificate entries
if (o instanceof X509Certificate) {
if ((purpose != KeySelector.Purpose.VERIFY) &&
(crl != null) &&
crl.isRevoked((X509Certificate)o)) {
continue;
} else {
return new SimpleKeySelectorResult
(((X509Certificate)o).getPublicKey());
}
}
}
}
}
throw new KeySelectorException("No X509Certificate found!");
}
}
private static class SimpleKeySelectorResult implements KeySelectorResult {
private PublicKey pk;
SimpleKeySelectorResult(PublicKey pk) {
this.pk = pk;
}
public Key getKey() {
return pk;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment