migrated enveloped document test (1 of 2)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1618288 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
777fd47d71
commit
1b2f321ae9
12
build.xml
12
build.xml
@ -145,6 +145,10 @@ under the License.
|
|||||||
<property name="main.ant.url" value="${repository.m2}/maven2/org/apache/ant/ant/1.9.4/ant-1.9.4.jar"/>
|
<property name="main.ant.url" value="${repository.m2}/maven2/org/apache/ant/ant/1.9.4/ant-1.9.4.jar"/>
|
||||||
<property name="main.antlauncher.jar" location="${main.lib}/ant-launcher-1.9.4.jar"/>
|
<property name="main.antlauncher.jar" location="${main.lib}/ant-launcher-1.9.4.jar"/>
|
||||||
<property name="main.antlauncher.url" value="${repository.m2}/maven2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.jar"/>
|
<property name="main.antlauncher.url" value="${repository.m2}/maven2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.jar"/>
|
||||||
|
<property name="main.mockito.jar" location="${main.lib}/mockito-core-1.9.5.jar"/>
|
||||||
|
<property name="main.mockito.url" value="${repository.m2}/maven2/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5.jar"/>
|
||||||
|
<property name="main.objenesis.jar" location="${main.lib}/com.springsource.org.objenesis-1.0.0.jar"/>
|
||||||
|
<property name="main.objenesis.url" value="http://repository.springsource.com/ivy/bundles/external/org.objenesis/com.springsource.org.objenesis/1.0.0/com.springsource.org.objenesis-1.0.0.jar"/>
|
||||||
|
|
||||||
<!-- jars in the lib-ooxml directory, see the fetch-ooxml-jars target-->
|
<!-- jars in the lib-ooxml directory, see the fetch-ooxml-jars target-->
|
||||||
<property name="ooxml.xmlbeans23.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/>
|
<property name="ooxml.xmlbeans23.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/>
|
||||||
@ -431,6 +435,14 @@ under the License.
|
|||||||
<param name="sourcefile" value="${rat.url}"/>
|
<param name="sourcefile" value="${rat.url}"/>
|
||||||
<param name="destfile" value="${rat.jar}"/>
|
<param name="destfile" value="${rat.jar}"/>
|
||||||
</antcall>
|
</antcall>
|
||||||
|
<antcall target="downloadfile">
|
||||||
|
<param name="sourcefile" value="${main.mockito.url}"/>
|
||||||
|
<param name="destfile" value="${main.mockito.jar}"/>
|
||||||
|
</antcall>
|
||||||
|
<antcall target="downloadfile">
|
||||||
|
<param name="sourcefile" value="${main.objenesis.url}"/>
|
||||||
|
<param name="destfile" value="${main.objenesis.jar}"/>
|
||||||
|
</antcall>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="check-ooxml-jars">
|
<target name="check-ooxml-jars">
|
||||||
|
@ -126,26 +126,28 @@ public class SignatureInfo {
|
|||||||
DigestInfo digestInfo = signatureService.preSign(null, x509Chain, null, null, null);
|
DigestInfo digestInfo = signatureService.preSign(null, x509Chain, null, null, null);
|
||||||
|
|
||||||
// setup: key material, signature value
|
// setup: key material, signature value
|
||||||
|
byte[] signatureValue = signDigest(key, hashAlgo, digestInfo.digestValue);
|
||||||
Cipher cipher = CryptoFunctions.getCipher(key, CipherAlgorithm.rsa
|
|
||||||
, ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");
|
|
||||||
|
|
||||||
byte[] signatureValue;
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();
|
|
||||||
digestInfoValueBuf.write(getHashMagic(hashAlgo));
|
|
||||||
digestInfoValueBuf.write(digestInfo.digestValue);
|
|
||||||
byte[] digestInfoValue = digestInfoValueBuf.toByteArray();
|
|
||||||
signatureValue = cipher.doFinal(digestInfoValue);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new EncryptedDocumentException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// operate: postSign
|
// operate: postSign
|
||||||
signatureService.postSign(signatureValue, Collections.singletonList(x509));
|
signatureService.postSign(signatureValue, Collections.singletonList(x509));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] signDigest(Key key, HashAlgorithm hashAlgo, byte digest[]) {
|
||||||
|
Cipher cipher = CryptoFunctions.getCipher(key, CipherAlgorithm.rsa
|
||||||
|
, ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();
|
||||||
|
digestInfoValueBuf.write(getHashMagic(hashAlgo));
|
||||||
|
digestInfoValueBuf.write(digest);
|
||||||
|
byte[] digestInfoValue = digestInfoValueBuf.toByteArray();
|
||||||
|
byte[] signatureValue = cipher.doFinal(digestInfoValue);
|
||||||
|
return signatureValue;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new EncryptedDocumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public XmlSignatureService createSignatureService(HashAlgorithm hashAlgo, OPCPackage pkg) {
|
public XmlSignatureService createSignatureService(HashAlgorithm hashAlgo, OPCPackage pkg) {
|
||||||
XmlSignatureService signatureService = new XmlSignatureService(hashAlgo, pkg);
|
XmlSignatureService signatureService = new XmlSignatureService(hashAlgo, pkg);
|
||||||
signatureService.initFacets(new Date());
|
signatureService.initFacets(new Date());
|
||||||
|
@ -49,8 +49,6 @@ import javax.xml.crypto.dsig.XMLSignatureFactory;
|
|||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf;
|
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf;
|
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicOCSPRespIf;
|
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicOCSPRespIf;
|
||||||
@ -62,6 +60,8 @@ import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf;
|
|||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.RespIDIf;
|
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.RespIDIf;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ResponderIDIf;
|
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ResponderIDIf;
|
||||||
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509NameIf;
|
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509NameIf;
|
||||||
|
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
|
||||||
|
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
|
import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
|
||||||
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
|
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
|
||||||
@ -373,25 +373,22 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] getC14nValue(List<Node> nodeList, String c14nAlgoId) {
|
public static byte[] getC14nValue(List<Node> nodeList, String c14nAlgoId) {
|
||||||
byte[] c14nValue = null;
|
ByteArrayOutputStream c14nValue = new ByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
for (Node node : nodeList) {
|
for (Node node : nodeList) {
|
||||||
/*
|
/*
|
||||||
* Re-initialize the c14n else the namespaces will get cached
|
* Re-initialize the c14n else the namespaces will get cached
|
||||||
* and will be missing from the c14n resulting nodes.
|
* and will be missing from the c14n resulting nodes.
|
||||||
*/
|
*/
|
||||||
CanonicalizerIf c14n = HorribleProxy.createProxy(CanonicalizerIf.class, "newInstance", c14nAlgoId);
|
CanonicalizerIf c14n = HorribleProxy.createProxy(CanonicalizerIf.class, "getInstance", c14nAlgoId);
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
c14nValue.write(c14n.canonicalizeSubtree(node));
|
||||||
bos.write(c14nValue);
|
|
||||||
bos.write(c14n.canonicalizeSubtree(node));
|
|
||||||
c14nValue = bos.toByteArray();
|
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("c14n error: " + e.getMessage(), e);
|
throw new RuntimeException("c14n error: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
return c14nValue;
|
return c14nValue.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preSign(XMLSignatureFactory signatureFactory,
|
public void preSign(XMLSignatureFactory signatureFactory,
|
||||||
|
@ -112,7 +112,7 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
protected final List<SignatureFacet> signatureFacets;
|
protected final List<SignatureFacet> signatureFacets;
|
||||||
|
|
||||||
private String signatureNamespacePrefix;
|
private String signatureNamespacePrefix;
|
||||||
private String signatureId;
|
private String signatureId = "idPackageSignature";
|
||||||
private final HashAlgorithm hashAlgo;
|
private final HashAlgorithm hashAlgo;
|
||||||
private final OPCPackage opcPackage;
|
private final OPCPackage opcPackage;
|
||||||
private SignatureDocument sigDoc;
|
private SignatureDocument sigDoc;
|
||||||
@ -124,7 +124,6 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {
|
public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {
|
||||||
this.signatureFacets = new LinkedList<SignatureFacet>();
|
this.signatureFacets = new LinkedList<SignatureFacet>();
|
||||||
this.signatureNamespacePrefix = null;
|
this.signatureNamespacePrefix = null;
|
||||||
this.signatureId = null;
|
|
||||||
this.hashAlgo = digestAlgo;
|
this.hashAlgo = digestAlgo;
|
||||||
this.opcPackage = opcPackage;
|
this.opcPackage = opcPackage;
|
||||||
this.sigDoc = null;
|
this.sigDoc = null;
|
||||||
@ -142,7 +141,6 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
* Work-around for Office 2010.
|
* Work-around for Office 2010.
|
||||||
*/
|
*/
|
||||||
this.xadesSignatureFacet.setIssuerNameNoReverseOrder(true);
|
this.xadesSignatureFacet.setIssuerNameNoReverseOrder(true);
|
||||||
setSignatureId("idPackageSignature");
|
|
||||||
addSignatureFacet(this.xadesSignatureFacet);
|
addSignatureFacet(this.xadesSignatureFacet);
|
||||||
addSignatureFacet(new Office2010SignatureFacet());
|
addSignatureFacet(new Office2010SignatureFacet());
|
||||||
}
|
}
|
||||||
@ -398,8 +396,9 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
|
|
||||||
registerIds(doc);
|
registerIds(doc);
|
||||||
Element el = doc.getElementById("idPackageObject");
|
Element el = doc.getElementById("idPackageObject");
|
||||||
assert (el != null);
|
if (el != null) {
|
||||||
el.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
|
el.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -550,6 +549,10 @@ public class XmlSignatureService implements SignatureService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SignatureDocument getSignatureDocument() {
|
||||||
|
return sigDoc;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getCanonicalizationMethod() {
|
protected String getCanonicalizationMethod() {
|
||||||
return CanonicalizationMethod.INCLUSIVE;
|
return CanonicalizationMethod.INCLUSIVE;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -54,6 +56,10 @@ import java.util.List;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
import javax.xml.crypto.KeySelector;
|
||||||
|
import javax.xml.crypto.dsig.XMLSignature;
|
||||||
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||||
|
import javax.xml.crypto.dsig.dom.DOMValidateContext;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
@ -75,10 +81,14 @@ import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
|
|||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
import org.apache.xmlbeans.XmlObject;
|
||||||
|
import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
|
||||||
|
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
import org.w3.x2000.x09.xmldsig.SignatureDocument;
|
||||||
|
|
||||||
public class TestSignatureInfo {
|
public class TestSignatureInfo {
|
||||||
private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);
|
private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);
|
||||||
@ -244,8 +254,52 @@ public class TestSignatureInfo {
|
|||||||
|
|
||||||
// verify
|
// verify
|
||||||
assertNotNull(digestInfo);
|
assertNotNull(digestInfo);
|
||||||
assertEquals("SHA-1", digestInfo.hashAlgo);
|
assertEquals(HashAlgorithm.sha1, digestInfo.hashAlgo);
|
||||||
assertNotNull(digestInfo.digestValue);
|
assertNotNull(digestInfo.digestValue);
|
||||||
|
|
||||||
|
SignatureDocument sigDoc = testedInstance.getSignatureDocument();
|
||||||
|
String certDigestXQuery =
|
||||||
|
"declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; "
|
||||||
|
+ "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "
|
||||||
|
+ "$this/ds:Signature/ds:Object/xades:QualifyingProperties/xades:SignedProperties/xades:SignedSignatureProperties/xades:SigningCertificate/xades:Cert/xades:CertDigest";
|
||||||
|
XmlObject xoList[] = sigDoc.selectPath(certDigestXQuery);
|
||||||
|
assertEquals(xoList.length, 1);
|
||||||
|
DigestAlgAndValueType certDigest = (DigestAlgAndValueType)xoList[0];
|
||||||
|
assertNotNull(certDigest.getDigestValue());
|
||||||
|
|
||||||
|
// Sign the received XML signature digest value.
|
||||||
|
byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);
|
||||||
|
|
||||||
|
// Operate: postSign
|
||||||
|
testedInstance.postSign(signatureValue, certificateChain);
|
||||||
|
|
||||||
|
// verify
|
||||||
|
verify(mockTimeStampService, times(2)).timeStamp(any(byte[].class), any(RevocationData.class));
|
||||||
|
verify(mockRevocationDataService).getRevocationData(certificateChain);
|
||||||
|
|
||||||
|
DOMValidateContext domValidateContext = new DOMValidateContext(
|
||||||
|
KeySelector.singletonKeySelector(keyPair.getPublic()),
|
||||||
|
testedInstance.getSignatureDocument().getDomNode());
|
||||||
|
XMLSignatureFactory xmlSignatureFactory = SignatureInfo.getSignatureFactory();
|
||||||
|
XMLSignature xmlSignature = xmlSignatureFactory
|
||||||
|
.unmarshalXMLSignature(domValidateContext);
|
||||||
|
boolean validity = xmlSignature.validate(domValidateContext);
|
||||||
|
assertTrue(validity);
|
||||||
|
|
||||||
|
xoList = sigDoc.selectPath(certDigestXQuery);
|
||||||
|
assertEquals(xoList.length, 1);
|
||||||
|
certDigest = (DigestAlgAndValueType)xoList[0];
|
||||||
|
assertNotNull(certDigest.getDigestValue());
|
||||||
|
|
||||||
|
String qualPropXQuery =
|
||||||
|
"declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; "
|
||||||
|
+ "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "
|
||||||
|
+ "$this/ds:Signature/ds:Object/xades:QualifyingProperties";
|
||||||
|
xoList = sigDoc.selectPath(qualPropXQuery);
|
||||||
|
assertEquals(xoList.length, 1);
|
||||||
|
QualifyingPropertiesType qualProp = (QualifyingPropertiesType)xoList[0];
|
||||||
|
boolean qualPropXsdOk = qualProp.validate();
|
||||||
|
assertTrue(qualPropXsdOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {
|
private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {
|
||||||
|
Loading…
Reference in New Issue
Block a user