\r
package org.apache.poi.poifs.crypt.dsig;\r
\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;\r
+\r
import java.io.ByteArrayOutputStream;\r
+import java.io.File;\r
import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.URISyntaxException;\r
+import java.security.InvalidAlgorithmParameterException;\r
+import java.security.MessageDigest;\r
import java.security.NoSuchAlgorithmException;\r
-import java.security.PrivateKey;\r
+import java.security.NoSuchProviderException;\r
import java.security.Provider;\r
import java.security.cert.X509Certificate;\r
import java.util.ArrayList;\r
import java.util.Collections;\r
+import java.util.HashMap;\r
import java.util.List;\r
+import java.util.Map;\r
\r
import javax.crypto.Cipher;\r
import javax.xml.crypto.MarshalException;\r
+import javax.xml.crypto.URIDereferencer;\r
+import javax.xml.crypto.XMLStructure;\r
+import javax.xml.crypto.dsig.CanonicalizationMethod;\r
+import javax.xml.crypto.dsig.DigestMethod;\r
+import javax.xml.crypto.dsig.Manifest;\r
+import javax.xml.crypto.dsig.Reference;\r
+import javax.xml.crypto.dsig.SignatureMethod;\r
+import javax.xml.crypto.dsig.SignedInfo;\r
+import javax.xml.crypto.dsig.XMLObject;\r
+import javax.xml.crypto.dsig.XMLSignContext;\r
import javax.xml.crypto.dsig.XMLSignature;\r
+import javax.xml.crypto.dsig.XMLSignatureException;\r
import javax.xml.crypto.dsig.XMLSignatureFactory;\r
+import javax.xml.crypto.dsig.dom.DOMSignContext;\r
import javax.xml.crypto.dsig.dom.DOMValidateContext;\r
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;\r
+import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;\r
import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.transform.TransformerException;\r
+import javax.xml.transform.TransformerFactoryConfigurationError;\r
\r
+import org.apache.jcp.xml.dsig.internal.dom.DOMReference;\r
+import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;\r
import org.apache.poi.EncryptedDocumentException;\r
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
import org.apache.poi.openxml4j.opc.OPCPackage;\r
+import org.apache.poi.openxml4j.opc.PackageNamespaces;\r
import org.apache.poi.openxml4j.opc.PackagePart;\r
+import org.apache.poi.openxml4j.opc.PackagePartName;\r
import org.apache.poi.openxml4j.opc.PackageRelationship;\r
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;\r
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;\r
+import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
+import org.apache.poi.openxml4j.opc.TargetMode;\r
import org.apache.poi.poifs.crypt.ChainingMode;\r
import org.apache.poi.poifs.crypt.CipherAlgorithm;\r
import org.apache.poi.poifs.crypt.CryptoFunctions;\r
-import org.apache.poi.poifs.crypt.HashAlgorithm;\r
+import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;\r
-import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
import org.apache.poi.util.DocumentHelper;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
import org.apache.xml.security.Init;\r
-import org.apache.xmlbeans.XmlCursor;\r
+import org.apache.xml.security.utils.Base64;\r
import org.apache.xmlbeans.XmlException;\r
-import org.apache.xmlbeans.XmlObject;\r
+import org.apache.xmlbeans.XmlOptions;\r
+import org.w3.x2000.x09.xmldsig.SignatureDocument;\r
import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
import org.w3c.dom.Node;\r
import org.w3c.dom.NodeList;\r
+import org.w3c.dom.events.Event;\r
+import org.w3c.dom.events.EventListener;\r
+import org.w3c.dom.events.EventTarget;\r
+import org.w3c.dom.events.MutationEvent;\r
+import org.xml.sax.SAXException;\r
\r
public class SignatureInfo {\r
\r
private static final POILogger LOG = POILogFactory.getLogger(SignatureInfo.class);\r
private static boolean isInitialized = false;\r
\r
- private final OPCPackage pkg;\r
- \r
- public SignatureInfo(OPCPackage pkg) {\r
- this.pkg = pkg;\r
+ private SignatureInfoConfig signatureConfig;\r
+\r
+ public SignatureInfoConfig getSignatureConfig() {\r
+ return signatureConfig;\r
}\r
- \r
+\r
+ public void setSignatureConfig(SignatureInfoConfig signatureConfig) {\r
+ this.signatureConfig = signatureConfig;\r
+ }\r
+\r
public boolean verifySignature() {\r
initXmlProvider();\r
// http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html\r
return getSignersAndValidate(signers, true);\r
}\r
\r
- public void confirmSignature(PrivateKey key, X509Certificate x509)\r
- throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {\r
- confirmSignature(key, x509, HashAlgorithm.sha1);\r
- }\r
- \r
- public void confirmSignature(PrivateKey key, X509Certificate x509, HashAlgorithm hashAlgo)\r
- throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {\r
- SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
- signatureConfig.setOpcPackage(pkg);\r
- signatureConfig.setDigestAlgo(hashAlgo);\r
- signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));\r
- signatureConfig.setKey(key);\r
- signatureConfig.addDefaultFacets();\r
- XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);\r
-\r
+ public void confirmSignature()\r
+ throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException, InvalidAlgorithmParameterException, NoSuchProviderException, XMLSignatureException, TransformerFactoryConfigurationError, TransformerException, SAXException, URISyntaxException {\r
Document document = DocumentHelper.createDocument();\r
\r
// operate\r
- DigestInfo digestInfo = signatureService.preSign(document, null);\r
+ DigestInfo digestInfo = preSign(document, null);\r
\r
// setup: key material, signature value\r
- byte[] signatureValue = signDigest(key, hashAlgo, digestInfo.digestValue);\r
+ byte[] signatureValue = signDigest(digestInfo.digestValue);\r
\r
// operate: postSign\r
- signatureService.postSign(document, signatureValue);\r
+ postSign(document, signatureValue);\r
}\r
\r
- public static byte[] signDigest(PrivateKey key, HashAlgorithm hashAlgo, byte digest[]) {\r
- Cipher cipher = CryptoFunctions.getCipher(key, CipherAlgorithm.rsa\r
+ public byte[] signDigest(byte digest[]) {\r
+ Cipher cipher = CryptoFunctions.getCipher(signatureConfig.getKey(), CipherAlgorithm.rsa\r
, ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");\r
\r
try {\r
ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();\r
- digestInfoValueBuf.write(getHashMagic(hashAlgo));\r
+ digestInfoValueBuf.write(getHashMagic());\r
digestInfoValueBuf.write(digest);\r
byte[] digestInfoValue = digestInfoValueBuf.toByteArray();\r
byte[] signatureValue = cipher.doFinal(digestInfoValue);\r
allValid = false;\r
}\r
\r
- SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
- signatureConfig.setOpcPackage(pkg);\r
- \r
for (PackagePart signaturePart : signatureParts) {\r
KeyInfoKeySelector keySelector = new KeyInfoKeySelector();\r
\r
try {\r
Document doc = DocumentHelper.readDocument(signaturePart.getInputStream());\r
- XmlSignatureService.registerIds(doc);\r
+ registerIds(doc);\r
\r
DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);\r
domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);\r
\r
protected List<PackagePart> getSignatureParts(boolean onlyFirst) {\r
List<PackagePart> packageParts = new ArrayList<PackagePart>();\r
+ OPCPackage pkg = signatureConfig.getOpcPackage();\r
\r
PackageRelationshipCollection sigOrigRels = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
for (PackageRelationship rel : sigOrigRels) {\r
throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!");\r
}\r
\r
- public static void insertXChild(XmlObject root, XmlObject child) {\r
- XmlCursor rootCursor = root.newCursor();\r
- insertXChild(rootCursor, child);\r
- rootCursor.dispose();\r
- }\r
-\r
- public static void insertXChild(XmlCursor rootCursor, XmlObject child) {\r
- rootCursor.toEndToken();\r
- XmlCursor childCursor = child.newCursor();\r
- childCursor.toNextToken();\r
- childCursor.moveXml(rootCursor);\r
- childCursor.dispose();\r
- }\r
-\r
-// public static void setPrefix(XmlObject xobj, String ns, String prefix) {\r
-// XmlCursor cur;\r
-// for (cur = xobj.newCursor(); cur.hasNextToken(); cur.toNextToken()) {\r
-// if (cur.isStart()) {\r
-// Element el = (Element)cur.getDomNode();\r
-// if (ns.equals(el.getNamespaceURI())) el.setPrefix(prefix);\r
-// }\r
-// }\r
-// cur.dispose();\r
-// }\r
-\r
public static void setPrefix(Node el, String ns, String prefix) {\r
if (ns.equals(el.getNamespaceURI())) el.setPrefix(prefix);\r
NodeList nl = el.getChildNodes();\r
}\r
}\r
\r
- protected static byte[] getHashMagic(HashAlgorithm hashAlgo) {\r
- switch (hashAlgo) {\r
+ protected byte[] getHashMagic() {\r
+ switch (signatureConfig.getDigestAlgo()) {\r
case sha1: return SHA1_DIGEST_INFO_PREFIX;\r
// sha224: return SHA224_DIGEST_INFO_PREFIX;\r
case sha256: return SHA256_DIGEST_INFO_PREFIX;\r
case ripemd128: return RIPEMD128_DIGEST_INFO_PREFIX;\r
case ripemd160: return RIPEMD160_DIGEST_INFO_PREFIX;\r
// case ripemd256: return RIPEMD256_DIGEST_INFO_PREFIX;\r
- default: throw new EncryptedDocumentException("Hash algorithm "+hashAlgo+" not supported for signing.");\r
+ default: throw new EncryptedDocumentException("Hash algorithm "+signatureConfig.getDigestAlgo()+" not supported for signing.");\r
}\r
}\r
+\r
+ protected String getSignatureMethod() {\r
+ switch (signatureConfig.getDigestAlgo()) {\r
+ case sha1: return ALGO_ID_SIGNATURE_RSA_SHA1;\r
+ case sha256: return ALGO_ID_SIGNATURE_RSA_SHA256;\r
+ case sha384: return ALGO_ID_SIGNATURE_RSA_SHA384;\r
+ case sha512: return ALGO_ID_SIGNATURE_RSA_SHA512;\r
+ case ripemd160: return ALGO_ID_MAC_HMAC_RIPEMD160;\r
+ default: throw new EncryptedDocumentException("Hash algorithm "+signatureConfig.getDigestAlgo()+" not supported for signing.");\r
+ }\r
+ }\r
+\r
+ \r
\r
public static synchronized void initXmlProvider() {\r
if (isInitialized) return;\r
throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e);\r
}\r
}\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
+ throws ParserConfigurationException, NoSuchAlgorithmException,\r
+ InvalidAlgorithmParameterException, MarshalException,\r
+ javax.xml.crypto.dsig.XMLSignatureException,\r
+ TransformerFactoryConfigurationError, TransformerException,\r
+ IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException {\r
+ SignatureInfo.initXmlProvider();\r
+ \r
+ // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
+ // normal way to interfere with, so we need to add the namespace under the hand ...\r
+ final EventTarget et = (EventTarget)document;\r
+ EventListener myModificationListener = new EventListener() {\r
+ @Override\r
+ public void handleEvent(Event e) {\r
+ if (e instanceof MutationEvent) {\r
+ MutationEvent mutEvt = (MutationEvent)e;\r
+ if (mutEvt.getTarget() instanceof Element) {\r
+ Element el = (Element)mutEvt.getTarget();\r
+ if ("idPackageObject".equals(el.getAttribute("Id"))) {\r
+ et.removeEventListener("DOMSubtreeModified", this, false);\r
+ el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ };\r
+ \r
+ et.addEventListener("DOMSubtreeModified", myModificationListener, false);\r
+ \r
+ /*\r
+ * Signature context construction.\r
+ */\r
+ XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);\r
+ URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();\r
+ if (null != uriDereferencer) {\r
+ xmlSignContext.setURIDereferencer(uriDereferencer);\r
+ }\r
+\r
+ xmlSignContext.putNamespacePrefix(\r
+ "http://schemas.openxmlformats.org/package/2006/digital-signature",\r
+ "mdssi");\r
+ \r
+ String sigNsPrefix = signatureConfig.getSignatureNamespacePrefix();\r
+ if (sigNsPrefix != null) {\r
+ /*\r
+ * OOo doesn't like ds namespaces so per default prefixing is off.\r
+ */\r
+ xmlSignContext.putNamespacePrefix(XmlDSigNS, sigNsPrefix);\r
+ }\r
+\r
+ XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();\r
+\r
+ /*\r
+ * Add ds:References that come from signing client local files.\r
+ */\r
+ List<Reference> references = new ArrayList<Reference>();\r
+ for (DigestInfo digestInfo : safe(digestInfos)) {\r
+ byte[] documentDigestValue = digestInfo.digestValue;\r
+\r
+ DigestMethod digestMethod = signatureFactory.newDigestMethod(\r
+ digestInfo.hashAlgo.xmlSignUri, null);\r
+\r
+ String uri = new File(digestInfo.description).getName();\r
+\r
+ Reference reference = signatureFactory.newReference\r
+ (uri, digestMethod, null, null, null, documentDigestValue);\r
+ references.add(reference);\r
+ }\r
+\r
+ /*\r
+ * Invoke the signature facets.\r
+ */\r
+ List<XMLObject> objects = new ArrayList<XMLObject>();\r
+ for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
+ LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
+ signatureFacet.preSign(document, signatureFactory, references, objects);\r
+ }\r
+\r
+ /*\r
+ * ds:SignedInfo\r
+ */\r
+ SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(), null);\r
+ CanonicalizationMethod canonicalizationMethod = signatureFactory\r
+ .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),\r
+ (C14NMethodParameterSpec) null);\r
+ SignedInfo signedInfo = signatureFactory.newSignedInfo(\r
+ canonicalizationMethod, signatureMethod, references);\r
+\r
+ /*\r
+ * JSR105 ds:Signature creation\r
+ */\r
+ String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";\r
+ javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
+ .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),\r
+ signatureValueId);\r
+\r
+ /*\r
+ * ds:Signature Marshalling.\r
+ */\r
+ xmlSignContext.setDefaultNamespacePrefix(signatureConfig.getSignatureNamespacePrefix());\r
+ // xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");\r
+ xmlSignature.sign(xmlSignContext);\r
+\r
+ registerIds(document);\r
+ \r
+ /*\r
+ * Completion of undigested ds:References in the ds:Manifests.\r
+ */\r
+ for (XMLObject object : objects) {\r
+ LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
+ List<XMLStructure> objectContentList = object.getContent();\r
+ for (XMLStructure objectContent : objectContentList) {\r
+ LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
+ if (!(objectContent instanceof Manifest)) continue;\r
+ Manifest manifest = (Manifest) objectContent;\r
+ List<Reference> manifestReferences = manifest.getReferences();\r
+ for (Reference manifestReference : manifestReferences) {\r
+ if (manifestReference.getDigestValue() != null) continue;\r
+\r
+ DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
+ manifestDOMReference.digest(xmlSignContext);\r
+ }\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Completion of undigested ds:References.\r
+ */\r
+ List<Reference> signedInfoReferences = signedInfo.getReferences();\r
+ for (Reference signedInfoReference : signedInfoReferences) {\r
+ DOMReference domReference = (DOMReference)signedInfoReference;\r
+\r
+ // ds:Reference with external digest value\r
+ if (domReference.getDigestValue() != null) continue;\r
+ \r
+ domReference.digest(xmlSignContext);\r
+ }\r
+\r
+ /*\r
+ * Calculation of XML signature digest value.\r
+ */\r
+ DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
+ ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
+ domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
+ byte[] octets = dataStream.toByteArray();\r
+\r
+ /*\r
+ * TODO: we could be using DigestOutputStream here to optimize memory\r
+ * usage.\r
+ */\r
+\r
+ MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());\r
+ byte[] digestValue = jcaMessageDigest.digest(octets);\r
+ \r
+ \r
+ String description = signatureConfig.getSignatureDescription();\r
+ return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);\r
+ }\r
+\r
+ public void postSign(Document document, byte[] signatureValue)\r
+ throws IOException, MarshalException, ParserConfigurationException, XmlException {\r
+ LOG.log(POILogger.DEBUG, "postSign");\r
+ SignatureInfo.initXmlProvider();\r
+\r
+ /*\r
+ * Check ds:Signature node.\r
+ */\r
+ String signatureId = signatureConfig.getPackageSignatureId();\r
+ if (!signatureId.equals(document.getDocumentElement().getAttribute("Id"))) {\r
+ throw new RuntimeException("ds:Signature not found for @Id: " + signatureId);\r
+ }\r
+\r
+ /*\r
+ * Insert signature value into the ds:SignatureValue element\r
+ */\r
+ NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");\r
+ if (sigValNl.getLength() != 1) {\r
+ throw new RuntimeException("preSign has to be called before postSign");\r
+ }\r
+ sigValNl.item(0).setTextContent(Base64.encode(signatureValue));\r
+\r
+ /*\r
+ * Allow signature facets to inject their own stuff.\r
+ */\r
+ for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
+ signatureFacet.postSign(document, signatureConfig.getSigningCertificateChain());\r
+ }\r
+\r
+ registerIds(document);\r
+ writeDocument(document);\r
+ }\r
+\r
+ protected void writeDocument(Document document) throws IOException, XmlException {\r
+ XmlOptions xo = new XmlOptions();\r
+ Map<String,String> namespaceMap = new HashMap<String,String>();\r
+ for (SignatureFacet sf : signatureConfig.getSignatureFacets()) {\r
+ Map<String,String> sfm = sf.getNamespacePrefixMapping();\r
+ if (sfm != null) {\r
+ namespaceMap.putAll(sfm);\r
+ }\r
+ }\r
+ xo.setSaveSuggestedPrefixes(namespaceMap);\r
+ xo.setUseDefaultNamespace();\r
+\r
+ LOG.log(POILogger.DEBUG, "output signed Office OpenXML document");\r
+\r
+ /*\r
+ * Copy the original OOXML content to the signed OOXML package. During\r
+ * copying some files need to changed.\r
+ */\r
+ OPCPackage pkg = signatureConfig.getOpcPackage();\r
+\r
+ PackagePartName sigPartName, sigsPartName;\r
+ try {\r
+ // <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/>\r
+ sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig1.xml");\r
+ // <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>\r
+ sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs");\r
+ } catch (InvalidFormatException e) {\r
+ throw new IOException(e);\r
+ }\r
+ \r
+ String sigContentType = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml";\r
+ PackagePart sigPart = pkg.getPart(sigPartName);\r
+ if (sigPart == null) {\r
+ sigPart = pkg.createPart(sigPartName, sigContentType);\r
+ }\r
+ \r
+ OutputStream os = sigPart.getOutputStream();\r
+ SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);\r
+ sigDoc.save(os, xo);\r
+ os.close();\r
+ \r
+ String sigsContentType = "application/vnd.openxmlformats-package.digital-signature-origin";\r
+ PackagePart sigsPart = pkg.getPart(sigsPartName);\r
+ if (sigsPart == null) {\r
+ // touch empty marker file\r
+ sigsPart = pkg.createPart(sigsPartName, sigsContentType);\r
+ }\r
+ \r
+ PackageRelationshipCollection relCol = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
+ for (PackageRelationship pr : relCol) {\r
+ pkg.removeRelationship(pr.getId());\r
+ }\r
+ pkg.addRelationship(sigsPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
+ \r
+ sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);\r
+ }\r
+ \r
+ /**\r
+ * the resulting document needs to be tweaked before it can be digested -\r
+ * this applies to the verification and signing step\r
+ *\r
+ * @param doc\r
+ */\r
+ private static void registerIds(Document doc) {\r
+ NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");\r
+ registerIdAttribute(nl);\r
+ nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");\r
+ registerIdAttribute(nl);\r
+ }\r
+ \r
+ public static void registerIdAttribute(NodeList nl) {\r
+ for (int i=0; i<nl.getLength(); i++) {\r
+ Element el = (Element)nl.item(i);\r
+ if (el.hasAttribute("Id")) {\r
+ el.setIdAttribute("Id", true);\r
+ }\r
+ }\r
+ }\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ public static <T> List<T> safe(List<T> other) {\r
+ return other == null ? Collections.EMPTY_LIST : other;\r
+ }\r
}\r
import java.util.ArrayList;\r
import java.util.Date;\r
import java.util.List;\r
+import java.util.UUID;\r
\r
import javax.xml.crypto.URIDereferencer;\r
+import javax.xml.crypto.dsig.CanonicalizationMethod;\r
\r
import org.apache.poi.openxml4j.opc.OPCPackage;\r
import org.apache.poi.poifs.crypt.HashAlgorithm;\r
import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;\r
import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet;\r
import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.facets.SignaturePolicyService;\r
import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService;\r
import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;\r
import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;\r
\r
private AddressDTO address;\r
private byte[] photo;\r
private SignaturePolicyService signaturePolicyService;\r
- private URIDereferencer uriDereferencer; \r
+ private URIDereferencer uriDereferencer;\r
+ private String signatureNamespacePrefix;\r
+ private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE;\r
+\r
+ /**\r
+ * The signature Id attribute value used to create the XML signature. A\r
+ * <code>null</code> value will trigger an automatically generated signature Id.\r
+ */\r
+ private String packageSignatureId = "idPackageSignature";\r
+ \r
+ /**\r
+ * Gives back the human-readable description of what the citizen will be\r
+ * signing. The default value is "Office OpenXML Document".\r
+ */\r
+ private String signatureDescription = "Office OpenXML Document";\r
\r
public SignatureInfoConfig() {\r
OOXMLURIDereferencer uriDereferencer = new OOXMLURIDereferencer();\r
public SignaturePolicyService getSignaturePolicyService() {\r
return signaturePolicyService;\r
}\r
- public void setSignaturePolicyService(\r
- SignaturePolicyService signaturePolicyService) {\r
+ public void setSignaturePolicyService(SignaturePolicyService signaturePolicyService) {\r
this.signaturePolicyService = signaturePolicyService;\r
}\r
public URIDereferencer getUriDereferencer() {\r
public void setUriDereferencer(URIDereferencer uriDereferencer) {\r
this.uriDereferencer = uriDereferencer;\r
}\r
-\r
-\r
+ public String getSignatureDescription() {\r
+ return signatureDescription;\r
+ }\r
+ public void setSignatureDescription(String signatureDescription) {\r
+ this.signatureDescription = signatureDescription;\r
+ }\r
+ public String getSignatureNamespacePrefix() {\r
+ return signatureNamespacePrefix;\r
+ }\r
+ public void setSignatureNamespacePrefix(String signatureNamespacePrefix) {\r
+ this.signatureNamespacePrefix = signatureNamespacePrefix;\r
+ }\r
+ public String getCanonicalizationMethod() {\r
+ return canonicalizationMethod;\r
+ }\r
+ public void setCanonicalizationMethod(String canonicalizationMethod) {\r
+ this.canonicalizationMethod = canonicalizationMethod;\r
+ }\r
+ public String getPackageSignatureId() {\r
+ return packageSignatureId;\r
+ }\r
+ public void setPackageSignatureId(String packageSignatureId) {\r
+ this.packageSignatureId = (packageSignatureId != null)\r
+ ? packageSignatureId\r
+ : "xmldsig-" + UUID.randomUUID();\r
+ }\r
}\r
import javax.xml.crypto.dsig.XMLSignatureFactory;\r
import javax.xml.crypto.dsig.spec.TransformParameterSpec;\r
\r
-import org.apache.poi.poifs.crypt.HashAlgorithm;\r
+import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
import org.w3c.dom.Document;\r
\r
/**\r
*/\r
public class EnvelopedSignatureFacet implements SignatureFacet {\r
\r
- private final HashAlgorithm hashAlgo;\r
+ private SignatureInfoConfig signatureConfig;\r
\r
- /**\r
- * Default constructor. Digest algorithm will be SHA-1.\r
- */\r
- public EnvelopedSignatureFacet() {\r
- this(HashAlgorithm.sha1);\r
- }\r
-\r
- /**\r
- * Main constructor.\r
- * \r
- * @param hashAlgo\r
- * the digest algorithm to be used within the ds:Reference\r
- * element. Possible values: "SHA-1", "SHA-256, or "SHA-512".\r
- */\r
- public EnvelopedSignatureFacet(HashAlgorithm hashAlgo) {\r
- this.hashAlgo = hashAlgo;\r
+ public EnvelopedSignatureFacet(SignatureInfoConfig signatureConfig) {\r
+ this.signatureConfig = signatureConfig;\r
}\r
\r
@Override\r
}\r
\r
@Override\r
- public void preSign(Document document,\r
- XMLSignatureFactory signatureFactory,\r
- String signatureId,\r
- List<X509Certificate> signingCertificateChain,\r
- List<Reference> references, List<XMLObject> objects)\r
- throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
- DigestMethod digestMethod = signatureFactory.newDigestMethod(\r
- this.hashAlgo.xmlSignUri, null);\r
+ public void preSign(Document document\r
+ , XMLSignatureFactory signatureFactory\r
+ , List<Reference> references\r
+ , List<XMLObject> objects)\r
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
+ DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);\r
\r
List<Transform> transforms = new ArrayList<Transform>();\r
Transform envelopedTransform = signatureFactory\r
}\r
\r
@Override\r
- public void preSign(Document document,\r
- XMLSignatureFactory signatureFactory,\r
- String signatureId,\r
- List<X509Certificate> signingCertificateChain,\r
- List<Reference> references,\r
- List<XMLObject> objects\r
+ public void preSign(\r
+ Document document\r
+ , XMLSignatureFactory signatureFactory\r
+ , List<Reference> references\r
+ , List<XMLObject> objects\r
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
// empty\r
}\r
}\r
\r
@Override\r
- public void preSign(Document document,\r
- XMLSignatureFactory signatureFactory,\r
- String signatureId,\r
- List<X509Certificate> signingCertificateChain,\r
- List<Reference> references, List<XMLObject> objects)\r
- throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {\r
+ public void preSign(\r
+ Document document\r
+ , XMLSignatureFactory signatureFactory\r
+ , List<Reference> references\r
+ , List<XMLObject> objects)\r
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {\r
LOG.log(POILogger.DEBUG, "pre sign");\r
- addManifestObject(document, signatureFactory, signatureId, references, objects);\r
- addSignatureInfo(document, signatureFactory, signatureId, references, objects);\r
+ addManifestObject(document, signatureFactory, references, objects);\r
+ addSignatureInfo(document, signatureFactory, references, objects);\r
}\r
\r
private void addManifestObject(Document document,\r
XMLSignatureFactory signatureFactory,\r
- String signatureId, List<Reference> references,\r
+ List<Reference> references,\r
List<XMLObject> objects) throws NoSuchAlgorithmException,\r
InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {\r
\r
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();\r
objectContent.add(manifest);\r
\r
- addSignatureTime(document, signatureFactory, signatureId, objectContent);\r
+ addSignatureTime(document, signatureFactory, objectContent);\r
\r
XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, null, null);\r
objects.add(xo);\r
\r
private void addSignatureTime(Document document,\r
XMLSignatureFactory signatureFactory,\r
- String signatureId,\r
List<XMLStructure> objectContent) {\r
/*\r
* SignatureTime\r
List<XMLStructure> signatureTimeContent = new ArrayList<XMLStructure>();\r
signatureTimeContent.add(new DOMStructure(n));\r
SignatureProperty signatureTimeSignatureProperty = signatureFactory\r
- .newSignatureProperty(signatureTimeContent, "#" + signatureId,\r
+ .newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(),\r
"idSignatureTime");\r
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();\r
signaturePropertyContent.add(signatureTimeSignatureProperty);\r
}\r
\r
private void addSignatureInfo(Document document,\r
- XMLSignatureFactory signatureFactory,\r
- String signatureId, List<Reference> references,\r
- List<XMLObject> objects) throws NoSuchAlgorithmException,\r
- InvalidAlgorithmParameterException {\r
+ XMLSignatureFactory signatureFactory,\r
+ List<Reference> references,\r
+ List<XMLObject> objects)\r
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
List<XMLStructure> objectContent = new ArrayList<XMLStructure>();\r
\r
SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();\r
List<XMLStructure> signatureInfoContent = new ArrayList<XMLStructure>();\r
signatureInfoContent.add(new DOMStructure(n));\r
SignatureProperty signatureInfoSignatureProperty = signatureFactory\r
- .newSignatureProperty(signatureInfoContent, "#" + signatureId,\r
+ .newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(),\r
"idOfficeV1Details");\r
\r
List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();\r
public class Office2010SignatureFacet implements SignatureFacet {\r
\r
@Override\r
- public void preSign(Document document,\r
- XMLSignatureFactory signatureFactory,\r
- String signatureId,\r
- List<X509Certificate> signingCertificateChain,\r
- List<Reference> references,\r
- List<XMLObject> objects\r
+ public void preSign(\r
+ Document document\r
+ , XMLSignatureFactory signatureFactory\r
+ , List<Reference> references\r
+ , List<XMLObject> objects\r
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
}\r
\r
void preSign(\r
Document document\r
, XMLSignatureFactory signatureFactory\r
- , String signatureId\r
- , List<X509Certificate> signingCertificateChain\r
, List<Reference> references\r
, List<XMLObject> objects\r
) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException;\r
+++ /dev/null
-/* ====================================================================\r
- Licensed to the Apache Software Foundation (ASF) under one or more\r
- contributor license agreements. See the NOTICE file distributed with\r
- this work for additional information regarding copyright ownership.\r
- The ASF licenses this file to You under the Apache License, Version 2.0\r
- (the "License"); you may not use this file except in compliance with\r
- the License. You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-==================================================================== */\r
-\r
-/* ====================================================================\r
- This product contains an ASLv2 licensed version of the OOXML signer\r
- package from the eID Applet project\r
- http://code.google.com/p/eid-applet/source/browse/trunk/README.txt \r
- Copyright (C) 2008-2014 FedICT.\r
- ================================================================= */ \r
-\r
-package org.apache.poi.poifs.crypt.dsig.facets;\r
-\r
-/**\r
- * Interface for the signature policy service.\r
- * \r
- * @author Frank Cornelis\r
- * \r
- */\r
-public interface SignaturePolicyService {\r
-\r
- /**\r
- * Gives back the signature policy identifier URI.\r
- * \r
- * @return\r
- */\r
- String getSignaturePolicyIdentifier();\r
-\r
- /**\r
- * Gives back the short description of the signature policy or\r
- * <code>null</code> if a description is not available.\r
- * \r
- * @return the description, or <code>null</code>.\r
- */\r
- String getSignaturePolicyDescription();\r
-\r
- /**\r
- * Gives back the download URL where the signature policy document can be\r
- * found. Can be <code>null</code> in case such a download location does not\r
- * exist.\r
- * \r
- * @return the download URL, or <code>null</code>.\r
- */\r
- String getSignaturePolicyDownloadUrl();\r
-\r
- /**\r
- * Gives back the signature policy document.\r
- * \r
- * @return the bytes of the signature policy document.\r
- */\r
- byte[] getSignaturePolicyDocument();\r
-}
\ No newline at end of file
import org.apache.poi.poifs.crypt.HashAlgorithm;\r
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
-import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
+import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
+import org.apache.xmlbeans.XmlCursor;\r
+import org.apache.xmlbeans.XmlObject;\r
import org.apache.xmlbeans.XmlString;\r
import org.etsi.uri.x01903.v13.AnyType;\r
import org.etsi.uri.x01903.v13.CertIDListType;\r
@Override\r
public void preSign(Document document,\r
XMLSignatureFactory signatureFactory,\r
- String signatureId,\r
- List<X509Certificate> signingCertificateChain,\r
List<Reference> references, List<XMLObject> objects)\r
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
LOG.log(POILogger.DEBUG, "preSign");\r
// QualifyingProperties\r
QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance();\r
QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties();\r
- qualifyingProperties.setTarget("#" + signatureId);\r
+ qualifyingProperties.setTarget("#" + signatureConfig.getPackageSignatureId());\r
\r
// SignedProperties\r
SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties();\r
String signedPropertiesId = this.idSignedProperties;\r
if (this.idSignedProperties == null) {\r
- signedPropertiesId = signatureId + "-xades";\r
+ signedPropertiesId = signatureConfig.getPackageSignatureId() + "-xades";\r
}\r
signedProperties.setId(signedPropertiesId);\r
\r
signedSignatureProperties.setSigningTime(xmlGregorianCalendar);\r
\r
// SigningCertificate\r
- if (null == signingCertificateChain\r
- || signingCertificateChain.isEmpty()) {\r
+ if (signatureConfig.getSigningCertificateChain() == null\r
+ || signatureConfig.getSigningCertificateChain().isEmpty()) {\r
throw new RuntimeException("no signing certificate chain available");\r
}\r
CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate();\r
CertIDType certId = signingCertificates.addNewCert();\r
- X509Certificate signingCertificate = signingCertificateChain.get(0);\r
+ X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0);\r
setCertID(certId, signingCertificate, this.signatureConfig.getDigestAlgo(), this.issuerNameNoReverseOrder);\r
\r
// ClaimedRole\r
AnyType claimedRole = claimedRolesList.addNewClaimedRole();\r
XmlString roleString = XmlString.Factory.newInstance();\r
roleString.setStringValue(this.role);\r
- SignatureInfo.insertXChild(claimedRole, roleString);\r
+ insertXChild(claimedRole, roleString);\r
}\r
\r
// XAdES-EPES\r
AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier();\r
XmlString spUriElement = XmlString.Factory.newInstance();\r
spUriElement.setStringValue(signaturePolicyDownloadUrl);\r
- SignatureInfo.insertXChild(sigPolicyQualifier, spUriElement);\r
+ insertXChild(sigPolicyQualifier, spUriElement);\r
}\r
} else if (this.signaturePolicyImplied) {\r
SignaturePolicyIdentifierType signaturePolicyIdentifier = \r
// add XAdES ds:Object\r
List<XMLStructure> xadesObjectContent = new ArrayList<XMLStructure>();\r
Element qualDocEl = (Element)document.importNode(qualifyingProperties.getDomNode(), true);\r
- XmlSignatureService.registerIdAttribute(qualDocEl.getElementsByTagName("SignedProperties"));\r
+ SignatureInfo.registerIdAttribute(qualDocEl.getElementsByTagName("SignedProperties"));\r
qualDocEl.setAttributeNS(XmlNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#");\r
setPrefix(qualDocEl, "http://uri.etsi.org/01903/v1.3.2#", "xd");\r
xadesObjectContent.add(new DOMStructure(qualDocEl));\r
return map;\r
}\r
\r
+ protected static void insertXChild(XmlObject root, XmlObject child) {\r
+ XmlCursor rootCursor = root.newCursor();\r
+ rootCursor.toEndToken();\r
+ XmlCursor childCursor = child.newCursor();\r
+ childCursor.toNextToken();\r
+ childCursor.moveXml(rootCursor);\r
+ childCursor.dispose();\r
+ rootCursor.dispose();\r
+ }\r
+\r
}
\ No newline at end of file
package org.apache.poi.poifs.crypt.dsig.facets;\r
\r
import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;\r
+import static org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet.insertXChild;\r
\r
import java.io.ByteArrayInputStream;\r
import java.io.ByteArrayOutputStream;\r
import javax.xml.crypto.dsig.XMLSignatureFactory;\r
\r
import org.apache.poi.poifs.crypt.HashAlgorithm;\r
-import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;\r
import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;\r
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;\r
// xadesv141::TimeStampValidationData\r
if (tsaRevocationDataXadesT.hasRevocationDataEntries()) {\r
ValidationDataType validationData = createValidationData(tsaRevocationDataXadesT);\r
- SignatureInfo.insertXChild(unsignedSigProps, validationData);\r
+ insertXChild(unsignedSigProps, validationData);\r
}\r
\r
if (null == this.revocationDataService) {\r
this.c14nAlgoId, this.timeStampService);\r
if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) {\r
ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1);\r
- SignatureInfo.insertXChild(unsignedSigProps, timeStampXadesX1ValidationData);\r
+ insertXChild(unsignedSigProps, timeStampXadesX1ValidationData);\r
}\r
\r
// marshal XAdES-X\r
@Override\r
public void preSign(Document document,\r
XMLSignatureFactory signatureFactory,\r
- String signatureId,\r
- List<X509Certificate> signingCertificateChain,\r
List<Reference> references, List<XMLObject> objects)\r
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
// nothing to do here\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+/* ====================================================================\r
+ This product contains an ASLv2 licensed version of the OOXML signer\r
+ package from the eID Applet project\r
+ http://code.google.com/p/eid-applet/source/browse/trunk/README.txt \r
+ Copyright (C) 2008-2014 FedICT.\r
+ ================================================================= */ \r
+\r
+package org.apache.poi.poifs.crypt.dsig.services;\r
+\r
+/**\r
+ * Interface for the signature policy service.\r
+ * \r
+ * @author Frank Cornelis\r
+ * \r
+ */\r
+public interface SignaturePolicyService {\r
+\r
+ /**\r
+ * Gives back the signature policy identifier URI.\r
+ * \r
+ * @return\r
+ */\r
+ String getSignaturePolicyIdentifier();\r
+\r
+ /**\r
+ * Gives back the short description of the signature policy or\r
+ * <code>null</code> if a description is not available.\r
+ * \r
+ * @return the description, or <code>null</code>.\r
+ */\r
+ String getSignaturePolicyDescription();\r
+\r
+ /**\r
+ * Gives back the download URL where the signature policy document can be\r
+ * found. Can be <code>null</code> in case such a download location does not\r
+ * exist.\r
+ * \r
+ * @return the download URL, or <code>null</code>.\r
+ */\r
+ String getSignaturePolicyDownloadUrl();\r
+\r
+ /**\r
+ * Gives back the signature policy document.\r
+ * \r
+ * @return the bytes of the signature policy document.\r
+ */\r
+ byte[] getSignaturePolicyDocument();\r
+}
\ No newline at end of file
+++ /dev/null
-/* ====================================================================\r
- Licensed to the Apache Software Foundation (ASF) under one or more\r
- contributor license agreements. See the NOTICE file distributed with\r
- this work for additional information regarding copyright ownership.\r
- The ASF licenses this file to You under the Apache License, Version 2.0\r
- (the "License"); you may not use this file except in compliance with\r
- the License. You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-==================================================================== */\r
-\r
-/* ====================================================================\r
- This product contains an ASLv2 licensed version of the OOXML signer\r
- package from the eID Applet project\r
- http://code.google.com/p/eid-applet/source/browse/trunk/README.txt \r
- Copyright (C) 2008-2014 FedICT.\r
- ================================================================= */ \r
-\r
-package org.apache.poi.poifs.crypt.dsig.services;\r
-\r
-import java.io.IOException;\r
-import java.security.NoSuchAlgorithmException;\r
-import java.util.List;\r
-\r
-import javax.xml.crypto.MarshalException;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-\r
-import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
-import org.apache.xmlbeans.XmlException;\r
-import org.w3c.dom.Document;\r
-\r
-/**\r
- * Interface for signature service component.\r
- * \r
- * @author Frank Cornelis\r
- * \r
- */\r
-public interface SignatureService {\r
-\r
- /**\r
- * Pre-sign callback method. Depending on the configuration some parameters\r
- * are passed. The returned value will be signed by the eID Applet.\r
- * \r
- * @param digestInfos\r
- * the optional list of digest infos.\r
- * @return the digest to be signed.\r
- * @throws NoSuchAlgorithmException\r
- */\r
- DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
- throws NoSuchAlgorithmException;\r
-\r
- /**\r
- * Post-sign callback method. Received the signature value. Depending on the\r
- * configuration the signing certificate chain is also obtained.\r
- * \r
- * @param signatureValue\r
- * @param signingCertificateChain\r
- * the optional chain of signing certificates.\r
- */\r
- void postSign(Document document, byte[] signatureValue)\r
- throws IOException, MarshalException, ParserConfigurationException, XmlException;\r
-}\r
+++ /dev/null
-/* ====================================================================\r
- Licensed to the Apache Software Foundation (ASF) under one or more\r
- contributor license agreements. See the NOTICE file distributed with\r
- this work for additional information regarding copyright ownership.\r
- The ASF licenses this file to You under the Apache License, Version 2.0\r
- (the "License"); you may not use this file except in compliance with\r
- the License. You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-==================================================================== */\r
-\r
-/* ====================================================================\r
- This product contains an ASLv2 licensed version of the OOXML signer\r
- package from the eID Applet project\r
- http://code.google.com/p/eid-applet/source/browse/trunk/README.txt \r
- Copyright (C) 2008-2014 FedICT.\r
- ================================================================= */ \r
-\r
-package org.apache.poi.poifs.crypt.dsig.services;\r
-\r
-import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;\r
-import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;\r
-\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.MalformedURLException;\r
-import java.net.URISyntaxException;\r
-import java.security.InvalidAlgorithmParameterException;\r
-import java.security.MessageDigest;\r
-import java.security.NoSuchAlgorithmException;\r
-import java.security.NoSuchProviderException;\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.UUID;\r
-\r
-import javax.xml.crypto.MarshalException;\r
-import javax.xml.crypto.URIDereferencer;\r
-import javax.xml.crypto.XMLStructure;\r
-import javax.xml.crypto.dsig.CanonicalizationMethod;\r
-import javax.xml.crypto.dsig.DigestMethod;\r
-import javax.xml.crypto.dsig.Manifest;\r
-import javax.xml.crypto.dsig.Reference;\r
-import javax.xml.crypto.dsig.SignatureMethod;\r
-import javax.xml.crypto.dsig.SignedInfo;\r
-import javax.xml.crypto.dsig.XMLObject;\r
-import javax.xml.crypto.dsig.XMLSignContext;\r
-import javax.xml.crypto.dsig.XMLSignatureFactory;\r
-import javax.xml.crypto.dsig.dom.DOMSignContext;\r
-import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import javax.xml.transform.TransformerException;\r
-import javax.xml.transform.TransformerFactoryConfigurationError;\r
-\r
-import org.apache.jcp.xml.dsig.internal.dom.DOMReference;\r
-import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;\r
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
-import org.apache.poi.openxml4j.opc.OPCPackage;\r
-import org.apache.poi.openxml4j.opc.PackageNamespaces;\r
-import org.apache.poi.openxml4j.opc.PackagePart;\r
-import org.apache.poi.openxml4j.opc.PackagePartName;\r
-import org.apache.poi.openxml4j.opc.PackageRelationship;\r
-import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;\r
-import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;\r
-import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
-import org.apache.poi.openxml4j.opc.TargetMode;\r
-import org.apache.poi.poifs.crypt.CryptoFunctions;\r
-import org.apache.poi.poifs.crypt.HashAlgorithm;\r
-import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
-import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
-import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
-import org.apache.poi.util.POILogFactory;\r
-import org.apache.poi.util.POILogger;\r
-import org.apache.xml.security.signature.XMLSignature;\r
-import org.apache.xml.security.utils.Base64;\r
-import org.apache.xmlbeans.XmlException;\r
-import org.apache.xmlbeans.XmlOptions;\r
-import org.w3.x2000.x09.xmldsig.SignatureDocument;\r
-import org.w3c.dom.Document;\r
-import org.w3c.dom.Element;\r
-import org.w3c.dom.NodeList;\r
-import org.w3c.dom.events.Event;\r
-import org.w3c.dom.events.EventListener;\r
-import org.w3c.dom.events.EventTarget;\r
-import org.w3c.dom.events.MutationEvent;\r
-import org.xml.sax.SAXException;\r
-\r
-\r
-/**\r
- * Abstract base class for an XML Signature Service implementation.\r
- */\r
-public class XmlSignatureService implements SignatureService {\r
- private static final POILogger LOG = POILogFactory.getLogger(XmlSignatureService.class);\r
-\r
- protected SignatureInfoConfig signatureConfig;\r
- \r
- private String signatureNamespacePrefix;\r
- private String signatureId = "idPackageSignature";\r
- \r
- /**\r
- * Main constructor.\r
- */\r
- public XmlSignatureService(SignatureInfoConfig signatureConfig) {\r
- this.signatureNamespacePrefix = null;\r
- this.signatureConfig = signatureConfig;\r
- }\r
- \r
- public SignatureInfoConfig getSignatureConfig() {\r
- return signatureConfig;\r
- }\r
-\r
- /**\r
- * Sets the signature Id attribute value used to create the XML signature. A\r
- * <code>null</code> value will trigger an automatically generated signature\r
- * Id.\r
- * \r
- * @param signatureId\r
- */\r
- protected void setSignatureId(String signatureId) {\r
- this.signatureId = signatureId;\r
- }\r
-\r
- /**\r
- * Sets the XML Signature namespace prefix to be used for signature\r
- * creation. A <code>null</code> value will omit the prefixing.\r
- * \r
- * @param signatureNamespacePrefix\r
- */\r
- protected void setSignatureNamespacePrefix(String signatureNamespacePrefix) {\r
- this.signatureNamespacePrefix = signatureNamespacePrefix;\r
- }\r
-\r
- /**\r
- * Gives back the human-readable description of what the citizen will be\r
- * signing. The default value is "XML Document". Override this method to\r
- * provide the citizen with another description.\r
- * \r
- * @return\r
- */\r
- protected String getSignatureDescription() {\r
- return "Office OpenXML Document";\r
- }\r
-\r
- /**\r
- * Gives back the output stream to which to write the signed XML document.\r
- * \r
- * @return\r
- */\r
- // protected abstract OutputStream getSignedDocumentOutputStream();\r
- @Override\r
- public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
- throws NoSuchAlgorithmException {\r
- SignatureInfo.initXmlProvider();\r
-\r
- LOG.log(POILogger.DEBUG, "preSign");\r
- HashAlgorithm hashAlgo = this.signatureConfig.getDigestAlgo();\r
-\r
- byte[] digestValue;\r
- try {\r
- digestValue = getXmlSignatureDigestValue(document, digestInfos);\r
- } catch (Exception e) {\r
- throw new RuntimeException("XML signature error: " + e.getMessage(), e);\r
- }\r
-\r
- String description = getSignatureDescription();\r
- return new DigestInfo(digestValue, hashAlgo, description);\r
- }\r
-\r
- @Override\r
- public void postSign(Document document, byte[] signatureValue)\r
- throws IOException, MarshalException, ParserConfigurationException, XmlException {\r
- LOG.log(POILogger.DEBUG, "postSign");\r
- SignatureInfo.initXmlProvider();\r
-\r
- /*\r
- * Check ds:Signature node.\r
- */\r
- if (!signatureId.equals(document.getDocumentElement().getAttribute("Id"))) {\r
- throw new RuntimeException("ds:Signature not found for @Id: " + signatureId);\r
- }\r
-\r
- /*\r
- * Insert signature value into the ds:SignatureValue element\r
- */\r
- NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");\r
- if (sigValNl.getLength() != 1) {\r
- throw new RuntimeException("preSign has to be called before postSign");\r
- }\r
- sigValNl.item(0).setTextContent(Base64.encode(signatureValue));\r
-\r
- /*\r
- * Allow signature facets to inject their own stuff.\r
- */\r
- for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {\r
- signatureFacet.postSign(document, this.signatureConfig.getSigningCertificateChain());\r
- }\r
-\r
- registerIds(document);\r
- writeDocument(document);\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- private byte[] getXmlSignatureDigestValue(Document document, List<DigestInfo> digestInfos)\r
- throws ParserConfigurationException, NoSuchAlgorithmException,\r
- InvalidAlgorithmParameterException, MarshalException,\r
- javax.xml.crypto.dsig.XMLSignatureException,\r
- TransformerFactoryConfigurationError, TransformerException,\r
- IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException {\r
-\r
- // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
- // normal way to interfere with, so we need to add the namespace under the hand ...\r
- final EventTarget et = (EventTarget)document;\r
- EventListener myModificationListener = new EventListener() {\r
- @Override\r
- public void handleEvent(Event e) {\r
- if (e instanceof MutationEvent) {\r
- MutationEvent mutEvt = (MutationEvent)e;\r
- if (mutEvt.getTarget() instanceof Element) {\r
- Element el = (Element)mutEvt.getTarget();\r
- if ("idPackageObject".equals(el.getAttribute("Id"))) {\r
- et.removeEventListener("DOMSubtreeModified", this, false);\r
- el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);\r
- }\r
- }\r
- }\r
- }\r
- };\r
- \r
- et.addEventListener("DOMSubtreeModified", myModificationListener, false);\r
- \r
- /*\r
- * Signature context construction.\r
- */\r
- XMLSignContext xmlSignContext = new DOMSignContext(this.signatureConfig.getKey(), document);\r
- URIDereferencer uriDereferencer = this.signatureConfig.getUriDereferencer();\r
- if (null != uriDereferencer) {\r
- xmlSignContext.setURIDereferencer(uriDereferencer);\r
- }\r
-\r
- xmlSignContext.putNamespacePrefix(\r
- "http://schemas.openxmlformats.org/package/2006/digital-signature",\r
- "mdssi");\r
- \r
- if (this.signatureNamespacePrefix != null) {\r
- /*\r
- * OOo doesn't like ds namespaces so per default prefixing is off.\r
- */\r
- xmlSignContext.putNamespacePrefix(XmlDSigNS, this.signatureNamespacePrefix);\r
- }\r
-\r
- XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();\r
-\r
- /*\r
- * Add ds:References that come from signing client local files.\r
- */\r
- List<Reference> references = new ArrayList<Reference>();\r
- addDigestInfosAsReferences(digestInfos, signatureFactory, references);\r
-\r
- /*\r
- * Invoke the signature facets.\r
- */\r
- String localSignatureId = this.signatureId;\r
- if (localSignatureId == null) {\r
- localSignatureId = "xmldsig-" + UUID.randomUUID().toString();\r
- }\r
- List<XMLObject> objects = new ArrayList<XMLObject>();\r
- for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {\r
- LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
- signatureFacet.preSign(document, signatureFactory, localSignatureId, this.signatureConfig.getSigningCertificateChain(), references, objects);\r
- }\r
-\r
- /*\r
- * ds:SignedInfo\r
- */\r
- SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(this.signatureConfig.getDigestAlgo()), null);\r
- CanonicalizationMethod canonicalizationMethod = signatureFactory\r
- .newCanonicalizationMethod(getCanonicalizationMethod(),\r
- (C14NMethodParameterSpec) null);\r
- SignedInfo signedInfo = signatureFactory.newSignedInfo(\r
- canonicalizationMethod, signatureMethod, references);\r
-\r
- /*\r
- * JSR105 ds:Signature creation\r
- */\r
- String signatureValueId = localSignatureId + "-signature-value";\r
- javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
- .newXMLSignature(signedInfo, null, objects, localSignatureId,\r
- signatureValueId);\r
-\r
- /*\r
- * ds:Signature Marshalling.\r
- */\r
- xmlSignContext.setDefaultNamespacePrefix(this.signatureNamespacePrefix);\r
- // xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");\r
- xmlSignature.sign(xmlSignContext);\r
-\r
- registerIds(document);\r
- \r
- /*\r
- * Completion of undigested ds:References in the ds:Manifests.\r
- */\r
- for (XMLObject object : objects) {\r
- LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
- List<XMLStructure> objectContentList = object.getContent();\r
- for (XMLStructure objectContent : objectContentList) {\r
- LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
- if (!(objectContent instanceof Manifest)) continue;\r
- Manifest manifest = (Manifest) objectContent;\r
- List<Reference> manifestReferences = manifest.getReferences();\r
- for (Reference manifestReference : manifestReferences) {\r
- if (manifestReference.getDigestValue() != null) continue;\r
-\r
- DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
- manifestDOMReference.digest(xmlSignContext);\r
- }\r
- }\r
- }\r
-\r
- /*\r
- * Completion of undigested ds:References.\r
- */\r
- List<Reference> signedInfoReferences = signedInfo.getReferences();\r
- for (Reference signedInfoReference : signedInfoReferences) {\r
- DOMReference domReference = (DOMReference)signedInfoReference;\r
-\r
- // ds:Reference with external digest value\r
- if (domReference.getDigestValue() != null) continue;\r
- \r
- domReference.digest(xmlSignContext);\r
- }\r
-\r
- /*\r
- * Calculation of XML signature digest value.\r
- */\r
- DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
- ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
- domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
- byte[] octets = dataStream.toByteArray();\r
-\r
- /*\r
- * TODO: we could be using DigestOutputStream here to optimize memory\r
- * usage.\r
- */\r
-\r
- MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(this.signatureConfig.getDigestAlgo());\r
- byte[] digestValue = jcaMessageDigest.digest(octets);\r
- return digestValue;\r
- }\r
-\r
- /**\r
- * the resulting document needs to be tweaked before it can be digested -\r
- * this applies to the verification and signing step\r
- *\r
- * @param doc\r
- */\r
- public static void registerIds(Document doc) {\r
- NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");\r
- registerIdAttribute(nl);\r
- nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");\r
- registerIdAttribute(nl);\r
- }\r
- \r
- public static void registerIdAttribute(NodeList nl) {\r
- for (int i=0; i<nl.getLength(); i++) {\r
- Element el = (Element)nl.item(i);\r
- if (el.hasAttribute("Id")) {\r
- el.setIdAttribute("Id", true);\r
- }\r
- }\r
- }\r
- \r
- private void addDigestInfosAsReferences(List<DigestInfo> digestInfos, XMLSignatureFactory signatureFactory, List<Reference> references)\r
- throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, MalformedURLException {\r
- for (DigestInfo digestInfo : safe(digestInfos)) {\r
- byte[] documentDigestValue = digestInfo.digestValue;\r
-\r
- DigestMethod digestMethod = signatureFactory.newDigestMethod(\r
- digestInfo.hashAlgo.xmlSignUri, null);\r
-\r
- String uri = new File(digestInfo.description).getName();\r
-\r
- Reference reference = signatureFactory.newReference(uri,\r
- digestMethod, null, null, null, documentDigestValue);\r
- references.add(reference);\r
- }\r
- }\r
-\r
- private String getSignatureMethod(HashAlgorithm hashAlgo) {\r
- if (null == hashAlgo) {\r
- throw new RuntimeException("digest algo is null");\r
- }\r
-\r
- switch (hashAlgo) {\r
- case sha1: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;\r
- case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;\r
- case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;\r
- case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;\r
- case ripemd160: return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;\r
- default: break;\r
- }\r
-\r
- throw new RuntimeException("unsupported sign algo: " + hashAlgo);\r
- }\r
-\r
- protected String getCanonicalizationMethod() {\r
- return CanonicalizationMethod.INCLUSIVE;\r
- }\r
-\r
- protected void writeDocument(Document document) throws IOException, XmlException {\r
- XmlOptions xo = new XmlOptions();\r
- Map<String,String> namespaceMap = new HashMap<String,String>();\r
- for (SignatureFacet sf : this.signatureConfig.getSignatureFacets()) {\r
- Map<String,String> sfm = sf.getNamespacePrefixMapping();\r
- if (sfm != null) {\r
- namespaceMap.putAll(sfm);\r
- }\r
- }\r
- xo.setSaveSuggestedPrefixes(namespaceMap);\r
- xo.setUseDefaultNamespace();\r
-\r
- LOG.log(POILogger.DEBUG, "output signed Office OpenXML document");\r
-\r
- /*\r
- * Copy the original OOXML content to the signed OOXML package. During\r
- * copying some files need to changed.\r
- */\r
- OPCPackage pkg = this.signatureConfig.getOpcPackage();\r
-\r
- PackagePartName sigPartName, sigsPartName;\r
- try {\r
- // <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/>\r
- sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig1.xml");\r
- // <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>\r
- sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs");\r
- } catch (InvalidFormatException e) {\r
- throw new IOException(e);\r
- }\r
- \r
- String sigContentType = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml";\r
- PackagePart sigPart = pkg.getPart(sigPartName);\r
- if (sigPart == null) {\r
- sigPart = pkg.createPart(sigPartName, sigContentType);\r
- }\r
- \r
- OutputStream os = sigPart.getOutputStream();\r
- SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);\r
- sigDoc.save(os, xo);\r
- os.close();\r
- \r
- String sigsContentType = "application/vnd.openxmlformats-package.digital-signature-origin";\r
- PackagePart sigsPart = pkg.getPart(sigsPartName);\r
- if (sigsPart == null) {\r
- // touch empty marker file\r
- sigsPart = pkg.createPart(sigsPartName, sigsContentType);\r
- }\r
- \r
- PackageRelationshipCollection relCol = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
- for (PackageRelationship pr : relCol) {\r
- pkg.removeRelationship(pr.getId());\r
- }\r
- pkg.addRelationship(sigsPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
- \r
- sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- public static <T> List<T> safe(List<T> other) {\r
- return other == null ? Collections.EMPTY_LIST : other;\r
- }\r
-}\r
import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService;\r
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;\r
import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;\r
-import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
import org.apache.poi.util.DocumentHelper;\r
import org.apache.poi.util.IOUtils;\r
\r
for (String testFile : testFiles) {\r
OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
- SignatureInfo si = new SignatureInfo(pkg);\r
+ SignatureInfoConfig sic = new SignatureInfoConfig();\r
+ sic.setOpcPackage(pkg);\r
+ SignatureInfo si = new SignatureInfo();\r
+ si.setSignatureConfig(sic);\r
List<X509Certificate> result = si.getSigners();\r
pkg.revert();\r
pkg.close();\r
\r
for (String testFile : testFiles) {\r
OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
- SignatureInfo si = new SignatureInfo(pkg);\r
+ SignatureInfoConfig sic = new SignatureInfoConfig();\r
+ sic.setOpcPackage(pkg);\r
+ SignatureInfo si = new SignatureInfo();\r
+ si.setSignatureConfig(sic);\r
List<X509Certificate> result = si.getSigners();\r
\r
assertNotNull(result);\r
public void getMultiSigners() throws Exception {\r
String testFile = "hello-world-signed-twice.docx";\r
OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
- SignatureInfo si = new SignatureInfo(pkg);\r
+ SignatureInfoConfig sic = new SignatureInfoConfig();\r
+ sic.setOpcPackage(pkg);\r
+ SignatureInfo si = new SignatureInfo();\r
+ si.setSignatureConfig(sic);\r
List<X509Certificate> result = si.getSigners();\r
\r
assertNotNull(result);\r
\r
@Test\r
public void testSignSpreadsheetWithSignatureInfo() throws Exception {\r
+ initKeyPair("Test", "CN=Test");\r
String testFile = "hello-world-unsigned.xlsx";\r
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);\r
- SignatureInfo si = new SignatureInfo(pkg);\r
- initKeyPair("Test", "CN=Test");\r
+ SignatureInfoConfig sic = new SignatureInfoConfig();\r
+ sic.setOpcPackage(pkg);\r
+ sic.setKey(keyPair.getPrivate());\r
+ sic.setSigningCertificateChain(Collections.singletonList(x509));\r
+ sic.addDefaultFacets();\r
+ SignatureInfo si = new SignatureInfo();\r
+ si.setSignatureConfig(sic);\r
// hash > sha1 doesn't work in excel viewer ...\r
- si.confirmSignature(keyPair.getPrivate(), x509, HashAlgorithm.sha1);\r
+ si.confirmSignature();\r
List<X509Certificate> signer = si.getSigners();\r
assertEquals(1, signer.size());\r
pkg.close();\r
certificateChain.add(x509);\r
signatureConfig.setSigningCertificateChain(certificateChain);\r
\r
- signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet());\r
+ signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet(signatureConfig));\r
signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));\r
signatureConfig.addSignatureFacet(new XAdESSignatureFacet(signatureConfig));\r
\r
\r
XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(\r
timeStampService, revocationDataService);\r
- XmlSignatureService testedInstance = new XmlSignatureService(signatureConfig);\r
+ SignatureInfo si = new SignatureInfo();\r
+ si.setSignatureConfig(signatureConfig);\r
\r
Document document = DocumentHelper.createDocument();\r
\r
// operate\r
- DigestInfo digestInfo = testedInstance.preSign(document, null);\r
+ DigestInfo digestInfo = si.preSign(document, null);\r
\r
// verify\r
assertNotNull(digestInfo);\r
assertNotNull(certDigest.getDigestValue());\r
\r
// Sign the received XML signature digest value.\r
- byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);\r
+ byte[] signatureValue = si.signDigest(digestInfo.digestValue);\r
\r
// Operate: postSign\r
- testedInstance.postSign(document, signatureValue);\r
+ si.postSign(document, signatureValue);\r
\r
DOMValidateContext domValidateContext = new DOMValidateContext(\r
KeySelector.singletonKeySelector(keyPair.getPublic()),\r
signatureConfig.setOpcPackage(pkgCopy);\r
signatureConfig.addDefaultFacets();\r
\r
- XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);\r
+ SignatureInfo si = new SignatureInfo();\r
+ si.setSignatureConfig(signatureConfig);\r
\r
Document document = DocumentHelper.createDocument();\r
\r
// operate\r
- DigestInfo digestInfo = signatureService.preSign(document, null);\r
+ DigestInfo digestInfo = si.preSign(document, null);\r
\r
// verify\r
assertNotNull(digestInfo);\r
assertNotNull(digestInfo.digestValue);\r
\r
// setup: key material, signature value\r
- byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);\r
+ byte[] signatureValue = si.signDigest(digestInfo.digestValue);\r
\r
// operate: postSign\r
- signatureService.postSign(document, signatureValue);\r
+ si.postSign(document, signatureValue);\r
\r
// verify: signature\r
- SignatureInfo si = new SignatureInfo(pkgCopy);\r
+ si.getSignatureConfig().setOpcPackage(pkgCopy);\r
List<X509Certificate> signers = si.getSigners();\r
assertEquals(signerCount, signers.size());\r
\r