Author: kiwiwings
Date: Sun Sep 28 22:30:02 2014
New Revision: 1628107

URL: http://svn.apache.org/r1628107
Log:
more tests, some refactoring

Added:
    poi/branches/xml_signature/test-data/xmldsign/chaintest.pfx   (with props)
Modified:
    
poi/branches/xml_signature/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java
    
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java
    
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java
    
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java
    
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java
    
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
    
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
    
poi/branches/xml_signature/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java

Modified: 
poi/branches/xml_signature/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java
URL: 
http://svn.apache.org/viewvc/poi/branches/xml_signature/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java?rev=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java
 (original)
+++ 
poi/branches/xml_signature/src/java/org/apache/poi/poifs/crypt/HashAlgorithm.java
 Sun Sep 28 22:30:02 2014
@@ -17,24 +17,24 @@
 
 package org.apache.poi.poifs.crypt;
 
-import javax.xml.crypto.dsig.DigestMethod;
-
 import org.apache.poi.EncryptedDocumentException;
 
 public enum HashAlgorithm {
-    none     (         "", 0x0000,           "",  0,               "", null, 
false),
-    sha1     (    "SHA-1", 0x8004,       "SHA1", 20,       "HmacSHA1", 
DigestMethod.SHA1, false),
-    sha256   (  "SHA-256", 0x800C,     "SHA256", 32,     "HmacSHA256", 
DigestMethod.SHA256, false),
-    sha384   (  "SHA-384", 0x800D,     "SHA384", 48,     "HmacSHA384", null, 
false),
-    sha512   (  "SHA-512", 0x800E,     "SHA512", 64,     "HmacSHA512", 
DigestMethod.SHA512, false),
+    none     (         "", 0x0000,           "",  0,               "", false),
+    sha1     (    "SHA-1", 0x8004,       "SHA1", 20,       "HmacSHA1", false),
+    sha256   (  "SHA-256", 0x800C,     "SHA256", 32,     "HmacSHA256", false),
+    sha384   (  "SHA-384", 0x800D,     "SHA384", 48,     "HmacSHA384", false),
+    sha512   (  "SHA-512", 0x800E,     "SHA512", 64,     "HmacSHA512", false),
     /* only for agile encryption */
-    md5      (      "MD5",     -1,        "MD5", 16,        "HmacMD5", null, 
false),
+    md5      (      "MD5",     -1,        "MD5", 16,        "HmacMD5", false),
     // although sunjc2 supports md2, hmac-md2 is only supported by bouncycastle
-    md2      (      "MD2",     -1,        "MD2", 16,       "Hmac-MD2", null, 
true),
-    md4      (      "MD4",     -1,        "MD4", 16,       "Hmac-MD4", null, 
true),
-    ripemd128("RipeMD128",     -1, "RIPEMD-128", 16, "HMac-RipeMD128", null, 
true),
-    ripemd160("RipeMD160",     -1, "RIPEMD-160", 20, "HMac-RipeMD160", 
DigestMethod.RIPEMD160, true),
-    whirlpool("Whirlpool",     -1,  "WHIRLPOOL", 64, "HMac-Whirlpool", null, 
true),
+    md2      (      "MD2",     -1,        "MD2", 16,       "Hmac-MD2", true),
+    md4      (      "MD4",     -1,        "MD4", 16,       "Hmac-MD4", true),
+    ripemd128("RipeMD128",     -1, "RIPEMD-128", 16, "HMac-RipeMD128", true),
+    ripemd160("RipeMD160",     -1, "RIPEMD-160", 20, "HMac-RipeMD160", true),
+    whirlpool("Whirlpool",     -1,  "WHIRLPOOL", 64, "HMac-Whirlpool", true),
+    // only for xml signing
+    sha224   (  "SHA-224",     -1,     "SHA224", 28,     "HmacSHA224", true);
     ;
 
     public final String jceId;
@@ -42,16 +42,14 @@ public enum HashAlgorithm {
     public final String ecmaString;
     public final int hashSize;
     public final String jceHmacId;
-    public final String xmlSignUri;
     public final boolean needsBouncyCastle;
     
-    HashAlgorithm(String jceId, int ecmaId, String ecmaString, int hashSize, 
String jceHmacId, String xmlSignUri, boolean needsBouncyCastle) {
+    HashAlgorithm(String jceId, int ecmaId, String ecmaString, int hashSize, 
String jceHmacId, boolean needsBouncyCastle) {
         this.jceId = jceId;
         this.ecmaId = ecmaId;
         this.ecmaString = ecmaString;
         this.hashSize = hashSize;
         this.jceHmacId = jceHmacId;
-        this.xmlSignUri = xmlSignUri;
         this.needsBouncyCastle = needsBouncyCastle;
     }
     

Modified: 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java
URL: 
http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java?rev=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java
 (original)
+++ 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/KeyInfoKeySelector.java
 Sun Sep 28 22:30:02 2014
@@ -26,6 +26,7 @@ package org.apache.poi.poifs.crypt.dsig;
 
 import java.security.Key;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.crypto.AlgorithmMethod;
@@ -48,7 +49,7 @@ public class KeyInfoKeySelector extends 
 
     private static final POILogger LOG = 
POILogFactory.getLogger(KeyInfoKeySelector.class);
 
-    private X509Certificate certificate;
+    private List<X509Certificate> certChain = new ArrayList<X509Certificate>();
 
     @SuppressWarnings("unchecked")
     @Override
@@ -58,35 +59,31 @@ public class KeyInfoKeySelector extends 
             throw new KeySelectorException("no ds:KeyInfo present");
         }
         List<XMLStructure> keyInfoContent = keyInfo.getContent();
-        this.certificate = null;
+        certChain.clear();
         for (XMLStructure keyInfoStructure : keyInfoContent) {
-            if (false == (keyInfoStructure instanceof X509Data)) {
+            if (!(keyInfoStructure instanceof X509Data)) {
                 continue;
             }
             X509Data x509Data = (X509Data) keyInfoStructure;
             List<Object> x509DataList = x509Data.getContent();
             for (Object x509DataObject : x509DataList) {
-                if (false == (x509DataObject instanceof X509Certificate)) {
+                if (!(x509DataObject instanceof X509Certificate)) {
                     continue;
                 }
                 X509Certificate certificate = (X509Certificate) x509DataObject;
                 LOG.log(POILogger.DEBUG, "certificate", 
certificate.getSubjectX500Principal());
-                if (null == this.certificate) {
-                    /*
-                     * The first certificate is presumably the signer.
-                     */
-                    this.certificate = certificate;
-                }
-            }
-            if (null != this.certificate) {
-                return this;
+                certChain.add(certificate);
             }
         }
-        throw new KeySelectorException("No key found!");
+        if (certChain.isEmpty()) {
+            throw new KeySelectorException("No key found!");
+        }
+        return this;
     }
 
     public Key getKey() {
-        return this.certificate.getPublicKey();
+        // The first certificate is presumably the signer.
+        return certChain.isEmpty() ? null : certChain.get(0).getPublicKey();
     }
 
     /**
@@ -95,7 +92,12 @@ public class KeyInfoKeySelector extends 
      * 
      * @return
      */
-    public X509Certificate getCertificate() {
-        return this.certificate;
+    public X509Certificate getSigner() {
+        // The first certificate is presumably the signer.
+        return certChain.isEmpty() ? null : certChain.get(0);
+    }
+    
+    public List<X509Certificate> getCertChain() {
+        return certChain;
     }
 }

Modified: 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java
URL: 
http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java?rev=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java
 (original)
+++ 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java
 Sun Sep 28 22:30:02 2014
@@ -31,6 +31,7 @@ import java.util.UUID;
 
 import javax.xml.crypto.URIDereferencer;
 import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.DigestMethod;
 
 import org.apache.poi.EncryptedDocumentException;
 import org.apache.poi.openxml4j.opc.OPCPackage;
@@ -87,7 +88,10 @@ public class SignatureConfig {
     // timestamp service provider URL
     private String tspUrl;
     private boolean tspOldProtocol = false;
-    private HashAlgorithm tspDigestAlgo = HashAlgorithm.sha1;
+    /**
+     * if not defined, it's the same as the main digest
+     */
+    private HashAlgorithm tspDigestAlgo = null;
     private String tspUser;
     private String tspPass;
     private TimeStampServiceValidator tspValidator;
@@ -103,7 +107,10 @@ public class SignatureConfig {
      * When <code>null</code> the signature will be limited to XAdES-T only.
      */
     private RevocationDataService revocationDataService;
-    private HashAlgorithm xadesDigestAlgo = HashAlgorithm.sha1;
+    /**
+     * if not defined, it's the same as the main digest
+     */
+    private HashAlgorithm xadesDigestAlgo = null;
     private String xadesRole = null;
     private String xadesSignatureId = null;
     private boolean xadesSignaturePolicyImplied = true;
@@ -290,9 +297,7 @@ public class SignatureConfig {
         return packageSignatureId;
     }
     public void setPackageSignatureId(String packageSignatureId) {
-        this.packageSignatureId = (packageSignatureId != null)
-            ? packageSignatureId
-            : "xmldsig-" + UUID.randomUUID();
+        this.packageSignatureId = 
nvl(packageSignatureId,"xmldsig-"+UUID.randomUUID());
     }
     public String getTspUrl() {
         return tspUrl;
@@ -307,7 +312,7 @@ public class SignatureConfig {
         this.tspOldProtocol = tspOldProtocol;
     }
     public HashAlgorithm getTspDigestAlgo() {
-        return tspDigestAlgo;
+        return nvl(tspDigestAlgo,digestAlgo);
     }
     public void setTspDigestAlgo(HashAlgorithm tspDigestAlgo) {
         this.tspDigestAlgo = tspDigestAlgo;
@@ -349,7 +354,7 @@ public class SignatureConfig {
         this.revocationDataService = revocationDataService;
     }
     public HashAlgorithm getXadesDigestAlgo() {
-        return xadesDigestAlgo;
+        return nvl(xadesDigestAlgo,digestAlgo);
     }
     public void setXadesDigestAlgo(HashAlgorithm xadesDigestAlgo) {
         this.xadesDigestAlgo = xadesDigestAlgo;
@@ -420,4 +425,81 @@ public class SignatureConfig {
     public void setNamespacePrefixes(Map<String, String> namespacePrefixes) {
         this.namespacePrefixes = namespacePrefixes;
     }
+    protected static <T> T nvl(T value, T defaultValue)  {
+        return value == null ? defaultValue : value;
+    }
+    public byte[] getHashMagic() {
+        // see https://www.ietf.org/rfc/rfc3110.txt
+        // RSA/SHA1 SIG Resource Records
+        byte result[];
+        switch (getDigestAlgo()) {
+        case sha1: result = new byte[]
+            { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e
+            , 0x03, 0x02, 0x1a, 0x04, 0x14 };
+            break;
+        case sha224: result = new byte[] 
+            { 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
+            , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x04, 0x1c };
+            break;
+        case sha256: result = new byte[]
+            { 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
+            , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20 };
+            break;
+        case sha384: result = new byte[]
+            { 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
+            , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30 };
+            break;
+        case sha512: result  = new byte[]
+            { 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
+            , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40 };
+            break;
+        case ripemd128: result = new byte[]
+            { 0x30, 0x1b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24
+            , 0x03, 0x02, 0x02, 0x04, 0x10 };
+            break;
+        case ripemd160: result = new byte[]
+            { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24
+            , 0x03, 0x02, 0x01, 0x04, 0x14 };
+            break;
+        // case ripemd256: result = new byte[]
+        //    { 0x30, 0x2b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24
+        //    , 0x03, 0x02, 0x03, 0x04, 0x20 };
+        //    break;
+        default: throw new EncryptedDocumentException("Hash algorithm "
+            +getDigestAlgo()+" not supported for signing.");
+        }
+        
+        return result;
+    }
+
+    public String getSignatureMethod() {
+        switch (getDigestAlgo()) {
+        case sha1:   return 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+        case sha224: return 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224;
+        case sha256: return 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
+        case sha384: return 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;
+        case sha512: return 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;
+        case ripemd160: return 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_RIPEMD160;
+        default: throw new EncryptedDocumentException("Hash algorithm "
+            +getDigestAlgo()+" not supported for signing.");
+        }
+    }
+    
+    public String getDigestMethodUri() {
+        return getDigestMethodUri(getDigestAlgo());
+    }
+    
+    public static String getDigestMethodUri(HashAlgorithm digestAlgo) {
+        switch (digestAlgo) {
+        case sha1:   return DigestMethod.SHA1;
+        case sha224: return "http://www.w3.org/2001/04/xmldsig-more#sha224";;
+        case sha256: return DigestMethod.SHA256;
+        case sha384: return "http://www.w3.org/2001/04/xmldsig-more#sha384";;
+        case sha512: return DigestMethod.SHA512;
+        case ripemd160: return DigestMethod.RIPEMD160;
+        default: throw new EncryptedDocumentException("Hash algorithm "
+            +digestAlgo+" not supported for signing.");
+        }
+    }
+    
 }

Modified: 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java
URL: 
http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java?rev=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java
 (original)
+++ 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java
 Sun Sep 28 22:30:02 2014
@@ -25,11 +25,6 @@
 package org.apache.poi.poifs.crypt.dsig;
 
 import static 
org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_DIGSIG_NS;
-import static 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;
-import static 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
-import static 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;
-import static 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;
-import static 
org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -113,36 +108,6 @@ import org.xml.sax.SAXException;
 
 public class SignatureInfo implements SignatureConfigurable {
 
-    // see https://www.ietf.org/rfc/rfc3110.txt
-    // RSA/SHA1 SIG Resource Records
-    public static final byte[] SHA1_DIGEST_INFO_PREFIX = new byte[]
-        { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 
0x04, 0x14 };
-
-    public static final byte[] SHA224_DIGEST_INFO_PREFIX = new byte[] 
-        { 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
-        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x04, 0x1c };
-
-    public static final byte[] SHA256_DIGEST_INFO_PREFIX = new byte[]
-        { 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
-        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20 };
-
-    public static final byte[] SHA384_DIGEST_INFO_PREFIX = new byte[]
-        { 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
-        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30 };
-
-    public static final byte[] SHA512_DIGEST_INFO_PREFIX = new byte[]
-        { 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86
-        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40 };
-
-    public static final byte[] RIPEMD128_DIGEST_INFO_PREFIX = new byte[]
-        { 0x30, 0x1b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x02, 
0x04, 0x10 };
-
-    public static final byte[] RIPEMD160_DIGEST_INFO_PREFIX = new byte[]
-        { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 
0x04, 0x14 };
-
-    public static final byte[] RIPEMD256_DIGEST_INFO_PREFIX = new byte[]
-        { 0x30, 0x2b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x03, 
0x04, 0x20 };
-
     private static final POILogger LOG = 
POILogFactory.getLogger(SignatureInfo.class);
     private static boolean isInitialized = false;
     
@@ -151,6 +116,7 @@ public class SignatureInfo implements Si
     public class SignaturePart {
         private final PackagePart signaturePart;
         private X509Certificate signer;
+        private List<X509Certificate> certChain;
         
         private SignaturePart(PackagePart signaturePart) {
             this.signaturePart = signaturePart;
@@ -164,6 +130,10 @@ public class SignatureInfo implements Si
             return signer;
         }
         
+        public List<X509Certificate> getCertChain() {
+            return certChain;
+        }
+        
         public SignatureDocument getSignatureDocument() throws IOException, 
XmlException {
             // TODO: check for XXE
             return 
SignatureDocument.Factory.parse(signaturePart.getInputStream());
@@ -188,7 +158,8 @@ public class SignatureInfo implements Si
                 boolean valid = xmlSignature.validate(domValidateContext);
 
                 if (valid) {
-                    signer = keySelector.getCertificate();
+                    signer = keySelector.getSigner();
+                    certChain = keySelector.getCertChain();
                 }
                 
                 return valid;
@@ -240,7 +211,7 @@ public class SignatureInfo implements Si
             
         try {
             ByteArrayOutputStream digestInfoValueBuf = new 
ByteArrayOutputStream();
-            digestInfoValueBuf.write(getHashMagic());
+            digestInfoValueBuf.write(signatureConfig.getHashMagic());
             digestInfoValueBuf.write(digest);
             byte[] digestInfoValue = digestInfoValueBuf.toByteArray();
             byte[] signatureValue = cipher.doFinal(digestInfoValue);
@@ -324,31 +295,6 @@ public class SignatureInfo implements Si
         throw new RuntimeException("JRE doesn't support default xml signature 
provider - set jsr105Provider system property!");
     }
     
-    protected byte[] getHashMagic() {
-        switch (signatureConfig.getDigestAlgo()) {
-        case sha1: return SHA1_DIGEST_INFO_PREFIX;
-        // sha224: return SHA224_DIGEST_INFO_PREFIX;
-        case sha256: return SHA256_DIGEST_INFO_PREFIX;
-        case sha384: return SHA384_DIGEST_INFO_PREFIX;
-        case sha512: return SHA512_DIGEST_INFO_PREFIX;
-        case ripemd128: return RIPEMD128_DIGEST_INFO_PREFIX;
-        case ripemd160: return RIPEMD160_DIGEST_INFO_PREFIX;
-        // case ripemd256: return RIPEMD256_DIGEST_INFO_PREFIX;
-        default: throw new EncryptedDocumentException("Hash algorithm 
"+signatureConfig.getDigestAlgo()+" not supported for signing.");
-        }
-    }
-
-    protected String getSignatureMethod() {
-        switch (signatureConfig.getDigestAlgo()) {
-        case sha1:   return ALGO_ID_SIGNATURE_RSA_SHA1;
-        case sha256: return ALGO_ID_SIGNATURE_RSA_SHA256;
-        case sha384: return ALGO_ID_SIGNATURE_RSA_SHA384;
-        case sha512: return ALGO_ID_SIGNATURE_RSA_SHA512;
-        case ripemd160: return ALGO_ID_MAC_HMAC_RIPEMD160;
-        default: throw new EncryptedDocumentException("Hash algorithm 
"+signatureConfig.getDigestAlgo()+" not supported for signing.");
-        }
-    }
-    
     protected static synchronized void initXmlProvider() {
         if (isInitialized) return;
         isInitialized = true;
@@ -409,8 +355,8 @@ public class SignatureInfo implements Si
         for (DigestInfo digestInfo : safe(digestInfos)) {
             byte[] documentDigestValue = digestInfo.digestValue;
 
-            DigestMethod digestMethod = signatureFactory.newDigestMethod(
-                            digestInfo.hashAlgo.xmlSignUri, null);
+            DigestMethod digestMethod = signatureFactory.newDigestMethod
+                (signatureConfig.getDigestMethodUri(), null);
 
             String uri = new File(digestInfo.description).getName();
 
@@ -431,7 +377,8 @@ public class SignatureInfo implements Si
         /*
          * ds:SignedInfo
          */
-        SignatureMethod signatureMethod = 
signatureFactory.newSignatureMethod(getSignatureMethod(), null);
+        SignatureMethod signatureMethod = signatureFactory.newSignatureMethod
+            (signatureConfig.getSignatureMethod(), null);
         CanonicalizationMethod canonicalizationMethod = signatureFactory
             
.newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),
             (C14NMethodParameterSpec) null);

Modified: 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java
URL: 
http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java?rev=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java
 (original)
+++ 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java
 Sun Sep 28 22:30:02 2014
@@ -42,16 +42,15 @@ public class EnvelopedSignatureFacet imp
         , List<Reference> references
         , List<XMLObject> objects)
     throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
-        DigestMethod digestMethod = 
signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, 
null);
+        DigestMethod digestMethod = signatureFactory.newDigestMethod
+            (signatureConfig.getDigestMethodUri(), null);
 
         List<Transform> transforms = new ArrayList<Transform>();
-        Transform envelopedTransform = signatureFactory
-                .newTransform(CanonicalizationMethod.ENVELOPED,
-                        (TransformParameterSpec) null);
+        Transform envelopedTransform = signatureFactory.newTransform
+            (CanonicalizationMethod.ENVELOPED, (TransformParameterSpec) null);
         transforms.add(envelopedTransform);
-        Transform exclusiveTransform = signatureFactory
-                .newTransform(CanonicalizationMethod.EXCLUSIVE,
-                        (TransformParameterSpec) null);
+        Transform exclusiveTransform = signatureFactory.newTransform
+            (CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null);
         transforms.add(exclusiveTransform);
 
         Reference reference = signatureFactory.newReference("", digestMethod,

Modified: 
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=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
 (original)
+++ 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
 Sun Sep 28 22:30:02 2014
@@ -123,7 +123,8 @@ public class OOXMLSignatureFacet impleme
         XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, 
null, null);
         objects.add(xo);
 
-        DigestMethod digestMethod = 
signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, 
null);
+        DigestMethod digestMethod = signatureFactory.newDigestMethod
+            (signatureConfig.getDigestMethodUri(), null);
         Reference reference = signatureFactory.newReference
             ("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null);
         references.add(reference);
@@ -136,7 +137,8 @@ public class OOXMLSignatureFacet impleme
         OPCPackage ooxml = signatureConfig.getOpcPackage();
         List<PackagePart> relsEntryNames = 
ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);
 
-        DigestMethod digestMethod = 
signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, 
null);
+        DigestMethod digestMethod = signatureFactory.newDigestMethod
+            (signatureConfig.getDigestMethodUri(), null);
         Set<String> digestedPartNames = new HashSet<String>();
         for (PackagePart pp : relsEntryNames) {
             String baseUri = 
pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1");
@@ -252,7 +254,7 @@ public class OOXMLSignatureFacet impleme
 
         SignatureInfoV1Document sigV1 = 
SignatureInfoV1Document.Factory.newInstance();
         CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1();
-        
ctSigV1.setManifestHashAlgorithm(signatureConfig.getDigestAlgo().xmlSignUri);
+        ctSigV1.setManifestHashAlgorithm(signatureConfig.getDigestMethodUri());
         Element n = (Element)document.importNode(ctSigV1.getDomNode(), true);
         n.setAttributeNS(XML_NS, XMLConstants.XMLNS_ATTRIBUTE, MS_DIGSIG_NS);
         
@@ -271,7 +273,8 @@ public class OOXMLSignatureFacet impleme
         String objectId = "idOfficeObject";
         objects.add(signatureFactory.newXMLObject(objectContent, objectId, 
null, null));
 
-        DigestMethod digestMethod = 
signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, 
null);
+        DigestMethod digestMethod = signatureFactory.newDigestMethod
+            (signatureConfig.getDigestMethodUri(), null);
         Reference reference = signatureFactory.newReference
             ("#" + objectId, digestMethod, null, XML_DIGSIG_NS+"Object", null);
         references.add(reference);

Modified: 
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=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
 (original)
+++ 
poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
 Sun Sep 28 22:30:02 2014
@@ -213,7 +213,7 @@ public class XAdESSignatureFacet impleme
         objects.add(xadesObject);
 
         // add XAdES ds:Reference
-        DigestMethod digestMethod = 
signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, 
null);
+        DigestMethod digestMethod = 
signatureFactory.newDigestMethod(signatureConfig.getDigestMethodUri(), null);
         List<Transform> transforms = new ArrayList<Transform>();
         Transform exclusiveTransform = signatureFactory
                 .newTransform(CanonicalizationMethod.INCLUSIVE,
@@ -236,11 +236,11 @@ public class XAdESSignatureFacet impleme
     protected static void setDigestAlgAndValue(
             DigestAlgAndValueType digestAlgAndValue,
             byte[] data,
-            HashAlgorithm hashAlgo) {
+            HashAlgorithm digestAlgo) {
         DigestMethodType digestMethod = digestAlgAndValue.addNewDigestMethod();
-        digestMethod.setAlgorithm(hashAlgo.xmlSignUri);
+        
digestMethod.setAlgorithm(SignatureConfig.getDigestMethodUri(digestAlgo));
         
-        MessageDigest messageDigest = 
CryptoFunctions.getMessageDigest(hashAlgo);
+        MessageDigest messageDigest = 
CryptoFunctions.getMessageDigest(digestAlgo);
         byte[] digestValue = messageDigest.digest(data);
         digestAlgAndValue.setDigestValue(digestValue);
     }

Modified: 
poi/branches/xml_signature/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java
URL: 
http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java?rev=1628107&r1=1628106&r2=1628107&view=diff
==============================================================================
--- 
poi/branches/xml_signature/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java
 (original)
+++ 
poi/branches/xml_signature/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java
 Sun Sep 28 22:30:02 2014
@@ -24,6 +24,7 @@
 package org.apache.poi.poifs.crypt;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -31,6 +32,8 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -68,6 +71,7 @@ import org.apache.poi.util.DocumentHelpe
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.apache.xmlbeans.XmlObject;
 import org.bouncycastle.asn1.x509.KeyUsage;
 import org.bouncycastle.cert.ocsp.OCSPResp;
@@ -208,6 +212,35 @@ public class TestSignatureInfo {
     }
 
     @Test
+    public void testManipulation() throws Exception {
+        // sign & validate
+        String testFile = "hello-world-unsigned.xlsx";
+        OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), 
PackageAccess.READ_WRITE);
+        sign(pkg, "Test", "CN=Test", 1);
+        
+        // manipulate
+        XSSFWorkbook wb = new XSSFWorkbook(pkg);
+        wb.setSheetName(0, "manipulated");
+        // ... I don't know, why commit is protected ...
+        Method m = XSSFWorkbook.class.getDeclaredMethod("commit");
+        m.setAccessible(true);
+        m.invoke(wb);
+
+        // todo: test a manipulation on a package part, which is not signed
+        // ... maybe in combination with #56164 
+        
+        // validate
+        SignatureConfig sic = new SignatureConfig();
+        sic.setOpcPackage(pkg);
+        SignatureInfo si = new SignatureInfo();
+        si.setSignatureConfig(sic);
+        boolean b = si.verifySignature();
+        assertFalse("signature should be broken", b);
+        
+        wb.close();
+    }
+    
+    @Test
     public void testSignSpreadsheetWithSignatureInfo() throws Exception {
         initKeyPair("Test", "CN=Test");
         String testFile = "hello-world-unsigned.xlsx";
@@ -321,7 +354,7 @@ public class TestSignatureInfo {
             "$this/ds:Signature/ds:SignedInfo/ds:Reference";
         for (ReferenceType rt : 
(ReferenceType[])sigDoc.selectPath(digestValXQuery)) {
             assertNotNull(rt.getDigestValue());
-            assertEquals(HashAlgorithm.sha1.xmlSignUri, 
rt.getDigestMethod().getAlgorithm());
+            assertEquals(signatureConfig.getDigestMethodUri(), 
rt.getDigestMethod().getAlgorithm());
         }
 
         String certDigestXQuery = declareNS +
@@ -341,8 +374,83 @@ public class TestSignatureInfo {
 
         pkg.close();
     }
+
+    @Test
+    public void testCertChain() throws Exception {
+        KeyStore keystore = KeyStore.getInstance("PKCS12");
+        String password = "test";
+        InputStream is = testdata.openResourceAsStream("chaintest.pfx");
+        keystore.load(is, password.toCharArray());
+        is.close();
+
+        Key key = keystore.getKey("poitest", password.toCharArray());
+        Certificate chainList[] = keystore.getCertificateChain("poitest");
+        List<X509Certificate> certChain = new ArrayList<X509Certificate>();
+        for (Certificate c : chainList) {
+            certChain.add((X509Certificate)c);
+        }
+        x509 = certChain.get(0);
+        keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);
+        
+        String testFile = "hello-world-unsigned.xlsx";
+        OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), 
PackageAccess.READ_WRITE);
+
+        SignatureConfig signatureConfig = new SignatureConfig();
+        signatureConfig.setKey(keyPair.getPrivate());
+        signatureConfig.setSigningCertificateChain(certChain);
+        Calendar cal = Calendar.getInstance();
+        cal.set(2007, 7, 1);
+        signatureConfig.setExecutionTime(cal.getTime());
+        signatureConfig.setDigestAlgo(HashAlgorithm.sha1);
+        signatureConfig.setOpcPackage(pkg);
+        
+        SignatureInfo si = new SignatureInfo();
+        si.setSignatureConfig(signatureConfig);
+
+        si.confirmSignature();
+        
+        for (SignaturePart sp : si.getSignatureParts()){
+            boolean b = sp.validate();
+            assertTrue(b);
+            X509Certificate signer = sp.getSigner();
+            assertNotNull("signer undefined?!", signer);
+            List<X509Certificate> certChainRes = sp.getCertChain();
+            assertEquals(3, certChainRes.size());
+        }
+        
+        pkg.close();
+    }
+
+    @Test
+    public void testNonSha1() throws Exception {
+        String testFile = "hello-world-unsigned.xlsx";
+        initKeyPair("Test", "CN=Test");
+
+        SignatureConfig signatureConfig = new SignatureConfig();
+        signatureConfig.setKey(keyPair.getPrivate());
+        
signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));
+
+        HashAlgorithm testAlgo[] = { HashAlgorithm.sha224, HashAlgorithm.sha256
+            , HashAlgorithm.sha384, HashAlgorithm.sha512, 
HashAlgorithm.ripemd160 }; 
+        
+        for (HashAlgorithm ha : testAlgo) {
+            signatureConfig.setDigestAlgo(ha);
+            OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), 
PackageAccess.READ_WRITE);
+            signatureConfig.setOpcPackage(pkg);
+            
+            SignatureInfo si = new SignatureInfo();
+            si.setSignatureConfig(signatureConfig);
+    
+            si.confirmSignature();
+            boolean b = si.verifySignature();
+            pkg.close();
     
-    private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, 
int signerCount) throws Exception {
+            assertTrue(b);
+        }
+    }
+    
+    
+    private void sign(OPCPackage pkgCopy, String alias, String signerDn, int 
signerCount) throws Exception {
         initKeyPair(alias, signerDn);
 
         SignatureConfig signatureConfig = new SignatureConfig();
@@ -383,8 +491,6 @@ public class TestSignatureInfo {
             }
         }
         assertEquals(signerCount, result.size());
-
-        return pkgCopy;
     }
 
     private void initKeyPair(String alias, String subjectDN) throws Exception {

Added: poi/branches/xml_signature/test-data/xmldsign/chaintest.pfx
URL: 
http://svn.apache.org/viewvc/poi/branches/xml_signature/test-data/xmldsign/chaintest.pfx?rev=1628107&view=auto
==============================================================================
Binary file - no diff available.

Propchange: poi/branches/xml_signature/test-data/xmldsign/chaintest.pfx
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to