Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. The ASF licenses this file to You * under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. For additional information regarding * copyright in this work, please see the NOTICE file in the top level * directory of this distribution. */ package org.apache.abdera2.security.xmlsec; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import org.apache.abdera2.Abdera; import org.apache.abdera2.model.Content; import org.apache.abdera2.model.Element; import org.apache.abdera2.model.Entry; import org.apache.abdera2.model.Link; import org.apache.abdera2.model.Source; import org.apache.abdera2.security.SecurityException; import org.apache.abdera2.security.SignatureOptions; import org.apache.abdera2.security.SignatureOptions.SignatureOptionsBuilder; import org.apache.abdera2.security.util.Constants; import org.apache.abdera2.security.util.SignatureBase; import org.apache.abdera2.common.iri.IRI; 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.w3c.dom.Node; import org.w3c.dom.NodeList; import com.google.common.collect.Iterables; public class XmlSignature extends SignatureBase { static { if (!org.apache.xml.security.Init.isInitialized()) org.apache.xml.security.Init.init(); } public XmlSignature() { super(Abdera.getInstance()); } public XmlSignature(Abdera abdera) { super(abdera); } @SuppressWarnings("unchecked") private <T extends Element> T _sign(T element, SignatureOptions options) throws XMLSecurityException { element.setBaseUri(element.getResolvedBaseUri()); org.w3c.dom.Element dom = fomToDom((Element) element.clone(), options); org.w3c.dom.Document domdoc = dom.getOwnerDocument(); PrivateKey signingKey = options.getSigningKey(); X509Certificate cert = options.getCertificate(); PublicKey pkey = options.getPublicKey(); IRI baseUri = element.getResolvedBaseUri(); XMLSignature sig = new XMLSignature(domdoc, (baseUri != null) ? baseUri.toString() : "", options.getSigningAlgorithm()); dom.appendChild(sig.getElement()); Transforms transforms = new Transforms(domdoc); transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE); transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS); sig.addDocument("", transforms, org.apache.xml.security.utils.Constants.ALGO_ID_DIGEST_SHA1); for (String ref : options.getReferences()) sig.addDocument(ref); if (options.isSignLinks()) { String[] rels = Iterables.toArray(options.getSignLinkRels(), String.class); List<Link> links = null; Content content = null; if (element instanceof Source) { links = (rels == null) ? ((Source) element).getLinks() : ((Source) element).getLinks(rels); } else if (element instanceof Entry) { links = (rels == null) ? ((Entry) element).getLinks() : ((Entry) element).getLinks(rels); content = ((Entry) element).getContentElement(); } if (links != null) { for (Link link : links) { sig.addDocument(link.getResolvedHref().toASCIIString()); } } if (content != null && content.getResolvedSrc() != null) sig.addDocument(content.getResolvedSrc().toASCIIString()); } if (cert != null) sig.addKeyInfo(cert); if (pkey != null) sig.addKeyInfo(pkey); sig.sign(signingKey); return (T) domToFom(dom, options); } public <T extends Element> T sign(T entry, SignatureOptions options) throws SecurityException { try { return (T) _sign(entry, options); } catch (Exception e) { throw new SecurityException(e); } } private boolean is_valid_signature(XMLSignature sig, SignatureOptions options) throws XMLSignatureException, XMLSecurityException { KeyInfo ki = sig.getKeyInfo(); if (ki != null) { X509Certificate cert = ki.getX509Certificate(); if (cert != null) { return sig.checkSignatureValue(cert); } else { PublicKey key = ki.getPublicKey(); if (key != null) { return sig.checkSignatureValue(key); } } } else if (options != null) { PublicKey key = options.getPublicKey(); X509Certificate cert = options.getCertificate(); if (key != null) return sig.checkSignatureValue(key); if (cert != null) return sig.checkSignatureValue(cert); } return false; } private <T extends Element> X509Certificate[] _getcerts(T element, SignatureOptions options) throws XMLSignatureException, XMLSecurityException { List<X509Certificate> certs = new ArrayList<X509Certificate>(); org.w3c.dom.Element dom = fomToDom((Element) element, options); NodeList children = dom.getChildNodes(); for (int n = 0; n < children.getLength(); n++) { try { Node node = children.item(n); if (node.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element el = (org.w3c.dom.Element) node; if (Constants.DSIG_NS.equals(el.getNamespaceURI()) && Constants.LN_SIGNATURE.equals(el.getLocalName())) { IRI baseUri = element.getResolvedBaseUri(); XMLSignature sig = new XMLSignature(el, (baseUri != null) ? baseUri.toString() : ""); if (is_valid_signature(sig, options)) { KeyInfo ki = sig.getKeyInfo(); if (ki != null) { X509Certificate cert = ki.getX509Certificate(); if (cert != null) certs.add(cert); } } } } } catch (Exception e) { } } return certs.toArray(new X509Certificate[certs.size()]); } public X509Certificate[] getValidSignatureCertificates(Element element, SignatureOptions options) throws SecurityException { try { return _getcerts(element, options); } catch (Exception e) { } return null; } public KeyInfo getSignatureKeyInfo(Element element, SignatureOptions options) throws SecurityException { KeyInfo ki = null; org.w3c.dom.Element dom = fomToDom((Element) element, options); NodeList children = dom.getChildNodes(); for (int n = 0; n < children.getLength(); n++) { try { Node node = children.item(n); if (node.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element el = (org.w3c.dom.Element) node; if (Constants.DSIG_NS.equals(el.getNamespaceURI()) && Constants.LN_SIGNATURE.equals(el.getLocalName())) { IRI baseUri = element.getResolvedBaseUri(); XMLSignature sig = new XMLSignature(el, (baseUri != null) ? baseUri.toString() : ""); ki = sig.getKeyInfo(); } } } catch (Exception e) { } } return ki; } private boolean _verify(Element element, SignatureOptions options) throws XMLSignatureException, XMLSecurityException { boolean answer = false; org.w3c.dom.Element dom = fomToDom((Element) element, options); NodeList children = dom.getChildNodes(); for (int n = 0; n < children.getLength(); n++) { Node node = children.item(n); if (node.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element el = (org.w3c.dom.Element) node; if (Constants.DSIG_NS.equals(el.getNamespaceURI()) && Constants.LN_SIGNATURE.equals(el.getLocalName())) { IRI baseUri = element.getResolvedBaseUri(); XMLSignature sig = new XMLSignature(el, (baseUri != null) ? baseUri.toString() : ""); answer = is_valid_signature(sig, options); } } } return answer; } public boolean verify(Element entry, SignatureOptions options) throws SecurityException { if (!isSigned(entry)) return false; try { return _verify(entry, options); } catch (Exception e) { throw new SecurityException(e); } } public SignatureOptionsBuilder getDefaultSignatureOptions() throws SecurityException { return XmlSignatureOptions.make().abdera(getAbdera()); } @SuppressWarnings("unchecked") public <T extends Element> T removeInvalidSignatures(T element, SignatureOptions options) throws SecurityException { List<org.w3c.dom.Element> remove = new ArrayList<org.w3c.dom.Element>(); org.w3c.dom.Element dom = fomToDom((Element) element, options); NodeList children = dom.getChildNodes(); for (int n = 0; n < children.getLength(); n++) { try { Node node = children.item(n); if (node.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element el = (org.w3c.dom.Element) node; if (Constants.DSIG_NS.equals(el.getNamespaceURI()) && Constants.LN_SIGNATURE.equals(el.getLocalName())) { IRI baseUri = element.getResolvedBaseUri(); XMLSignature sig = new XMLSignature(el, (baseUri != null) ? baseUri.toString() : ""); if (!is_valid_signature(sig, options)) { remove.add(el); } } } } catch (Exception e) { } } for (org.w3c.dom.Element el : remove) dom.removeChild(el); return (T) domToFom(dom, options); } }