Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java?rev=1617141&view=auto ============================================================================== --- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java (added) +++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java Sun Aug 10 18:25:10 2014 @@ -0,0 +1,194 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + 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. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.security.InvalidAlgorithmParameterException; +import java.security.Key; +import java.security.KeyException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dom.DOMCryptoContext; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.dom.DOMSignContext; +import javax.xml.crypto.dsig.keyinfo.KeyInfo; +import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; +import javax.xml.crypto.dsig.keyinfo.KeyValue; +import javax.xml.crypto.dsig.keyinfo.X509Data; + +import org.apache.poi.poifs.crypt.dsig.HorribleProxy; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMKeyInfoIf; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.w3.x2000.x09.xmldsig.ObjectType; +import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3c.dom.Node; + +/** + * Signature Facet implementation that adds ds:KeyInfo to the XML signature. + * + * @author Frank Cornelis + * + */ +public class KeyInfoSignatureFacet implements SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class); + + private final boolean includeEntireCertificateChain; + + private final boolean includeIssuerSerial; + + private final boolean includeKeyValue; + + /** + * Main constructor. + * + * @param includeEntireCertificateChain + * @param includeIssuerSerial + * @param includeKeyValue + */ + public KeyInfoSignatureFacet(boolean includeEntireCertificateChain, + boolean includeIssuerSerial, boolean includeKeyValue) { + this.includeEntireCertificateChain = includeEntireCertificateChain; + this.includeIssuerSerial = includeIssuerSerial; + this.includeKeyValue = includeKeyValue; + } + + public void postSign(SignatureType signatureElement, + List<X509Certificate> signingCertificateChain) { + LOG.log(POILogger.DEBUG, "postSign"); + + List<ObjectType> objList = signatureElement.getObjectList(); + + /* + * Make sure we insert right after the ds:SignatureValue element, just + * before the first ds:Object element. + */ + Node nextSibling = (objList.isEmpty()) ? null : objList.get(0).getDomNode(); + + /* + * Construct the ds:KeyInfo element using JSR 105. + */ + String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI"); + Provider xmlDSigProv; + try { + xmlDSigProv = (Provider) Class.forName(providerName).newInstance(); + } catch (Exception e) { + throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!", e); + } + + KeyInfoFactory keyInfoFactory = KeyInfoFactory.getInstance("DOM", xmlDSigProv); + List<Object> x509DataObjects = new LinkedList<Object>(); + X509Certificate signingCertificate = signingCertificateChain.get(0); + + List<Object> keyInfoContent = new LinkedList<Object>(); + + if (this.includeKeyValue) { + KeyValue keyValue; + try { + keyValue = keyInfoFactory.newKeyValue(signingCertificate.getPublicKey()); + } catch (KeyException e) { + throw new RuntimeException("key exception: " + e.getMessage(), e); + } + keyInfoContent.add(keyValue); + } + + if (this.includeIssuerSerial) { + x509DataObjects.add(keyInfoFactory.newX509IssuerSerial( + signingCertificate.getIssuerX500Principal().toString(), + signingCertificate.getSerialNumber())); + } + + if (this.includeEntireCertificateChain) { + for (X509Certificate certificate : signingCertificateChain) { + x509DataObjects.add(certificate); + } + } else { + x509DataObjects.add(signingCertificate); + } + + if (false == x509DataObjects.isEmpty()) { + X509Data x509Data = keyInfoFactory.newX509Data(x509DataObjects); + keyInfoContent.add(x509Data); + } + KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent); + DOMKeyInfoIf domKeyInfo; + try { + domKeyInfo = HorribleProxy.newProxy(DOMKeyInfoIf.class, keyInfo); + } catch (Exception e) { + throw new RuntimeException("DOMKeyInfo instance error: " + e.getMessage(), e); + } + + Key key = new Key() { + private static final long serialVersionUID = 1L; + + public String getAlgorithm() { + return null; + } + + public byte[] getEncoded() { + return null; + } + + public String getFormat() { + return null; + } + }; + + DOMSignContext domSignContext = new DOMSignContext(key, signatureElement.getDomNode()); + DOMCryptoContext domCryptoContext = domSignContext; + String signatureNamespacePrefix = "xd"; + try { + domKeyInfo.marshal(signatureElement.getDomNode(), nextSibling, + signatureNamespacePrefix, domCryptoContext); + } catch (MarshalException e) { + throw new RuntimeException("marshall error: " + e.getMessage(), e); + } + } + + public void preSign(XMLSignatureFactory signatureFactory, + String signatureId, + List<X509Certificate> signingCertificateChain, + List<Reference> references, + List<XMLObject> objects + ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + // empty + } + + public Map<String,String> getNamespacePrefixMapping() { + Map<String,String> map = new HashMap<String,String>(); + // map.put("xd", "http://www.w3.org/2000/09/xmldsig#"); + return map; + } + +} \ No newline at end of file
Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java?rev=1617141&view=auto ============================================================================== --- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java (added) +++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java Sun Aug 10 18:25:10 2014 @@ -0,0 +1,541 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + 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. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +import javax.xml.crypto.XMLStructure; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Manifest; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.SignatureProperties; +import javax.xml.crypto.dsig.SignatureProperty; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageNamespaces; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService; +import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec; +import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService; +import org.apache.poi.poifs.crypt.dsig.spi.Constants; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.xmlbeans.XmlException; +import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime; +import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument; +import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1; +import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document; + +/** + * Office OpenXML Signature Facet implementation. + * + * @author fcorneli + * @see http://msdn.microsoft.com/en-us/library/cc313071.aspx + */ +public class OOXMLSignatureFacet implements SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class); + + public static final String OOXML_DIGSIG_NS = "http://schemas.openxmlformats.org/package/2006/digital-signature"; + public static final String OFFICE_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig"; + + private final XmlSignatureService signatureService; + + private final Date clock; + + private final HashAlgorithm hashAlgo; + + /** + * Main constructor. + */ + public OOXMLSignatureFacet(XmlSignatureService signatureService, Date clock, HashAlgorithm hashAlgo) { + this.signatureService = signatureService; + this.clock = (clock == null ? new Date() : clock); + this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo); + } + + public void preSign(XMLSignatureFactory signatureFactory, + String signatureId, + List<X509Certificate> signingCertificateChain, + List<Reference> references, List<XMLObject> objects) + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + LOG.log(POILogger.DEBUG, "pre sign"); + addManifestObject(signatureFactory, signatureId, references, objects); + addSignatureInfo(signatureFactory, signatureId, references, objects); + } + + private void addManifestObject(XMLSignatureFactory signatureFactory, + String signatureId, List<Reference> references, + List<XMLObject> objects) throws NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + Manifest manifest = constructManifest(signatureFactory); + String objectId = "idPackageObject"; // really has to be this value. + List<XMLStructure> objectContent = new LinkedList<XMLStructure>(); + objectContent.add(manifest); + + addSignatureTime(signatureFactory, signatureId, objectContent); + + objects.add(signatureFactory.newXMLObject(objectContent, objectId, + null, null)); + + DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null); + Reference reference = signatureFactory.newReference("#" + objectId, + digestMethod, null, "http://www.w3.org/2000/09/xmldsig#Object", + null); + references.add(reference); + } + + private Manifest constructManifest(XMLSignatureFactory signatureFactory) + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + List<Reference> manifestReferences = new ArrayList<Reference>(); + + try { + addManifestReferences(signatureFactory, manifestReferences); + } catch (Exception e) { + throw new RuntimeException("error: " + e.getMessage(), e); + } + + return signatureFactory.newManifest(manifestReferences); + } + + private void addManifestReferences(XMLSignatureFactory signatureFactory, List<Reference> manifestReferences) + throws IOException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException, URISyntaxException, XmlException { + + OPCPackage ooxml = this.signatureService.getOfficeOpenXMLDocument(); + List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART); + + + DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null); + Set<String> digestedPartNames = new HashSet<String>(); + for (PackagePart pp : relsEntryNames) { + String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1"); + + PackageRelationshipCollection prc; + try { + prc = new PackageRelationshipCollection(ooxml); + prc.parseRelationshipsPart(pp); + } catch (InvalidFormatException e) { + throw new IOException("Invalid relationship descriptor: "+pp.getPartName().getName(), e); + } + + RelationshipTransformParameterSpec parameterSpec = new RelationshipTransformParameterSpec(); + for (PackageRelationship relationship : prc) { + String relationshipType = relationship.getRelationshipType(); + + if (TargetMode.EXTERNAL == relationship.getTargetMode()) { + /* + * ECMA-376 Part 2 - 3rd edition + * 13.2.4.16 Manifest Element + * "The producer shall not create a Manifest element that references any data outside of the package." + */ + continue; + } + + if (!isSignedRelationship(relationshipType)) continue; + + parameterSpec.addRelationshipReference(relationship.getId()); + + // TODO: find a better way ... + String partName = baseUri + relationship.getTargetURI().toString(); + partName = new URI(partName).normalize().getPath().replace('\\', '/'); + LOG.log(POILogger.DEBUG, "part name: " + partName); + + String contentType; + try { + PackagePartName relName = PackagingURIHelper.createPartName(partName); + PackagePart pp2 = ooxml.getPart(relName); + contentType = pp2.getContentType(); + } catch (InvalidFormatException e) { + throw new IOException(e); + } + if (relationshipType.endsWith("customXml") + && !(contentType.equals("inkml+xml") || contentType.equals("text/xml"))) { + LOG.log(POILogger.DEBUG, "skipping customXml with content type: " + contentType); + continue; + } + + if (!digestedPartNames.contains(partName)) { + // We only digest a part once. + String uri = partName + "?ContentType=" + contentType; + Reference reference = signatureFactory.newReference(uri, digestMethod); + manifestReferences.add(reference); + digestedPartNames.add(partName); + } + } + + if (parameterSpec.hasSourceIds()) { + List<Transform> transforms = new LinkedList<Transform>(); + transforms.add(signatureFactory.newTransform( + RelationshipTransformService.TRANSFORM_URI, + parameterSpec)); + transforms.add(signatureFactory.newTransform( + CanonicalizationMethod.INCLUSIVE, + (TransformParameterSpec) null)); + String uri = pp.getPartName().getName() + + "?ContentType=application/vnd.openxmlformats-package.relationships+xml"; + Reference reference = signatureFactory.newReference(uri, digestMethod, transforms, null, null); + manifestReferences.add(reference); + } + } + } + + + private void addSignatureTime(XMLSignatureFactory signatureFactory, + String signatureId, + List<XMLStructure> objectContent) { + /* + * SignatureTime + */ + DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + fmt.setTimeZone(TimeZone.getTimeZone("UTC")); + String nowStr = fmt.format(this.clock); + LOG.log(POILogger.DEBUG, "now: " + nowStr); + + SignatureTimeDocument sigTime = SignatureTimeDocument.Factory.newInstance(); + CTSignatureTime ctTime = sigTime.addNewSignatureTime(); + ctTime.setFormat("YYYY-MM-DDThh:mm:ssTZD"); + ctTime.setValue(nowStr); + + // TODO: find better method to have xmlbeans + export the prefix + Node n = ctTime.getDomNode(); + setPrefix(ctTime, PackageNamespaces.DIGITAL_SIGNATURE, "mdssi"); + + List<XMLStructure> signatureTimeContent = new LinkedList<XMLStructure>(); + signatureTimeContent.add(new DOMStructure(n)); + SignatureProperty signatureTimeSignatureProperty = signatureFactory + .newSignatureProperty(signatureTimeContent, "#" + signatureId, + "idSignatureTime"); + List<SignatureProperty> signaturePropertyContent = new LinkedList<SignatureProperty>(); + signaturePropertyContent.add(signatureTimeSignatureProperty); + SignatureProperties signatureProperties = signatureFactory + .newSignatureProperties(signaturePropertyContent, + "id-signature-time-" + this.clock.getTime()); + objectContent.add(signatureProperties); + } + + private void addSignatureInfo(XMLSignatureFactory signatureFactory, + String signatureId, List<Reference> references, + List<XMLObject> objects) throws NoSuchAlgorithmException, + InvalidAlgorithmParameterException { + List<XMLStructure> objectContent = new LinkedList<XMLStructure>(); + + SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance(); + CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1(); + ctSigV1.setManifestHashAlgorithm("http://www.w3.org/2000/09/xmldsig#sha1"); + Node n = ctSigV1.getDomNode(); + ((Element)n).setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig"); + + List<XMLStructure> signatureInfoContent = new LinkedList<XMLStructure>(); + signatureInfoContent.add(new DOMStructure(n)); + SignatureProperty signatureInfoSignatureProperty = signatureFactory + .newSignatureProperty(signatureInfoContent, "#" + signatureId, + "idOfficeV1Details"); + + List<SignatureProperty> signaturePropertyContent = new LinkedList<SignatureProperty>(); + signaturePropertyContent.add(signatureInfoSignatureProperty); + SignatureProperties signatureProperties = signatureFactory + .newSignatureProperties(signaturePropertyContent, null); + objectContent.add(signatureProperties); + + String objectId = "idOfficeObject"; + objects.add(signatureFactory.newXMLObject(objectContent, objectId, + null, null)); + + DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null); + Reference reference = signatureFactory.newReference("#" + objectId, + digestMethod, null, "http://www.w3.org/2000/09/xmldsig#Object", + null); + references.add(reference); + } + + public void postSign(SignatureType signatureElement, + List<X509Certificate> signingCertificateChain) { + // empty + } + + public static String getRelationshipReferenceURI(String zipEntryName) { + + return "/" + + zipEntryName + + "?ContentType=application/vnd.openxmlformats-package.relationships+xml"; + } + + public static String getResourceReferenceURI(String resourceName, + String contentType) { + + return "/" + resourceName + "?ContentType=" + contentType; + } + + public static String[] contentTypes = { + + /* + * Word + */ + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", + "application/vnd.openxmlformats-officedocument.theme+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", + "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", + + /* + * Word 2010 + */ + "application/vnd.ms-word.stylesWithEffects+xml", + + /* + * Excel + */ + "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", + + /* + * Powerpoint + */ + "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml", + "application/vnd.openxmlformats-officedocument.presentationml.slide+xml", + "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml", + + /* + * Powerpoint 2010 + */ + "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml", + "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml" }; + + public static boolean isSignedRelationship(String relationshipType) { + LOG.log(POILogger.DEBUG, "relationship type: " + relationshipType); + for (String signedTypeExtension : signed) { + if (relationshipType.endsWith(signedTypeExtension)) { + return true; + } + } + if (relationshipType.endsWith("customXml")) { + LOG.log(POILogger.DEBUG, "customXml relationship type"); + return true; + } + return false; + } + + public Map<String,String> getNamespacePrefixMapping() { + Map<String,String> m = new HashMap<String,String>(); + m.put("mdssi", OOXML_DIGSIG_NS); + m.put("xd", "http://uri.etsi.org/01903/v1.3.2#"); + return m; + } + + + /** + * Office 2010 list of signed types (extensions). + */ + public static String[] signed = { "powerPivotData", // + "activeXControlBinary", // + "attachedToolbars", // + "connectorXml", // + "downRev", // + "functionPrototypes", // + "graphicFrameDoc", // + "groupShapeXml", // + "ink", // + "keyMapCustomizations", // + "legacyDiagramText", // + "legacyDocTextInfo", // + "officeDocument", // + "pictureXml", // + "shapeXml", // + "smartTags", // + "ui/altText", // + "ui/buttonSize", // + "ui/controlID", // + "ui/description", // + "ui/enabled", // + "ui/extensibility", // + "ui/helperText", // + "ui/imageID", // + "ui/imageMso", // + "ui/keyTip", // + "ui/label", // + "ui/lcid", // + "ui/loud", // + "ui/pressed", // + "ui/progID", // + "ui/ribbonID", // + "ui/showImage", // + "ui/showLabel", // + "ui/supertip", // + "ui/target", // + "ui/text", // + "ui/title", // + "ui/tooltip", // + "ui/userCustomization", // + "ui/visible", // + "userXmlData", // + "vbaProject", // + "wordVbaData", // + "wsSortMap", // + "xlBinaryIndex", // + "xlExternalLinkPath/xlAlternateStartup", // + "xlExternalLinkPath/xlLibrary", // + "xlExternalLinkPath/xlPathMissing", // + "xlExternalLinkPath/xlStartup", // + "xlIntlMacrosheet", // + "xlMacrosheet", // + "customData", // + "diagramDrawing", // + "hdphoto", // + "inkXml", // + "media", // + "slicer", // + "slicerCache", // + "stylesWithEffects", // + "ui/extensibility", // + "chartColorStyle", // + "chartLayout", // + "chartStyle", // + "dictionary", // + "timeline", // + "timelineCache", // + "aFChunk", // + "attachedTemplate", // + "audio", // + "calcChain", // + "chart", // + "chartsheet", // + "chartUserShapes", // + "commentAuthors", // + "comments", // + "connections", // + "control", // + "customProperty", // + "customXml", // + "diagramColors", // + "diagramData", // + "diagramLayout", // + "diagramQuickStyle", // + "dialogsheet", // + "drawing", // + "endnotes", // + "externalLink", // + "externalLinkPath", // + "font", // + "fontTable", // + "footer", // + "footnotes", // + "glossaryDocument", // + "handoutMaster", // + "header", // + "hyperlink", // + "image", // + "mailMergeHeaderSource", // + "mailMergeRecipientData", // + "mailMergeSource", // + "notesMaster", // + "notesSlide", // + "numbering", // + "officeDocument", // + "oleObject", // + "package", // + "pivotCacheDefinition", // + "pivotCacheRecords", // + "pivotTable", // + "presProps", // + "printerSettings", // + "queryTable", // + "recipientData", // + "settings", // + "sharedStrings", // + "sheetMetadata", // + "slide", // + "slideLayout", // + "slideMaster", // + "slideUpdateInfo", // + "slideUpdateUrl", // + "styles", // + "table", // + "tableSingleCells", // + "tableStyles", // + "tags", // + "theme", // + "themeOverride", // + "transform", // + "video", // + "viewProps", // + "volatileDependencies", // + "webSettings", // + "worksheet", // + "xmlMaps", // + "ctrlProp", // + "customData", // + "diagram", // + "diagramColorsHeader", // + "diagramLayoutHeader", // + "diagramQuickStyleHeader", // + "documentParts", // + "slicer", // + "slicerCache", // + "vmlDrawing" // + }; +} \ No newline at end of file Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java?rev=1617141&view=auto ============================================================================== --- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java (added) +++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java Sun Aug 10 18:25:10 2014 @@ -0,0 +1,101 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + 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. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import static org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet.XADES_NAMESPACE; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.Map; + +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.namespace.QName; + +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.etsi.uri.x01903.v13.QualifyingPropertiesType; +import org.etsi.uri.x01903.v13.UnsignedPropertiesType; +import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType; +import org.w3.x2000.x09.xmldsig.ObjectType; +import org.w3.x2000.x09.xmldsig.SignatureType; + +/** + * Work-around for Office2010 to accept the XAdES-BES/EPES signature. + * + * xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be + * present. + * + * @author Frank Cornelis + * + */ +public class Office2010SignatureFacet implements SignatureFacet { + + public void preSign(XMLSignatureFactory signatureFactory, + String signatureId, + List<X509Certificate> signingCertificateChain, + List<Reference> references, + List<XMLObject> objects + ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + } + + public void postSign(SignatureType signatureElement, List<X509Certificate> signingCertificateChain) { + QualifyingPropertiesType qualProps = null; + + try { + // check for XAdES-BES + for (ObjectType ot : signatureElement.getObjectList()) { + XmlObject xo[] = ot.selectChildren(new QName(XADES_NAMESPACE, "QualifyingProperties")); + if (xo != null && xo.length > 0) { + qualProps = QualifyingPropertiesType.Factory.parse(xo[0].getDomNode()); + break; + } + } + } catch (XmlException e) { + throw new RuntimeException("signature decoding error", e); + } + + if (qualProps == null) { + throw new IllegalArgumentException("no XAdES-BES extension present"); + } + + // create basic XML container structure + UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); + if (unsignedProps == null) { + unsignedProps = qualProps.addNewUnsignedProperties(); + } + UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties(); + if (unsignedSigProps == null) { + unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties(); + } + } + + public Map<String,String> getNamespacePrefixMapping() { + return null; + } +} \ No newline at end of file Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java?rev=1617141&view=auto ============================================================================== --- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java (added) +++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java Sun Aug 10 18:25:10 2014 @@ -0,0 +1,83 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + 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. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.Map; + +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureFactory; + +import org.w3.x2000.x09.xmldsig.SignatureType; + +/** + * JSR105 Signature Facet interface. + * + * @author Frank Cornelis + * + */ +public interface SignatureFacet { + + /** + * This method is being invoked by the XML signature service engine during + * pre-sign phase. Via this method a signature facet implementation can add + * signature facets to an XML signature. + * + * @param signatureFactory + * @param document + * @param signatureId + * @param signingCertificateChain + * the optional signing certificate chain + * @param references + * @param objects + * @throws InvalidAlgorithmParameterException + * @throws NoSuchAlgorithmException + */ + void preSign( + XMLSignatureFactory signatureFactory + , String signatureId + , List<X509Certificate> signingCertificateChain + , List<Reference> references + , List<XMLObject> objects + ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException; + + /** + * This method is being invoked by the XML signature service engine during + * the post-sign phase. Via this method a signature facet can extend the XML + * signatures with for example key information. + * + * @param signatureElement + * @param signingCertificateChain + */ + void postSign( + SignatureType signatureElement + , List<X509Certificate> signingCertificateChain); + + Map<String,String> getNamespacePrefixMapping(); +} \ No newline at end of file Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java?rev=1617141&view=auto ============================================================================== --- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java (added) +++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java Sun Aug 10 18:25:10 2014 @@ -0,0 +1,65 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + 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. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +/** + * Interface for the signature policy service. + * + * @author Frank Cornelis + * + */ +public interface SignaturePolicyService { + + /** + * Gives back the signature policy identifier URI. + * + * @return + */ + String getSignaturePolicyIdentifier(); + + /** + * Gives back the short description of the signature policy or + * <code>null</code> if a description is not available. + * + * @return the description, or <code>null</code>. + */ + String getSignaturePolicyDescription(); + + /** + * Gives back the download URL where the signature policy document can be + * found. Can be <code>null</code> in case such a download location does not + * exist. + * + * @return the download URL, or <code>null</code>. + */ + String getSignaturePolicyDownloadUrl(); + + /** + * Gives back the signature policy document. + * + * @return the bytes of the signature policy document. + */ + byte[] getSignaturePolicyDocument(); +} \ No newline at end of file Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java?rev=1617141&view=auto ============================================================================== --- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java (added) +++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java Sun Aug 10 18:25:10 2014 @@ -0,0 +1,385 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + 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. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix; + +import java.security.InvalidAlgorithmParameterException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import javax.xml.crypto.XMLStructure; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; + +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; +import org.apache.poi.poifs.crypt.dsig.spi.Constants; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.xmlbeans.XmlString; +import org.etsi.uri.x01903.v13.AnyType; +import org.etsi.uri.x01903.v13.CertIDListType; +import org.etsi.uri.x01903.v13.CertIDType; +import org.etsi.uri.x01903.v13.ClaimedRolesListType; +import org.etsi.uri.x01903.v13.DataObjectFormatType; +import org.etsi.uri.x01903.v13.DigestAlgAndValueType; +import org.etsi.uri.x01903.v13.IdentifierType; +import org.etsi.uri.x01903.v13.ObjectIdentifierType; +import org.etsi.uri.x01903.v13.QualifyingPropertiesDocument; +import org.etsi.uri.x01903.v13.QualifyingPropertiesType; +import org.etsi.uri.x01903.v13.SigPolicyQualifiersListType; +import org.etsi.uri.x01903.v13.SignaturePolicyIdType; +import org.etsi.uri.x01903.v13.SignaturePolicyIdentifierType; +import org.etsi.uri.x01903.v13.SignedDataObjectPropertiesType; +import org.etsi.uri.x01903.v13.SignedPropertiesType; +import org.etsi.uri.x01903.v13.SignedSignaturePropertiesType; +import org.etsi.uri.x01903.v13.SignerRoleType; +import org.w3.x2000.x09.xmldsig.DigestMethodType; +import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3.x2000.x09.xmldsig.X509IssuerSerialType; +import org.w3c.dom.Element; + +/** + * XAdES Signature Facet. Implements XAdES v1.4.1 which is compatible with XAdES + * v1.3.2. The implemented XAdES format is XAdES-BES/EPES. It's up to another + * part of the signature service to upgrade the XAdES-BES to a XAdES-X-L. + * + * This implementation has been tested against an implementation that + * participated multiple ETSI XAdES plugtests. + * + * @author Frank Cornelis + * @see http://en.wikipedia.org/wiki/XAdES + * + */ +public class XAdESSignatureFacet implements SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class); + + private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties"; + + private final Date clock; + + private final HashAlgorithm hashAlgo; + + private final SignaturePolicyService signaturePolicyService; + + private String idSignedProperties; + + private boolean signaturePolicyImplied; + + private String role; + + private boolean issuerNameNoReverseOrder = false; + + private Map<String, String> dataObjectFormatMimeTypes; + + /** + * Main constructor. + * + * @param clock + * the clock to be used for determining the xades:SigningTime, + * defaults to now when null + * @param hashAlgo + * the digest algorithm to be used for all required XAdES digest + * operations. Possible values: "SHA-1", "SHA-256", or "SHA-512", + * defaults to SHA-1 when null + * @param signaturePolicyService + * the optional signature policy service used for XAdES-EPES. + */ + public XAdESSignatureFacet(Date clock, HashAlgorithm hashAlgo, + SignaturePolicyService signaturePolicyService) { + this.clock = (clock == null ? new Date() : clock); + this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo); + this.signaturePolicyService = signaturePolicyService; + this.dataObjectFormatMimeTypes = new HashMap<String, String>(); + } + + public void postSign(SignatureType signatureElement, + List<X509Certificate> signingCertificateChain) { + LOG.log(POILogger.DEBUG, "postSign"); + } + + public void preSign(XMLSignatureFactory signatureFactory, + String signatureId, + List<X509Certificate> signingCertificateChain, + List<Reference> references, List<XMLObject> objects) + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + LOG.log(POILogger.DEBUG, "preSign"); + + // QualifyingProperties + QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance(); + QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties(); + qualifyingProperties.setTarget("#" + signatureId); + + // SignedProperties + SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties(); + String signedPropertiesId; + if (null != this.idSignedProperties) { + signedPropertiesId = this.idSignedProperties; + } else { + signedPropertiesId = signatureId + "-xades"; + } + signedProperties.setId(signedPropertiesId); + + // SignedSignatureProperties + SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties(); + + // SigningTime + Calendar xmlGregorianCalendar = Calendar.getInstance(); + xmlGregorianCalendar.setTimeZone(TimeZone.getTimeZone("Z")); + xmlGregorianCalendar.setTime(this.clock); + xmlGregorianCalendar.clear(Calendar.MILLISECOND); + signedSignatureProperties.setSigningTime(xmlGregorianCalendar); + + // SigningCertificate + if (null == signingCertificateChain + || signingCertificateChain.isEmpty()) { + throw new RuntimeException("no signing certificate chain available"); + } + CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate(); + CertIDType certId = signingCertificates.addNewCert(); + X509Certificate signingCertificate = signingCertificateChain.get(0); + setCertID(certId, signingCertificate, this.hashAlgo, this.issuerNameNoReverseOrder); + + // ClaimedRole + if (null != this.role && false == this.role.isEmpty()) { + SignerRoleType signerRole = signedSignatureProperties.addNewSignerRole(); + signedSignatureProperties.setSignerRole(signerRole); + ClaimedRolesListType claimedRolesList = signerRole.addNewClaimedRoles(); + AnyType claimedRole = claimedRolesList.addNewClaimedRole(); + XmlString roleString = XmlString.Factory.newInstance(); + roleString.setStringValue(this.role); + SignatureInfo.insertXChild(claimedRole, roleString); + } + + // XAdES-EPES + if (null != this.signaturePolicyService) { + SignaturePolicyIdentifierType signaturePolicyIdentifier = + signedSignatureProperties.addNewSignaturePolicyIdentifier(); + + SignaturePolicyIdType signaturePolicyId = signaturePolicyIdentifier.addNewSignaturePolicyId(); + + ObjectIdentifierType objectIdentifier = signaturePolicyId.addNewSigPolicyId(); + objectIdentifier.setDescription(this.signaturePolicyService.getSignaturePolicyDescription()); + + IdentifierType identifier = objectIdentifier.addNewIdentifier(); + identifier.setStringValue(this.signaturePolicyService.getSignaturePolicyIdentifier()); + + byte[] signaturePolicyDocumentData = this.signaturePolicyService.getSignaturePolicyDocument(); + DigestAlgAndValueType sigPolicyHash = signaturePolicyId.addNewSigPolicyHash(); + setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, this.hashAlgo); + + String signaturePolicyDownloadUrl = this.signaturePolicyService + .getSignaturePolicyDownloadUrl(); + if (null != signaturePolicyDownloadUrl) { + SigPolicyQualifiersListType sigPolicyQualifiers = signaturePolicyId.addNewSigPolicyQualifiers(); + AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier(); + XmlString spUriElement = XmlString.Factory.newInstance(); + spUriElement.setStringValue(signaturePolicyDownloadUrl); + SignatureInfo.insertXChild(sigPolicyQualifier, spUriElement); + } + } else if (this.signaturePolicyImplied) { + SignaturePolicyIdentifierType signaturePolicyIdentifier = + signedSignatureProperties.addNewSignaturePolicyIdentifier(); + signaturePolicyIdentifier.addNewSignaturePolicyImplied(); + } + + // DataObjectFormat + if (false == this.dataObjectFormatMimeTypes.isEmpty()) { + SignedDataObjectPropertiesType signedDataObjectProperties = + signedProperties.addNewSignedDataObjectProperties(); + + List<DataObjectFormatType> dataObjectFormats = signedDataObjectProperties + .getDataObjectFormatList(); + for (Map.Entry<String, String> dataObjectFormatMimeType : this.dataObjectFormatMimeTypes + .entrySet()) { + DataObjectFormatType dataObjectFormat = DataObjectFormatType.Factory.newInstance(); + dataObjectFormat.setObjectReference("#" + dataObjectFormatMimeType.getKey()); + dataObjectFormat.setMimeType(dataObjectFormatMimeType.getValue()); + dataObjectFormats.add(dataObjectFormat); + } + } + + // marshall XAdES QualifyingProperties + // ((Element)qualifyingProperties.getSignedProperties().getDomNode()).setIdAttribute("Id", true); + + // add XAdES ds:Object + List<XMLStructure> xadesObjectContent = new LinkedList<XMLStructure>(); + Element qualDocEl = (Element)qualifyingProperties.getDomNode(); + qualDocEl.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#"); + setPrefix(qualifyingProperties, "http://uri.etsi.org/01903/v1.3.2#", "xd"); + xadesObjectContent.add(new DOMStructure(qualDocEl)); + XMLObject xadesObject = signatureFactory.newXMLObject(xadesObjectContent, null, null, null); + objects.add(xadesObject); + + // add XAdES ds:Reference + DigestMethod digestMethod = signatureFactory.newDigestMethod(hashAlgo.xmlSignUri, null); + List<Transform> transforms = new LinkedList<Transform>(); + Transform exclusiveTransform = signatureFactory + .newTransform(CanonicalizationMethod.INCLUSIVE, + (TransformParameterSpec) null); + transforms.add(exclusiveTransform); + Reference reference = signatureFactory.newReference("#" + + signedPropertiesId, digestMethod, transforms, XADES_TYPE, + null); + references.add(reference); + } + + /** + * Gives back the JAXB DigestAlgAndValue data structure. + * + * @param data + * @param xadesObjectFactory + * @param xmldsigObjectFactory + * @param hashAlgo + * @return + */ + protected static void setDigestAlgAndValue( + DigestAlgAndValueType digestAlgAndValue, + byte[] data, + HashAlgorithm hashAlgo) { + DigestMethodType digestMethod = digestAlgAndValue.addNewDigestMethod(); + digestMethod.setAlgorithm(hashAlgo.xmlSignUri); + + MessageDigest messageDigest = CryptoFunctions.getMessageDigest(hashAlgo); + byte[] digestValue = messageDigest.digest(data); + digestAlgAndValue.setDigestValue(digestValue); + } + + /** + * Gives back the JAXB CertID data structure. + * + * @param certificate + * @param xadesObjectFactory + * @param xmldsigObjectFactory + * @param digestAlgorithm + * @return + */ + protected static void setCertID( + CertIDType certId, + X509Certificate certificate, + HashAlgorithm digestAlgorithm, boolean issuerNameNoReverseOrder) { + X509IssuerSerialType issuerSerial = certId.addNewIssuerSerial(); + String issuerName; + if (issuerNameNoReverseOrder) { + /* + * Make sure the DN is encoded using the same order as present + * within the certificate. This is an Office2010 work-around. + * Should be reverted back. + * + * XXX: not correct according to RFC 4514. + */ + // TODO: check if issuerName is different on getTBSCertificate + // issuerName = PrincipalUtil.getIssuerX509Principal(certificate).getName().replace(",", ", "); + issuerName = certificate.getIssuerDN().getName().replace(",", ", "); + } else { + issuerName = certificate.getIssuerX500Principal().toString(); + } + issuerSerial.setX509IssuerName(issuerName); + issuerSerial.setX509SerialNumber(certificate.getSerialNumber()); + + byte[] encodedCertificate; + try { + encodedCertificate = certificate.getEncoded(); + } catch (CertificateEncodingException e) { + throw new RuntimeException("certificate encoding error: " + + e.getMessage(), e); + } + DigestAlgAndValueType certDigest = certId.addNewCertDigest(); + setDigestAlgAndValue(certDigest, encodedCertificate, digestAlgorithm); + } + + /** + * Adds a mime-type for the given ds:Reference (referred via its @URI). This + * information is added via the xades:DataObjectFormat element. + * + * @param dsReferenceUri + * @param mimetype + */ + public void addMimeType(String dsReferenceUri, String mimetype) { + this.dataObjectFormatMimeTypes.put(dsReferenceUri, mimetype); + } + + /** + * Sets the Id that will be used on the SignedProperties element; + * + * @param idSignedProperties + */ + public void setIdSignedProperties(String idSignedProperties) { + this.idSignedProperties = idSignedProperties; + } + + /** + * Sets the signature policy to implied. + * + * @param signaturePolicyImplied + */ + public void setSignaturePolicyImplied(boolean signaturePolicyImplied) { + this.signaturePolicyImplied = signaturePolicyImplied; + } + + /** + * Sets the XAdES claimed role. + * + * @param role + */ + public void setRole(String role) { + this.role = role; + } + + /** + * Work-around for Office 2010 IssuerName encoding. + * + * @param reverseOrder + */ + public void setIssuerNameNoReverseOrder(boolean reverseOrder) { + this.issuerNameNoReverseOrder = reverseOrder; + } + + + public Map<String,String> getNamespacePrefixMapping() { + Map<String,String> map = new HashMap<String,String>(); + map.put("xd", "http://uri.etsi.org/01903/v1.3.2#"); + return map; + } + +} \ No newline at end of file Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java?rev=1617141&view=auto ============================================================================== --- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java (added) +++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java Sun Aug 10 18:25:10 2014 @@ -0,0 +1,492 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + 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. +==================================================================== */ + +/* ==================================================================== + This product contains an ASLv2 licensed version of the OOXML signer + package from the eID Applet project + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + Copyright (C) 2008-2014 FedICT. + ================================================================= */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CRLException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.Calendar; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.namespace.QName; + +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.poifs.crypt.dsig.HorribleProxy; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicOCSPRespIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CanonicalizerIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DERIntegerIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DERTaggedObjectIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.InitIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.RespIDIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ResponderIDIf; +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509NameIf; +import org.apache.poi.poifs.crypt.dsig.services.RevocationData; +import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService; +import org.apache.poi.poifs.crypt.dsig.services.TimeStampService; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.etsi.uri.x01903.v13.CRLIdentifierType; +import org.etsi.uri.x01903.v13.CRLRefType; +import org.etsi.uri.x01903.v13.CRLRefsType; +import org.etsi.uri.x01903.v13.CRLValuesType; +import org.etsi.uri.x01903.v13.CertIDListType; +import org.etsi.uri.x01903.v13.CertIDType; +import org.etsi.uri.x01903.v13.CertificateValuesType; +import org.etsi.uri.x01903.v13.CompleteCertificateRefsType; +import org.etsi.uri.x01903.v13.CompleteRevocationRefsType; +import org.etsi.uri.x01903.v13.DigestAlgAndValueType; +import org.etsi.uri.x01903.v13.EncapsulatedPKIDataType; +import org.etsi.uri.x01903.v13.OCSPIdentifierType; +import org.etsi.uri.x01903.v13.OCSPRefType; +import org.etsi.uri.x01903.v13.OCSPRefsType; +import org.etsi.uri.x01903.v13.OCSPValuesType; +import org.etsi.uri.x01903.v13.QualifyingPropertiesType; +import org.etsi.uri.x01903.v13.ResponderIDType; +import org.etsi.uri.x01903.v13.RevocationValuesType; +import org.etsi.uri.x01903.v13.UnsignedPropertiesType; +import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType; +import org.etsi.uri.x01903.v13.XAdESTimeStampType; +import org.etsi.uri.x01903.v14.ValidationDataType; +import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType; +import org.w3.x2000.x09.xmldsig.ObjectType; +import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3.x2000.x09.xmldsig.SignatureValueType; +import org.w3c.dom.Node; + +/** + * XAdES-X-L v1.4.1 signature facet. This signature facet implementation will + * upgrade a given XAdES-BES/EPES signature to XAdES-X-L. + * + * We don't inherit from XAdESSignatureFacet as we also want to be able to use + * this facet out of the context of a signature creation. This signature facet + * assumes that the signature is already XAdES-BES/EPES compliant. + * + * This implementation has been tested against an implementation that + * participated multiple ETSI XAdES plugtests. + * + * @author Frank Cornelis + * @see XAdESSignatureFacet + */ +public class XAdESXLSignatureFacet implements SignatureFacet { + + private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class); + + public static final String XADES_NAMESPACE = "http://uri.etsi.org/01903/v1.3.2#"; + + public static final String XADES141_NAMESPACE = "http://uri.etsi.org/01903/v1.4.1#"; + + private final TimeStampService timeStampService; + + private String c14nAlgoId; + + private final RevocationDataService revocationDataService; + + private final CertificateFactory certificateFactory; + + private final HashAlgorithm hashAlgo; + + static { + try { + HorribleProxy.createProxy(InitIf.class, "init"); + } catch (Exception e) { + throw new RuntimeException("Can't initialize JDK xml signature classes - feature unsupported by the this JDK?!", e); + } + } + + /** + * Convenience constructor. + * + * @param timeStampService + * the time-stamp service used for XAdES-T and XAdES-X. + * @param revocationDataService + * the optional revocation data service used for XAdES-C and + * XAdES-X-L. When <code>null</code> the signature will be + * limited to XAdES-T only. + */ + public XAdESXLSignatureFacet(TimeStampService timeStampService, + RevocationDataService revocationDataService) { + this(timeStampService, revocationDataService, HashAlgorithm.sha1); + } + + /** + * Main constructor. + * + * @param timeStampService + * the time-stamp service used for XAdES-T and XAdES-X. + * @param revocationDataService + * the optional revocation data service used for XAdES-C and + * XAdES-X-L. When <code>null</code> the signature will be + * limited to XAdES-T only. + * @param digestAlgorithm + * the digest algorithm to be used for construction of the + * XAdES-X-L elements. + */ + public XAdESXLSignatureFacet(TimeStampService timeStampService, + RevocationDataService revocationDataService, + HashAlgorithm digestAlgorithm) { + this.c14nAlgoId = CanonicalizationMethod.EXCLUSIVE; + this.hashAlgo = digestAlgorithm; + this.timeStampService = timeStampService; + this.revocationDataService = revocationDataService; + + try { + this.certificateFactory = CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + throw new RuntimeException("X509 JCA error: " + e.getMessage(), e); + } + } + + public void setCanonicalizerAlgorithm(String c14nAlgoId) { + this.c14nAlgoId = c14nAlgoId; + } + + public void postSign(SignatureType signatureElement, + List<X509Certificate> signingCertificateChain) { + LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase"); + + QualifyingPropertiesType qualProps = null; + + try { + // check for XAdES-BES + for (ObjectType ot : signatureElement.getObjectList()) { + XmlObject xo[] = ot.selectChildren(new QName(XADES_NAMESPACE, "QualifyingProperties")); + if (xo != null && xo.length > 0) { + qualProps = QualifyingPropertiesType.Factory.parse(xo[0].getDomNode()); + break; + } + } + } catch (XmlException e) { + throw new RuntimeException("signature decoding error", e); + } + + if (qualProps == null) { + throw new IllegalArgumentException("no XAdES-BES extension present"); + } + + // create basic XML container structure + UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); + if (unsignedProps == null) { + unsignedProps = qualProps.addNewUnsignedProperties(); + } + UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties(); + if (unsignedSigProps == null) { + unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties(); + } + + + // create the XAdES-T time-stamp + SignatureValueType svt = signatureElement.getSignatureValue(); + + RevocationData tsaRevocationDataXadesT = new RevocationData(); + LOG.log(POILogger.DEBUG, "creating XAdES-T time-stamp"); + XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp( + Collections.singletonList(svt.getDomNode()), + tsaRevocationDataXadesT, this.c14nAlgoId, + this.timeStampService); + + // marshal the XAdES-T extension + unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp); + + // xadesv141::TimeStampValidationData + if (tsaRevocationDataXadesT.hasRevocationDataEntries()) { + ValidationDataType validationData = createValidationData(tsaRevocationDataXadesT); + SignatureInfo.insertXChild(unsignedSigProps, validationData); + } + + if (null == this.revocationDataService) { + /* + * Without revocation data service we cannot construct the XAdES-C + * extension. + */ + return; + } + + // XAdES-C: complete certificate refs + CompleteCertificateRefsType completeCertificateRefs = + unsignedSigProps.addNewCompleteCertificateRefs(); + + CertIDListType certIdList = completeCertificateRefs.addNewCertRefs(); + for (int certIdx = 1; certIdx < signingCertificateChain.size(); certIdx++) { + /* + * We skip the signing certificate itself according to section + * 4.4.3.2 of the XAdES 1.4.1 specification. + */ + X509Certificate certificate = signingCertificateChain.get(certIdx); + CertIDType certId = certIdList.addNewCert(); + XAdESSignatureFacet.setCertID(certId, certificate, this.hashAlgo, false); + } + + // XAdES-C: complete revocation refs + CompleteRevocationRefsType completeRevocationRefs = + unsignedSigProps.addNewCompleteRevocationRefs(); + RevocationData revocationData = this.revocationDataService + .getRevocationData(signingCertificateChain); + if (revocationData.hasCRLs()) { + CRLRefsType crlRefs = completeRevocationRefs.addNewCRLRefs(); + completeRevocationRefs.setCRLRefs(crlRefs); + + for (byte[] encodedCrl : revocationData.getCRLs()) { + CRLRefType crlRef = crlRefs.addNewCRLRef(); + X509CRL crl; + try { + crl = (X509CRL) this.certificateFactory + .generateCRL(new ByteArrayInputStream(encodedCrl)); + } catch (CRLException e) { + throw new RuntimeException("CRL parse error: " + + e.getMessage(), e); + } + + CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier(); + String issuerName = crl.getIssuerDN().getName().replace(",", ", "); + crlIdentifier.setIssuer(issuerName); + Calendar cal = Calendar.getInstance(); + cal.setTime(crl.getThisUpdate()); + crlIdentifier.setIssueTime(cal); + crlIdentifier.setNumber(getCrlNumber(crl)); + + DigestAlgAndValueType digestAlgAndValue = crlRef.addNewDigestAlgAndValue(); + XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, encodedCrl, this.hashAlgo); + } + } + if (revocationData.hasOCSPs()) { + OCSPRefsType ocspRefs = completeRevocationRefs.addNewOCSPRefs(); + for (byte[] ocsp : revocationData.getOCSPs()) { + try { + OCSPRefType ocspRef = ocspRefs.addNewOCSPRef(); + + DigestAlgAndValueType digestAlgAndValue = ocspRef.addNewDigestAlgAndValue(); + XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, ocsp, this.hashAlgo); + + OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier(); + + OCSPRespIf ocspResp = HorribleProxy.newProxy(OCSPRespIf.class, ocsp); + + BasicOCSPRespIf basicOcspResp = ocspResp.getResponseObject(); + + Calendar cal = Calendar.getInstance(); + cal.setTime(basicOcspResp.getProducedAt()); + ocspIdentifier.setProducedAt(cal); + + ResponderIDType responderId = ocspIdentifier.addNewResponderID(); + + RespIDIf respId = basicOcspResp.getResponderId(); + ResponderIDIf ocspResponderId = respId.toASN1Object(); + DERTaggedObjectIf derTaggedObject = ocspResponderId.toASN1Object(); + if (2 == derTaggedObject.getTagNo()) { + ASN1OctetStringIf keyHashOctetString = derTaggedObject.getObject$String(); + byte key[] = keyHashOctetString.getOctets(); + responderId.setByKey(key); + } else { + X509NameIf name = HorribleProxy.createProxy(X509NameIf.class, "getInstance", derTaggedObject.getObject$Object()); + String nameStr = name.toString$delegate(); + responderId.setByName(nameStr); + } + } catch (Exception e) { + throw new RuntimeException("OCSP decoding error: " + e.getMessage(), e); + } + } + } + + // marshal XAdES-C + + // XAdES-X Type 1 timestamp + + + + List<Node> timeStampNodesXadesX1 = new LinkedList<Node>(); + timeStampNodesXadesX1.add(signatureElement.getDomNode()); + timeStampNodesXadesX1.add(signatureTimeStamp.getDomNode()); + timeStampNodesXadesX1.add(completeCertificateRefs.getDomNode()); + timeStampNodesXadesX1.add(completeRevocationRefs.getDomNode()); + + RevocationData tsaRevocationDataXadesX1 = new RevocationData(); + LOG.log(POILogger.DEBUG, "creating XAdES-X time-stamp"); + XAdESTimeStampType timeStampXadesX1 = createXAdESTimeStamp( + timeStampNodesXadesX1, tsaRevocationDataXadesX1, + this.c14nAlgoId, this.timeStampService); + if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) { + ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1); + SignatureInfo.insertXChild(unsignedSigProps, timeStampXadesX1ValidationData); + } + + // marshal XAdES-X + + // XAdES-X-L + CertificateValuesType certificateValues = unsignedSigProps.addNewCertificateValues(); + for (X509Certificate certificate : signingCertificateChain) { + EncapsulatedPKIDataType encapsulatedPKIDataType = certificateValues.addNewEncapsulatedX509Certificate(); + try { + encapsulatedPKIDataType.setByteArrayValue(certificate.getEncoded()); + } catch (CertificateEncodingException e) { + throw new RuntimeException("certificate encoding error: " + e.getMessage(), e); + } + } + + RevocationValuesType revocationValues = unsignedSigProps.addNewRevocationValues(); + createRevocationValues(revocationValues, revocationData); + + // marshal XAdES-X-L + } + + public static byte[] getC14nValue(List<Node> nodeList, String c14nAlgoId) { + byte[] c14nValue = null; + try { + for (Node node : nodeList) { + /* + * Re-initialize the c14n else the namespaces will get cached + * and will be missing from the c14n resulting nodes. + */ + CanonicalizerIf c14n = HorribleProxy.createProxy(CanonicalizerIf.class, "newInstance", c14nAlgoId); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(c14nValue); + bos.write(c14n.canonicalizeSubtree(node)); + c14nValue = bos.toByteArray(); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException("c14n error: " + e.getMessage(), e); + } + return c14nValue; + } + + public void preSign(XMLSignatureFactory signatureFactory, + String signatureId, + List<X509Certificate> signingCertificateChain, + List<Reference> references, List<XMLObject> objects) + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + // nothing to do here + } + + private BigInteger getCrlNumber(X509CRL crl) { + byte[] crlNumberExtensionValue = crl.getExtensionValue("2.5.29.20" /*CRLNumber*/); + if (null == crlNumberExtensionValue) { + return null; + } + try { + ASN1InputStreamIf asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, crlNumberExtensionValue); + ASN1OctetStringIf octetString = asn1InputStream.readObject$ASNString(); + byte[] octets = octetString.getOctets(); + asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, octets); + DERIntegerIf integer = asn1InputStream.readObject$Integer(); + BigInteger crlNumber = integer.getPositiveValue(); + return crlNumber; + } catch (Exception e) { + throw new RuntimeException("I/O error: " + e.getMessage(), e); + } + } + + public static XAdESTimeStampType createXAdESTimeStamp( + List<Node> nodeList, + RevocationData revocationData, + String c14nAlgoId, + TimeStampService timeStampService) { + byte[] c14nSignatureValueElement = getC14nValue(nodeList, c14nAlgoId); + + return createXAdESTimeStamp(c14nSignatureValueElement, revocationData, + c14nAlgoId, timeStampService); + } + + public static XAdESTimeStampType createXAdESTimeStamp( + byte[] data, + RevocationData revocationData, + String c14nAlgoId, + TimeStampService timeStampService) { + // create the time-stamp + byte[] timeStampToken; + try { + timeStampToken = timeStampService.timeStamp(data, revocationData); + } catch (Exception e) { + throw new RuntimeException("error while creating a time-stamp: " + + e.getMessage(), e); + } + + // create a XAdES time-stamp container + XAdESTimeStampType xadesTimeStamp = XAdESTimeStampType.Factory.newInstance(); + xadesTimeStamp.setId("time-stamp-" + UUID.randomUUID().toString()); + CanonicalizationMethodType c14nMethod = xadesTimeStamp.addNewCanonicalizationMethod(); + c14nMethod.setAlgorithm(c14nAlgoId); + + // embed the time-stamp + EncapsulatedPKIDataType encapsulatedTimeStamp = xadesTimeStamp.addNewEncapsulatedTimeStamp(); + encapsulatedTimeStamp.setByteArrayValue(timeStampToken); + encapsulatedTimeStamp.setId("time-stamp-token-" + UUID.randomUUID().toString()); + + return xadesTimeStamp; + } + + private ValidationDataType createValidationData( + RevocationData revocationData) { + ValidationDataType validationData = ValidationDataType.Factory.newInstance(); + RevocationValuesType revocationValues = validationData.addNewRevocationValues(); + createRevocationValues(revocationValues, revocationData); + return validationData; + } + + private void createRevocationValues( + RevocationValuesType revocationValues, RevocationData revocationData) { + if (revocationData.hasCRLs()) { + CRLValuesType crlValues = revocationValues.addNewCRLValues(); + for (byte[] crl : revocationData.getCRLs()) { + EncapsulatedPKIDataType encapsulatedCrlValue = crlValues.addNewEncapsulatedCRLValue(); + encapsulatedCrlValue.setByteArrayValue(crl); + } + } + if (revocationData.hasOCSPs()) { + OCSPValuesType ocspValues = revocationValues.addNewOCSPValues(); + for (byte[] ocsp : revocationData.getOCSPs()) { + EncapsulatedPKIDataType encapsulatedOcspValue = ocspValues.addNewEncapsulatedOCSPValue(); + encapsulatedOcspValue.setByteArrayValue(ocsp); + } + } + } + + public Map<String,String> getNamespacePrefixMapping() { + return null; + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
