teichmann@5861: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5861: * Software engineering by Intevation GmbH teichmann@5861: * teichmann@5861: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5861: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5861: * documentation coming with Dive4Elements River for details. teichmann@5861: */ teichmann@5861: teichmann@5835: package org.dive4elements.river.client.server.auth.was; bjoern@2956: bjoern@2956: import java.io.ByteArrayInputStream; bjoern@2956: import java.security.cert.Certificate; bjoern@2956: import java.security.cert.CertificateException; bjoern@2956: import java.security.cert.CertificateFactory; bjoern@2956: bjoern@2956: import org.apache.commons.codec.binary.Base64; bjoern@2956: import org.apache.log4j.Logger; bjoern@2956: import org.jdom.Element; bjoern@2956: bjoern@2956: public class Signature { bjoern@2956: bjoern@2956: private static Logger logger = Logger.getLogger(Signature.class); bjoern@2956: bjoern@2956: private static final String XML_SIG_DIGEST_SHA1 = bjoern@2956: "http://www.w3.org/2000/09/xmldsig#sha1"; bjoern@2956: private static final String XML_SIG_SIGNATURE_RSA_SHA1 = bjoern@2956: "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; bjoern@2956: christian@2983: private final Element signature; bjoern@2956: private Certificate cert; bjoern@2956: private byte[] value; bjoern@2956: private byte[] digestvalue; bjoern@2956: private String reference; bjoern@2956: bjoern@2956: public Signature(Element signature) { bjoern@2956: this.signature = signature; bjoern@2956: this.parseSignatureInfo(); bjoern@2956: this.parseSignatureValue(); bjoern@2956: this.parseCertificate(); bjoern@2956: } bjoern@2956: bjoern@2956: private void parseSignatureInfo() { bjoern@2956: Element signatureinfo = this.signature.getChild("SignedInfo", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: if (signatureinfo != null) { bjoern@2956: Element signaturemethod = signatureinfo.getChild("SignatureMethod", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: String algorithm = signaturemethod.getAttributeValue("Algorithm"); bjoern@2956: if (!algorithm.equals(XML_SIG_SIGNATURE_RSA_SHA1)) { bjoern@2956: logger.warn("Unkown signature alorithm " + algorithm); bjoern@2956: } bjoern@2956: bjoern@2956: // There could be several references in XML-Sig spec but for me it bjoern@2956: // doesn't make sense to have more then one in a SAML Assertion bjoern@2956: Element reference = signatureinfo.getChild("Reference", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: // reference must be present but its better to check bjoern@2956: if (reference != null) { bjoern@2956: String digestvalue = reference.getChildText("DigestValue", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: String digestmethod = reference.getChildText("DigestMethod", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: if (!digestmethod.equals(XML_SIG_DIGEST_SHA1)) { bjoern@2956: logger.warn("Unknown digest method " + digestmethod); bjoern@2956: } bjoern@2956: this.digestvalue = Base64.decodeBase64(digestvalue); bjoern@2956: bjoern@2956: String referenceuri = reference.getAttributeValue("URI"); bjoern@2956: if (referenceuri.startsWith("#")) { bjoern@2956: this.reference = referenceuri.substring(1); bjoern@2956: } bjoern@2956: else { bjoern@2956: logger.warn("Unkown reference type " + referenceuri); bjoern@2956: this.reference = referenceuri; bjoern@2956: } bjoern@2956: } bjoern@2956: } bjoern@2956: } bjoern@2956: bjoern@2956: private void parseSignatureValue() { bjoern@2956: String signaturevalue = this.signature.getChildText("SignatureValue", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: this.value = Base64.decodeBase64(signaturevalue); bjoern@2956: } bjoern@2956: bjoern@2956: private void parseCertificate() { bjoern@2956: Element keyinfo = this.signature.getChild("KeyInfo", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: if (keyinfo != null) { bjoern@2956: Element data = keyinfo.getChild("X509Data", Namespaces.XML_SIG_NS); bjoern@2956: if (data != null) { bjoern@2956: String base64cert = data.getChildText("X509Certificate", bjoern@2956: Namespaces.XML_SIG_NS); bjoern@2956: if (base64cert != null) { bjoern@2956: byte[] bytes = Base64.decodeBase64(base64cert); bjoern@2956: try { bjoern@2956: CertificateFactory cf = CertificateFactory.getInstance( bjoern@2956: "X.509"); bjoern@2956: this.cert = cf.generateCertificate( bjoern@2956: new ByteArrayInputStream(bytes)); bjoern@2956: } bjoern@2956: catch(CertificateException e) { bjoern@2956: // should never occur bjoern@2956: logger.error(e); bjoern@2956: } bjoern@2956: } bjoern@2956: } bjoern@2956: } bjoern@2956: } bjoern@2956: bjoern@2956: public Certificate getCertificate() { bjoern@2956: return this.cert; bjoern@2956: } bjoern@2956: bjoern@2956: public byte[] getValue() { bjoern@2956: return this.value; bjoern@2956: } bjoern@2956: bjoern@2956: public String getReference() { bjoern@2956: // In theory there could be several references with digestvalues, ... bjoern@2956: return this.reference; bjoern@2956: } bjoern@2956: bjoern@2956: public byte[] getDigestValue() { bjoern@2956: return this.digestvalue; bjoern@2956: } bjoern@2956: } bjoern@2956: // vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: