Created
November 22, 2022 20:36
-
-
Save as1an/7318f1a69d838c4aac15486a238c442c to your computer and use it in GitHub Desktop.
Simple enveloped-signature via santuario
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.ByteArrayInputStream; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.io.StringWriter; | |
import java.security.KeyStore; | |
import java.security.PrivateKey; | |
import java.security.Provider; | |
import java.security.Security; | |
import java.security.cert.X509Certificate; | |
import java.util.Enumeration; | |
import javax.xml.parsers.DocumentBuilder; | |
import javax.xml.parsers.DocumentBuilderFactory; | |
import javax.xml.parsers.ParserConfigurationException; | |
import javax.xml.transform.Transformer; | |
import javax.xml.transform.TransformerException; | |
import javax.xml.transform.TransformerFactory; | |
import javax.xml.transform.dom.DOMSource; | |
import javax.xml.transform.stream.StreamResult; | |
import org.apache.xml.security.encryption.XMLCipherParameters; | |
import org.apache.xml.security.exceptions.XMLSecurityException; | |
import org.apache.xml.security.keys.KeyInfo; | |
import org.apache.xml.security.signature.XMLSignature; | |
import org.apache.xml.security.signature.XMLSignatureException; | |
import org.apache.xml.security.transforms.Transforms; | |
import org.apache.xml.security.utils.Constants; | |
import org.w3c.dom.Document; | |
import org.w3c.dom.Element; | |
import org.w3c.dom.Node; | |
import org.w3c.dom.NodeList; | |
import org.xml.sax.SAXException; | |
import kz.gov.pki.kalkan.asn1.knca.KNCAObjectIdentifiers; | |
import kz.gov.pki.kalkan.asn1.pkcs.PKCSObjectIdentifiers; | |
import kz.gov.pki.kalkan.jce.provider.KalkanProvider; | |
import kz.gov.pki.kalkan.xmldsig.KncaXS; | |
public class SimpleEnvelopedXml { | |
public static void main(String[] args) { | |
String xmlString = "<root>\n" + "<person id=\"someid\">\n" + "<name>Абай Құнанбайұлы</name>\n" | |
+ "<iin>123456789012</iin>\n" + "</person>\n" + "</root>\n"; | |
String path = "/tmp/keystore.p12"; | |
char[] password = "123456".toCharArray(); | |
Provider provider = new KalkanProvider(); | |
Security.addProvider(provider); | |
KncaXS.loadXMLSecurity(); | |
try { | |
KeyStore keyStore = KeyStore.getInstance("PKCS12", provider); | |
keyStore.load(new FileInputStream(path), password); | |
Enumeration<String> aliases = keyStore.aliases(); | |
String alias = aliases.nextElement(); | |
PrivateKey key = (PrivateKey) keyStore.getKey(alias, password); | |
X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias); | |
SimpleEnvelopedXml sample = new SimpleEnvelopedXml(); | |
String signedXml = sample.createXmlSignature(key, cert, xmlString); | |
System.out.println(signedXml); | |
boolean result = sample.verifyXml(signedXml); | |
System.out.println("verified: " + result); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
public Document getDocument(String xml) throws ParserConfigurationException, SAXException, IOException { | |
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); | |
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); | |
dbf.setNamespaceAware(true); | |
DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); | |
return documentBuilder.parse(new ByteArrayInputStream(xml.getBytes())); | |
} | |
public String createXmlSignature(PrivateKey key, X509Certificate cert, String xmlSource) | |
throws ParserConfigurationException, SAXException, IOException, XMLSecurityException, TransformerException { | |
Document document = getDocument(xmlSource); | |
String signMethod; | |
String digestMethod; | |
String sigAlgOid = cert.getSigAlgOID(); | |
if (sigAlgOid.equals(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId())) { | |
signMethod = Constants.MoreAlgorithmsSpecNS + "rsa-sha256"; | |
digestMethod = XMLCipherParameters.SHA256; | |
} else if (sigAlgOid.equals(KNCAObjectIdentifiers.gost34311_95_with_gost34310_2004.getId())) { | |
signMethod = Constants.MoreAlgorithmsSpecNS + "gost34310-gost34311"; | |
digestMethod = Constants.MoreAlgorithmsSpecNS + "gost34311"; | |
} else if (sigAlgOid.equals(KNCAObjectIdentifiers.gost3411_2015_with_gost3410_2015_512.getId())) { | |
signMethod = "urn:ietf:params:xml:ns:pkigovkz:xmlsec:algorithms:gostr34102015-gostr34112015-512"; | |
digestMethod = "urn:ietf:params:xml:ns:pkigovkz:xmlsec:algorithms:gostr34112015-512"; | |
} else { | |
throw new IllegalArgumentException("Incorrect algorithm: " + sigAlgOid); | |
} | |
Transforms transforms = new Transforms(document); | |
transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE); | |
transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS); | |
XMLSignature xmlSignature = new XMLSignature(document, "", signMethod); | |
document.getFirstChild().appendChild(xmlSignature.getElement()); | |
xmlSignature.addDocument("", transforms, digestMethod); | |
xmlSignature.addKeyInfo(cert); | |
xmlSignature.sign(key); | |
return getXmlString(document); | |
} | |
private String getXmlString(Document document) throws TransformerException, IOException { | |
try (StringWriter os = new StringWriter()) { | |
TransformerFactory tf = TransformerFactory.newInstance(); | |
Transformer trans = tf.newTransformer(); | |
trans.transform(new DOMSource(document), new StreamResult(os)); | |
return os.toString(); | |
} | |
} | |
public boolean verifyXml(String xmlString) throws ParserConfigurationException, SAXException, IOException, | |
XMLSignatureException, XMLSecurityException { | |
Document doc = getDocument(xmlString); | |
Element sigElement = null; | |
Element rootEl = (Element) doc.getFirstChild(); | |
NodeList list = rootEl.getElementsByTagName("ds:Signature"); | |
if (list.getLength() == 0) { | |
throw new IllegalStateException("ds:Signature not found"); | |
} | |
Node sigNode = list.item(0); | |
sigElement = (Element) sigNode; | |
XMLSignature signature = new XMLSignature(sigElement, ""); | |
KeyInfo ki = signature.getKeyInfo(); | |
X509Certificate cert = ki.getX509Certificate(); | |
if (cert == null) { | |
throw new IllegalStateException("Certificate not found"); | |
} | |
return signature.checkSignatureValue(cert); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment