Browse Source

removed HorribleProxy

added current version of BouncyCastle and xmlsec (using xmlsec instead of jdk internal classes, because of interoperabiltiy with e.g. IBM JDK)
heaps of changes because of above

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1620229 13f79535-47bb-0310-9956-ffa450edef68
pull/11/head
Andreas Beeker 9 years ago
parent
commit
d0cc2e4267

+ 4
- 0
.classpath View File

@@ -25,5 +25,9 @@
<classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-src-1.1.jar"/>
<classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.2.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.2.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="compile-lib/slf4j-api-1.7.7.jar"/>
<classpathentry kind="lib" path="compile-lib/bcpkix-jdk15on-151.jar"/>
<classpathentry kind="lib" path="compile-lib/bcprov-ext-jdk15on-1.51.jar"/>
<classpathentry kind="lib" path="compile-lib/xmlsec-2.0.1.jar"/>
<classpathentry kind="output" path="build/eclipse"/>
</classpath>

+ 20
- 7
build.xml View File

@@ -61,6 +61,7 @@ under the License.

<property name="main.lib" location="lib"/>
<property name="ooxml.lib" location="ooxml-lib"/>
<property name="compile.lib" location="compile-lib"/>
<property name="forrest.home" value="${env.FORREST_HOME}"/>

<!-- compiler options options -->
@@ -146,11 +147,15 @@ under the License.
<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"/>

<!-- test libs -->
<property name="test.bouncycastle-prov.jar" location="${main.lib}/bcprov-ext-jdk15on-1.51.jar"/>
<property name="test.bouncycastle-prov.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.51/bcprov-ext-jdk15on-1.51.jar"/>
<property name="test.bouncycastle-pkix.jar" location="${main.lib}/bcpkix-jdk15on-151.jar"/>
<property name="test.bouncycastle-pkix.url" value="${repository.m2}/maven2/org/bouncycastle/bcpkix-jdk15on/1.51/bcpkix-jdk15on-151.jar"/>
<!-- xml signature libs -->
<property name="dsig.xmlsec.jar" location="${compile.lib}/xmlsec-2.0.1.jar"/>
<property name="dsig.xmlsec.url" value="${repository.m2}/maven2/org/apache/santuario/xmlsec/2.0.1/xmlsec-2.0.1.jar"/>
<property name="dsig.bouncycastle-prov.jar" location="${compile.lib}/bcprov-ext-jdk15on-1.51.jar"/>
<property name="dsig.bouncycastle-prov.url" value="${repository.m2}/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.51/bcprov-ext-jdk15on-1.51.jar"/>
<property name="dsig.bouncycastle-pkix.jar" location="${compile.lib}/bcpkix-jdk15on-151.jar"/>
<property name="dsig.bouncycastle-pkix.url" value="${repository.m2}/maven2/org/bouncycastle/bcpkix-jdk15on/1.51/bcpkix-jdk15on-151.jar"/>
<property name="dsig.sl4j-api.jar" location="${compile.lib}/slf4j-api-1.7.7.jar"/>
<property name="dsig.sl4j-api.url" value="${repository.m2}/maven2/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar"/>

<!-- 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"/>
@@ -438,8 +443,16 @@ under the License.
<param name="destfile" value="${rat.jar}"/>
</antcall>
<antcall target="downloadfile">
<param name="sourcefile" value="${test.bouncycastle-prov.url}"/>
<param name="destfile" value="${test.bouncycastle-prov.jar}"/>
<param name="sourcefile" value="${dsig.bouncycastle-prov.url}"/>
<param name="destfile" value="${dsig.bouncycastle-prov.jar}"/>
</antcall>
<antcall target="downloadfile">
<param name="sourcefile" value="${dsig.bouncycastle-pkix.url}"/>
<param name="destfile" value="${dsig.bouncycastle-pkix.jar}"/>
</antcall>
<antcall target="downloadfile">
<param name="sourcefile" value="${dsig.xmlsec.url}"/>
<param name="destfile" value="${dsig.xmlsec.jar}"/>
</antcall>
</target>


+ 0
- 427
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/HorribleProxies.java View File

@@ -1,427 +0,0 @@
package org.apache.poi.poifs.crypt.dsig;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Date;
import javax.security.auth.x500.X500Principal;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.dom.DOMCryptoContext;
import javax.xml.crypto.dsig.XMLSignContext;
import javax.xml.crypto.dsig.XMLSignatureException;
import org.apache.poi.poifs.crypt.dsig.HorribleProxy.ProxyIf;
import org.w3c.dom.Node;
public interface HorribleProxies {
public static final String xmlSecBase = "org.jcp.xml.dsig.internal.dom";
// public static final String xmlSecBase = "org.apache.jcp.xml.dsig.internal.dom";
public interface ASN1InputStreamIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.ASN1InputStream";
ASN1OctetStringIf readObject$ASNString() throws IOException;
DEROctetStringIf readObject$DERString() throws IOException;
ASN1IntegerIf readObject$Integer() throws IOException;
ASN1SequenceIf readObject$Sequence() throws IOException;
Object readObject$Object() throws IOException;
}
public interface ASN1IntegerIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.ASN1Integer";
BigInteger getPositiveValue();
}
public interface ASN1ObjectIdentifierIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.ASN1ObjectIdentifier";
String getId();
}
public interface ASN1OctetStringIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.ASN1OctetString";
byte[] getOctets();
}
public interface ASN1SequenceIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.ASN1Sequence";
}
public interface AuthorityInformationAccessIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.AuthorityInformationAccess";
}
public interface AuthorityKeyIdentifierIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.AuthorityKeyIdentifier";
byte[] getKeyIdentifier();
}
public interface BasicConstraintsIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.BasicConstraints";
}
public interface BasicOCSPRespIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.BasicOCSPResp";
Date getProducedAt();
RespIDIf getResponderId();
}
public interface BcDigestCalculatorProviderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.operator.bc.BcDigestCalculatorProvider";
}
public interface BcRSASignerInfoVerifierBuilderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cms.bc.BcRSASignerInfoVerifierBuilder";
SignerInformationVerifierIf build(X509CertificateHolderIf holder);
}
public interface CanonicalizerIf extends ProxyIf {
String delegateClass = "com.sun.org.apache.xml.internal.security.c14n.Canonicalizer";
byte[] canonicalizeSubtree(Node node) throws Exception;
}
public interface CRLNumberIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.CRLNumber";
}
public interface DefaultDigestAlgorithmIdentifierFinderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder";
}
public interface DistributionPointNameIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.DistributionPointName";
}
public interface DistributionPointIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.DistributionPoint";
}
public interface DERIA5StringIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.DERIA5String";
}
public interface DEROctetStringIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.DEROctetString";
byte[] getOctets();
}
public interface DERTaggedObjectIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.DERTaggedObject";
int getTagNo();
ASN1OctetStringIf getObject$String();
Object getObject$Object();
}
public interface DERSequenceIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.DERSequence";
}
public interface DOMKeyInfoIf extends ProxyIf {
String delegateClass = xmlSecBase+".DOMKeyInfo";
void marshal(Node parent, Node nextSibling, String dsPrefix, DOMCryptoContext context) throws MarshalException;
}
public interface DOMReferenceIf extends ProxyIf {
String delegateClass = xmlSecBase+".DOMReference";
void digest(XMLSignContext paramXMLSignContext) throws XMLSignatureException;
byte[] getDigestValue();
}
public interface DOMSignedInfoIf extends ProxyIf {
String delegateClass = xmlSecBase+".DOMSignedInfo";
void canonicalize(XMLCryptoContext paramXMLCryptoContext, ByteArrayOutputStream paramByteArrayOutputStream);
}
public interface XMLSignatureIf extends ProxyIf {
String delegateClass = "com.sun.org.apache.xml.internal.security.signature.XMLSignature";
String ALGO_ID_SIGNATURE_RSA_SHA1();
String ALGO_ID_SIGNATURE_RSA_SHA256();
String ALGO_ID_SIGNATURE_RSA_SHA384();
String ALGO_ID_SIGNATURE_RSA_SHA512();
String ALGO_ID_MAC_HMAC_RIPEMD160();
}
public interface DOMXMLSignatureIf extends ProxyIf {
String delegateClass = xmlSecBase+".DOMXMLSignature";
void marshal(Node node, String prefix, DOMCryptoContext context) throws MarshalException;
}
public interface ExtensionsIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.Extensions";
}
public interface ExtensionIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.Extension";
}
public interface GeneralNameIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.GeneralName";
int uniformResourceIdentifier();
}
public interface GeneralNamesIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.GeneralNames";
}
public interface InitIf extends ProxyIf {
String delegateClass = "com.sun.org.apache.xml.internal.security.Init";
void init();
}
public interface JcaDigestCalculatorProviderBuilderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder";
JcaDigestCalculatorProviderBuilderIf setProvider(String provider);
DigestCalculatorProviderIf build();
}
public interface JcaContentSignerBuilderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.operator.jcajce.JcaContentSignerBuilder";
JcaContentSignerBuilderIf setProvider(String provider);
ContentSignerIf build(PrivateKey paramPrivateKey);
}
public interface ContentSignerIf extends ProxyIf {
String delegateClass = "org.bouncycastle.operator.ContentSigner";
}
public interface DigestCalculatorProviderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.operator.DigestCalculatorProvider";
DigestCalculatorIf get(AlgorithmIdentifierIf paramAlgorithmIdentifier);
}
public interface DigestCalculatorIf extends ProxyIf {
String delegateClass = "org.bouncycastle.operator.DigestCalculator";
}
public interface AlgorithmIdentifierIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.AlgorithmIdentifier";
}
public interface KeyUsageIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.KeyUsage";
int digitalSignature();
}
public interface OCSPObjectIdentifiersIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers";
ASN1ObjectIdentifierIf id_pkix_ocsp_nonce();
}
public interface OCSPRespIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.OCSPResp";
BasicOCSPRespIf getResponseObject();
byte[] getEncoded() throws IOException;
}
public interface PKIFailureInfoIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.cmp.PKIFailureInfo";
int intValue();
}
public interface RespIDIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.RespID";
ResponderIDIf toASN1Object();
}
public interface ResponderIDIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.ocsp.ResponderID";
DERTaggedObjectIf toASN1Object();
}
public interface SignerIdIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cms.SignerId";
BigInteger getSerialNumber();
X500Principal getIssuer();
}
public interface SignerInformationVerifierIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cms.SignerInformationVerifier";
}
public interface StoreIf extends ProxyIf {
String delegateClass = "org.bouncycastle.util.Store";
Collection<Certificate> getMatches(Object selector) throws Exception;
}
public interface SubjectKeyIdentifierIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.SubjectKeyIdentifier";
byte[] getKeyIdentifier();
}
public interface SubjectPublicKeyInfoIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.SubjectPublicKeyInfo";
}
public interface TimeStampRequestGeneratorIf extends ProxyIf {
String delegateClass = "org.bouncycastle.tsp.TimeStampRequestGenerator";
void setCertReq(boolean certReq);
void setReqPolicy(String reqPolicy);
TimeStampRequestIf generate(String igestAlgorithmOID, byte[] digest, BigInteger nonce);
}
public interface TimeStampRequestIf extends ProxyIf {
String delegateClass = "org.bouncycastle.tsp.TimeStampRequest";
byte[] getEncoded() throws IOException;
}
public interface TimeStampResponseIf extends ProxyIf {
String delegateClass = "org.bouncycastle.tsp.TimeStampResponse";
void validate(TimeStampRequestIf request) throws Exception;
int getStatus();
String getStatusString();
PKIFailureInfoIf getFailInfo();
TimeStampTokenIf getTimeStampToken();
}
public interface TimeStampTokenIf extends ProxyIf {
String delegateClass = "org.bouncycastle.tsp.TimeStampToken";
SignerIdIf getSID();
StoreIf getCertificates();
StoreIf getCRLs();
TimeStampTokenInfoIf getTimeStampInfo();
byte[] getEncoded() throws IOException;
void validate(SignerInformationVerifierIf verifier) throws Exception;
}
public interface TimeStampTokenInfoIf extends ProxyIf {
String delegateClass = "org.bouncycastle.tsp.TimeStampTokenInfo";
Date getGenTime();
}
public interface X509CertificateHolderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.X509CertificateHolder";
}
public interface X509NameIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.X509Name";
String toString$delegate();
}
public interface X509PrincipalIf extends ProxyIf {
String delegateClass = "org.bouncycastle.jce.X509Principal";
String getName();
}
public interface X509V3CertificateGeneratorIf extends ProxyIf {
String delegateClass = "org.bouncycastle.x509.X509V3CertificateGenerator";
void reset();
void setPublicKey(PublicKey key);
void setSignatureAlgorithm(String signatureAlgorithm);
void setNotBefore(Date date);
void setNotAfter(Date date);
void setIssuerDN(X509PrincipalIf issuerDN);
void setSubjectDN(X509PrincipalIf issuerDN);
void setSerialNumber(BigInteger serialNumber);
void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, SubjectKeyIdentifierIf value);
void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, AuthorityKeyIdentifierIf value);
void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, BasicConstraintsIf value);
void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, DERSequenceIf value);
void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, AuthorityInformationAccessIf value);
void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, KeyUsageIf value);
X509Certificate generate(PrivateKey issuerPrivateKey);
}
public interface OCSPReqIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.OCSPReq";
ReqIf[] getRequestList();
}
public interface OCSPReqBuilderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.OCSPReqBuilder";
OCSPReqBuilderIf addRequest(CertificateIDIf certId);
OCSPReqBuilderIf setRequestExtensions(ExtensionsIf paramExtensions);
OCSPReqIf build();
}
public interface OCSPRespBuilderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.OCSPRespBuilder";
OCSPRespIf build(int status, BasicOCSPRespIf basicOcspResp);
int SUCCESSFUL();
}
public interface BasicOCSPRespBuilderIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder";
BasicOCSPRespBuilderIf addResponse(CertificateIDIf certificateID, CertificateStatusIf certificateStatus);
BasicOCSPRespBuilderIf setResponseExtensions(ExtensionsIf paramExtensions);
BasicOCSPRespIf build(ContentSignerIf paramContentSigner, X509CertificateHolderIf[] paramArrayOfX509CertificateHolder, Date paramDate);
}
public interface CertificateIDIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.CertificateID";
AlgorithmIdentifierIf HASH_SHA1();
}
public interface X509ExtensionsIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.X509Extensions";
ASN1ObjectIdentifierIf AuthorityKeyIdentifier();
ASN1ObjectIdentifierIf SubjectKeyIdentifier();
ASN1ObjectIdentifierIf BasicConstraints();
ASN1ObjectIdentifierIf CRLDistributionPoints();
ASN1ObjectIdentifierIf AuthorityInfoAccess();
ASN1ObjectIdentifierIf KeyUsage();
ASN1ObjectIdentifierIf CRLNumber();
}
public interface X509ObjectIdentifiersIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.X509ObjectIdentifiers";
ASN1ObjectIdentifierIf ocspAccessMethod();
}
public interface X509V2CRLGeneratorIf extends ProxyIf {
String delegateClass = "org.bouncycastle.x509.X509V2CRLGenerator";
void setIssuerDN(X500Principal issuerDN);
void setThisUpdate(Date date);
void setNextUpdate(Date date);
void setSignatureAlgorithm(String algorithm);
void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, CRLNumberIf value);
X509CRL generate(PrivateKey privateKey);
}
public interface ReqIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.Req";
CertificateIDIf getCertID();
}
public interface CertificateStatusIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.CertificateStatus";
CertificateStatusIf GOOD();
}
public interface RevokedStatusIf extends ProxyIf {
String delegateClass = "org.bouncycastle.ocsp.RevokedStatus";
}
public interface CRLReasonIf extends ProxyIf {
String delegateClass = "org.bouncycastle.asn1.x509.CRLReason";
int unspecified();
int privilegeWithdrawn();
}
}

+ 0
- 264
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/HorribleProxy.java View File

@@ -1,264 +0,0 @@
package org.apache.poi.poifs.crypt.dsig;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import org.apache.poi.util.MethodUtils;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
public class HorribleProxy implements InvocationHandler {
private static final POILogger LOG = POILogFactory.getLogger(HorribleProxy.class);
protected static interface ProxyIf {
Object getDelegate();
void setInitDeferred(boolean initDeferred);
};
private final Class<?> delegateClass;
private Object delegateRef;
private boolean initDeferred = true;
protected HorribleProxy(Class<?> delegateClass, Object delegateRef) {
this.delegateClass = delegateClass;
// delegateRef can be null, then we have to deal with deferred initialisation
this.delegateRef = delegateRef;
initDeferred = (delegateRef == null);
}
/**
* Create new instance by constructor
*
* @param proxyClass
* @param initargs
* @return
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
public static <T extends ProxyIf> T newProxy(Class<T> proxyClass, Object ... initargs)
throws InvocationTargetException, IllegalAccessException, InstantiationException
, NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<?> delegateClass = getDelegateClass(proxyClass);
Object delegateRef;
if (initargs.length == 0) {
delegateRef = null;
} else if (initargs.length == 1 && delegateClass.isAssignableFrom(initargs[0].getClass())) {
delegateRef = initargs[0];
} else {
Class<?> paramTypes[] = updateMethodArgs(null, initargs);
Constructor<?> cons = null;
try {
cons = delegateClass.getConstructor(paramTypes);
} catch (Exception e) {
// fallback - find constructor with same amount of parameters
// horrible et al. ...
cons = MethodUtils.getMatchingAccessibleConstructor(delegateClass, paramTypes);
if (cons == null) {
throw new RuntimeException("There's no constructor for the given arguments.");
}
}
delegateRef = cons.newInstance(initargs);
}
HorribleProxy hp = new HorribleProxy(delegateClass, delegateRef);
return (T)Proxy.newProxyInstance(cl, new Class<?>[]{proxyClass}, hp);
}
/**
* Create new instance by factory method
*
* @param proxyClass
* @param factoryMethod
* @param initargs
* @return
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
public static <T extends ProxyIf> T createProxy(Class<T> proxyClass, String factoryMethod, Object ... initargs)
throws InvocationTargetException, IllegalAccessException, InstantiationException
, NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<?> delegateClass = getDelegateClass(proxyClass);
Class<?> paramTypes[] = updateMethodArgs(null, initargs);
Method facMethod = delegateClass.getMethod(factoryMethod, paramTypes);
Object delegateRef = facMethod.invoke(null, initargs);
if (delegateRef == null) {
return null;
}
HorribleProxy hp = new HorribleProxy(delegateClass, delegateRef);
return (T)Proxy.newProxyInstance(cl, new Class<?>[]{proxyClass}, hp);
}
@SuppressWarnings("unchecked")
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Exception {
String methodName = method.getName().replaceFirst("\\$.*", "");
if (Object.class == method.getDeclaringClass()) {
if ("equals".equals(methodName)) {
return proxy == args[0];
} else if ("hashCode".equals(methodName)) {
return System.identityHashCode(proxy);
} else if ("toString".equals(methodName)) {
return proxy.getClass().getName() + "@"
+ Integer.toHexString(System.identityHashCode(proxy))
+ ", with InvocationHandler " + this;
} else {
throw new IllegalStateException(String.valueOf(method));
}
}
if ("getDelegate".equals(methodName)) {
initDeferred();
return delegateRef;
} else if ("setInitDeferred".equals(methodName)) {
initDeferred = (Boolean)args[0];
return null;
}
Class<?> methodParams[] = updateMethodArgs(method.getParameterTypes(), args);
Object ret = null;
boolean isStaticField = false;
if (methodParams.length == 0) {
// check for static fields first
try {
Field f = delegateClass.getDeclaredField(methodName);
ret = f.get(delegateRef);
if (ret == null) return null;
isStaticField = true;
} catch (NoSuchFieldException e) {
LOG.log(POILogger.DEBUG, "No static field '"+methodName+"' in class '"+delegateClass.getCanonicalName()+"' - trying method now.");
}
}
if (!isStaticField) {
Method methodImpl = null;
try {
methodImpl = delegateClass.getMethod(methodName, methodParams);
} catch (Exception e) {
// fallback - if methodName is distinct, try to use it
// in case we can't provide method declaration in the Proxy interface
// ... and of course, this is horrible ...
methodImpl = MethodUtils.getMatchingAccessibleMethod(delegateClass, methodName, methodParams);
if (methodImpl == null) {
throw new RuntimeException("There's no method '"+methodName+"' for the given arguments.");
}
}
if (!Modifier.isStatic(methodImpl.getModifiers())) {
initDeferred();
}
ret = methodImpl.invoke(delegateRef, args);
}
Class<?> retType = method.getReturnType();
if (retType.isArray()) {
if (ProxyIf.class.isAssignableFrom(retType.getComponentType())) {
Class<? extends ProxyIf> cType = (Class<? extends ProxyIf>)retType.getComponentType();
ProxyIf paRet[] = (ProxyIf[])Array.newInstance(cType, ((Object[])ret).length);
for (int i=0; i<((Object[])ret).length; i++) {
paRet[i] = newProxy(cType, ((Object[])ret)[i]);
paRet[i].setInitDeferred(false);
}
ret = paRet;
}
} else if (ProxyIf.class.isAssignableFrom(retType)) {
ProxyIf pRet = newProxy((Class<? extends ProxyIf>)retType, ret);
pRet.setInitDeferred(false);
ret = pRet;
}
return ret;
}
@SuppressWarnings("unchecked")
private static Class<?>[] updateMethodArgs(Class<?> types[], Object args[])
throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
if (args == null) return new Class<?>[0];
if (types == null) types = new Class<?>[args.length];
if (types.length != args.length) {
throw new IllegalArgumentException();
}
for (int i=0; i<types.length; i++) {
if (types[i] == null) {
if (args[i] == null) {
throw new IllegalArgumentException();
}
types[i] = args[i].getClass();
}
if (types[i].isArray()) {
// TODO: check for null arguments ...
if (ProxyIf.class.isAssignableFrom(types[i].getComponentType())) {
ProxyIf pifs[] = (ProxyIf[])args[i];
Class<?> dc = getDelegateClass((Class<? extends ProxyIf>)types[i].getComponentType());
int dcArrSize = (pifs==null ? 0 : pifs.length);
Object[] dcArr = (Object[])Array.newInstance(dc, dcArrSize);
for (int j=0;j<dcArrSize;j++) {
dcArr[j] = pifs[j].getDelegate();
}
args[i] = dcArr;
types[i] = dcArr.getClass();
}
} else if (ProxyIf.class.isAssignableFrom(types[i])) {
types[i] = getDelegateClass((Class<? extends ProxyIf>)types[i]);
if (args[i] != null) {
args[i] = ((ProxyIf)args[i]).getDelegate();
}
}
}
return types;
}
private void initDeferred() throws Exception {
if (delegateRef != null || !initDeferred) return;
// currently works only for empty constructor
delegateRef = delegateClass.getConstructor().newInstance();
}
private static Class<?> getDelegateClass(Class<? extends ProxyIf> proxyClass)
throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
Field delegateField;
try {
delegateField = proxyClass.getDeclaredField("delegateClass");
} catch (NoSuchFieldException e) {
// sometimes a proxy interface is returned as proxyClass
// this has to be asked for the real ProxyIf interface
Class<?> ifs[] = proxyClass.getInterfaces();
if (ifs == null || ifs.length != 1) {
throw new IllegalArgumentException();
}
delegateField = ifs[0].getDeclaredField("delegateClass");
}
String delegateClassName = (String)delegateField.get(null);
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<?> delegateClass = Class.forName(delegateClassName, true, cl);
return delegateClass;
}
}

+ 62
- 38
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java View File

@@ -26,21 +26,22 @@ package org.apache.poi.poifs.crypt.dsig;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.crypto.Cipher;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
@@ -53,19 +54,24 @@ import org.apache.poi.poifs.crypt.ChainingMode;
import org.apache.poi.poifs.crypt.CipherAlgorithm;
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.InitIf;
import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.SAXHelper;
import org.apache.xml.security.Init;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class SignatureInfo {
public static final String XmlNS = "http://www.w3.org/2000/xmlns/";
public static final String XmlDSigNS = XMLSignature.XMLNS;
public static final byte[] SHA1_DIGEST_INFO_PREFIX = new byte[]
{ 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14 };
@@ -108,31 +114,33 @@ public class SignatureInfo {
public boolean verifySignature() {
initXmlProvider();
// http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html
List<X509Certificate> signers = new LinkedList<X509Certificate>();
List<X509Certificate> signers = new ArrayList<X509Certificate>();
return getSignersAndValidate(signers, true);
}
public void confirmSignature(Key key, X509Certificate x509)
throws NoSuchAlgorithmException, IOException {
public void confirmSignature(PrivateKey key, X509Certificate x509)
throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {
confirmSignature(key, x509, HashAlgorithm.sha1);
}
public void confirmSignature(Key key, X509Certificate x509, HashAlgorithm hashAlgo)
throws NoSuchAlgorithmException, IOException {
public void confirmSignature(PrivateKey key, X509Certificate x509, HashAlgorithm hashAlgo)
throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {
XmlSignatureService signatureService = createSignatureService(hashAlgo, pkg);
Document document = SAXHelper.getDocumentBuilder().newDocument();
// operate
List<X509Certificate> x509Chain = Collections.singletonList(x509);
DigestInfo digestInfo = signatureService.preSign(null, x509Chain, null, null, null);
DigestInfo digestInfo = signatureService.preSign(document, null, key, x509Chain, null, null, null);
// setup: key material, signature value
byte[] signatureValue = signDigest(key, hashAlgo, digestInfo.digestValue);
// operate: postSign
signatureService.postSign(signatureValue, Collections.singletonList(x509));
signatureService.postSign(document, signatureValue, Collections.singletonList(x509));
}
public static byte[] signDigest(Key key, HashAlgorithm hashAlgo, byte digest[]) {
public static byte[] signDigest(PrivateKey key, HashAlgorithm hashAlgo, byte digest[]) {
Cipher cipher = CryptoFunctions.getCipher(key, CipherAlgorithm.rsa
, ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");
@@ -156,7 +164,7 @@ public class SignatureInfo {
public List<X509Certificate> getSigners() {
initXmlProvider();
List<X509Certificate> signers = new LinkedList<X509Certificate>();
List<X509Certificate> signers = new ArrayList<X509Certificate>();
getSignersAndValidate(signers, false);
return signers;
}
@@ -201,7 +209,7 @@ public class SignatureInfo {
}
protected List<PackagePart> getSignatureParts(boolean onlyFirst) {
List<PackagePart> packageParts = new LinkedList<PackagePart>();
List<PackagePart> packageParts = new ArrayList<PackagePart>();
PackageRelationshipCollection sigOrigRels = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);
for (PackageRelationship rel : sigOrigRels) {
@@ -227,17 +235,32 @@ public class SignatureInfo {
}
public static XMLSignatureFactory getSignatureFactory() {
Provider p = Security.getProvider("XMLDSig");
assert(p != null);
return XMLSignatureFactory.getInstance("DOM", p);
return XMLSignatureFactory.getInstance("DOM", getProvider());
}
public static KeyInfoFactory getKeyInfoFactory() {
Provider p = Security.getProvider("XMLDSig");
assert(p != null);
return KeyInfoFactory.getInstance("DOM", p);
return KeyInfoFactory.getInstance("DOM", getProvider());
}
// currently classes are linked to Apache Santuario, so this might be superfluous
public static Provider getProvider() {
String dsigProviderNames[] = {
System.getProperty("jsr105Provider"),
"org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI", // Santuario xmlsec
"org.jcp.xml.dsig.internal.dom.XMLDSigRI" // JDK xmlsec
};
for (String pn : dsigProviderNames) {
if (pn == null) continue;
try {
return (Provider)Class.forName(pn).newInstance();
} catch (Exception e) {
LOG.log(POILogger.DEBUG, "XMLDsig-Provider '"+pn+"' can't be found - trying next.");
}
}
throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!");
}
public static void insertXChild(XmlObject root, XmlObject child) {
XmlCursor rootCursor = root.newCursor();
insertXChild(rootCursor, child);
@@ -252,12 +275,22 @@ public class SignatureInfo {
childCursor.dispose();
}
public static void setPrefix(XmlObject xobj, String ns, String prefix) {
for (XmlCursor cur = xobj.newCursor(); cur.hasNextToken(); cur.toNextToken()) {
if (cur.isStart()) {
Element el = (Element)cur.getDomNode();
if (ns.equals(el.getNamespaceURI())) el.setPrefix(prefix);
}
// public static void setPrefix(XmlObject xobj, String ns, String prefix) {
// XmlCursor cur;
// for (cur = xobj.newCursor(); cur.hasNextToken(); cur.toNextToken()) {
// if (cur.isStart()) {
// Element el = (Element)cur.getDomNode();
// if (ns.equals(el.getNamespaceURI())) el.setPrefix(prefix);
// }
// }
// cur.dispose();
// }
public static void setPrefix(Node el, String ns, String prefix) {
if (ns.equals(el.getNamespaceURI())) el.setPrefix(prefix);
NodeList nl = el.getChildNodes();
for (int i=0; i<nl.getLength(); i++) {
setPrefix(nl.item(i), ns, prefix);
}
}
@@ -280,18 +313,9 @@ public class SignatureInfo {
isInitialized = true;
try {
InitIf init = HorribleProxy.newProxy(InitIf.class);
init.init();
Init.init();
RelationshipTransformService.registerDsigProvider();
Provider bcProv = Security.getProvider("BC");
if (bcProv == null) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<?> c = cl.loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider");
bcProv = (Provider)c.newInstance();
Security.addProvider(bcProv);
}
CryptoFunctions.registerBouncyCastle();
} catch (Exception e) {
throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e);
}

+ 140
- 176
src/ooxml/testcases/org/apache/poi/poifs/crypt/PkiTestUtils.java View File

@@ -16,25 +16,18 @@
==================================================================== */
package org.apache.poi.poifs.crypt;
import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.newProxy;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.SignatureException;
import java.security.cert.CRLException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.security.spec.RSAKeyGenParameterSpec;
@@ -52,45 +45,49 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.AuthorityInformationAccessIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.AuthorityKeyIdentifierIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicConstraintsIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicOCSPRespBuilderIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicOCSPRespIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CRLNumberIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CRLReasonIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CertificateIDIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CertificateStatusIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ContentSignerIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DERIA5StringIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DEROctetStringIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DERSequenceIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DigestCalculatorIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DistributionPointIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DistributionPointNameIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ExtensionIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ExtensionsIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.GeneralNameIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.GeneralNamesIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.JcaContentSignerBuilderIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.JcaDigestCalculatorProviderBuilderIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.KeyUsageIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPObjectIdentifiersIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPReqBuilderIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPReqIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespBuilderIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ReqIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.RevokedStatusIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SubjectKeyIdentifierIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SubjectPublicKeyInfoIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509CertificateHolderIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509ExtensionsIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509ObjectIdentifiersIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509PrincipalIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509V2CRLGeneratorIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509V3CertificateGeneratorIf;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.asn1.x509.DistributionPoint;
import org.bouncycastle.asn1.x509.DistributionPointName;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v2CRLBuilder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
import org.bouncycastle.cert.ocsp.CertificateID;
import org.bouncycastle.cert.ocsp.CertificateStatus;
import org.bouncycastle.cert.ocsp.OCSPReq;
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
import org.bouncycastle.cert.ocsp.Req;
import org.bouncycastle.cert.ocsp.RevokedStatus;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
@@ -111,27 +108,21 @@ public class PkiTestUtils {
return keyPair;
}
private static SubjectKeyIdentifierIf createSubjectKeyId(PublicKey publicKey)
throws IOException, ClassNotFoundException, NoSuchMethodException, InstantiationException
, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
ASN1InputStreamIf asnObj = newProxy(ASN1InputStreamIf.class, bais);
SubjectPublicKeyInfoIf info =
newProxy(SubjectPublicKeyInfoIf.class, asnObj.readObject$Sequence());
SubjectKeyIdentifierIf keyId = newProxy(SubjectKeyIdentifierIf.class, info);
@SuppressWarnings("resource")
private static SubjectKeyIdentifier createSubjectKeyId(PublicKey publicKey)
throws IOException {
ASN1InputStream asnObj = new ASN1InputStream(publicKey.getEncoded());
SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(asnObj.readObject());
SubjectKeyIdentifier keyId = SubjectKeyIdentifier.getInstance(info.getEncoded());
return keyId;
}
private static AuthorityKeyIdentifierIf createAuthorityKeyId(PublicKey publicKey)
throws IOException, ClassNotFoundException, NoSuchMethodException, InstantiationException
, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
ASN1InputStreamIf asnObj = newProxy(ASN1InputStreamIf.class, bais);
SubjectPublicKeyInfoIf info =
newProxy(SubjectPublicKeyInfoIf.class, asnObj.readObject$Sequence());
AuthorityKeyIdentifierIf keyId = newProxy(AuthorityKeyIdentifierIf.class, info);
@SuppressWarnings("resource")
private static AuthorityKeyIdentifier createAuthorityKeyId(PublicKey publicKey)
throws IOException {
ASN1InputStream asnObj = new ASN1InputStream(publicKey.getEncoded());
SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(asnObj.readObject());
AuthorityKeyIdentifier keyId = AuthorityKeyIdentifier.getInstance(info);
return keyId;
}
@@ -139,88 +130,76 @@ public class PkiTestUtils {
String subjectDn, Date notBefore, Date notAfter,
X509Certificate issuerCertificate, PrivateKey issuerPrivateKey,
boolean caFlag, int pathLength, String crlUri, String ocspUri,
KeyUsageIf keyUsage)
throws IOException, InvalidKeyException, IllegalStateException, NoSuchAlgorithmException
, SignatureException, CertificateException, InvocationTargetException, IllegalAccessException
, InstantiationException, NoSuchMethodException, ClassNotFoundException, NoSuchFieldException
KeyUsage keyUsage)
throws IOException, OperatorCreationException, CertificateException
{
String signatureAlgorithm = "SHA1withRSA";
X509V3CertificateGeneratorIf certificateGenerator = newProxy(X509V3CertificateGeneratorIf.class);
certificateGenerator.reset();
certificateGenerator.setPublicKey(subjectPublicKey);
certificateGenerator.setSignatureAlgorithm(signatureAlgorithm);
certificateGenerator.setNotBefore(notBefore);
certificateGenerator.setNotAfter(notAfter);
X509PrincipalIf subjectDN = newProxy(X509PrincipalIf.class, subjectDn);
X509PrincipalIf issuerDN;
if (null != issuerCertificate) {
issuerDN = newProxy(X509PrincipalIf.class, issuerCertificate
.getSubjectX500Principal().toString());
X500Name issuerName;
if (issuerCertificate != null) {
issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer();
} else {
issuerDN = subjectDN;
issuerName = new X500Name(subjectDn);
}
certificateGenerator.setIssuerDN(issuerDN);
certificateGenerator.setSubjectDN(subjectDN);
certificateGenerator.setSerialNumber(new BigInteger(128,
new SecureRandom()));
X509ExtensionsIf X509Extensions = newProxy(X509ExtensionsIf.class);
SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(
ASN1Sequence.getInstance(subjectPublicKey.getEncoded()));
certificateGenerator.addExtension(X509Extensions.SubjectKeyIdentifier(),
false, createSubjectKeyId(subjectPublicKey));
PublicKey issuerPublicKey;
issuerPublicKey = subjectPublicKey;
certificateGenerator.addExtension(
X509Extensions.AuthorityKeyIdentifier(), false,
createAuthorityKeyId(issuerPublicKey));
X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder(
issuerName
, new BigInteger(128, new SecureRandom())
, notBefore
, notAfter
, new X500Name(subjectDn)
, subjectPublicKeyInfo
);
certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyId(subjectPublicKey));
certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, createAuthorityKeyId(subjectPublicKey));
if (caFlag) {
BasicConstraintsIf bc;
BasicConstraints bc;
if (-1 == pathLength) {
bc = newProxy(BasicConstraintsIf.class, true);
bc = new BasicConstraints(true);
} else {
bc = newProxy(BasicConstraintsIf.class, pathLength);
bc = new BasicConstraints(pathLength);
}
certificateGenerator.addExtension(X509Extensions.BasicConstraints(), false, bc);
certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
}
if (null != crlUri) {
GeneralNameIf gn = newProxy(GeneralNameIf.class);
int uri = gn.uniformResourceIdentifier();
DERIA5StringIf crlUriDer = newProxy(DERIA5StringIf.class, crlUri);
gn = newProxy(GeneralNameIf.class, uri, crlUriDer);
int uri = GeneralName.uniformResourceIdentifier;
DERIA5String crlUriDer = new DERIA5String(crlUri);
GeneralName gn = new GeneralName(uri, crlUriDer);
DERSequenceIf gnDer = newProxy(DERSequenceIf.class, gn);
GeneralNamesIf gns = newProxy(GeneralNamesIf.class, gnDer);
DERSequence gnDer = new DERSequence(gn);
GeneralNames gns = GeneralNames.getInstance(gnDer);
DistributionPointNameIf dpn = newProxy(DistributionPointNameIf.class, 0, gns);
DistributionPointIf distp = newProxy(DistributionPointIf.class, dpn, null, null);
DERSequenceIf distpDer = newProxy(DERSequenceIf.class, distp);
certificateGenerator.addExtension(X509Extensions.CRLDistributionPoints(), false, distpDer);
DistributionPointName dpn = new DistributionPointName(0, gns);
DistributionPoint distp = new DistributionPoint(dpn, null, null);
DERSequence distpDer = new DERSequence(distp);
certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer);
}
if (null != ocspUri) {
GeneralNameIf ocspName = newProxy(GeneralNameIf.class);
int uri = ocspName.uniformResourceIdentifier();
ocspName = newProxy(GeneralNameIf.class, uri, ocspUri);
int uri = GeneralName.uniformResourceIdentifier;
GeneralName ocspName = new GeneralName(uri, ocspUri);
X509ObjectIdentifiersIf X509ObjectIdentifiers = newProxy(X509ObjectIdentifiersIf.class);
AuthorityInformationAccessIf authorityInformationAccess =
newProxy(AuthorityInformationAccessIf.class
, X509ObjectIdentifiers.ocspAccessMethod(), ocspName);
AuthorityInformationAccess authorityInformationAccess =
new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
certificateGenerator.addExtension(
X509Extensions.AuthorityInfoAccess(), false,
authorityInformationAccess);
certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess);
}
if (null != keyUsage) {
certificateGenerator.addExtension(X509Extensions.KeyUsage(), true, keyUsage);
certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
}
X509Certificate certificate;
certificate = certificateGenerator.generate(issuerPrivateKey);
JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm);
signerBuilder.setProvider("BC");
X509CertificateHolder certHolder =
certificateGenerator.build(signerBuilder.build(issuerPrivateKey));
/*
* Next certificate factory trick is needed to make sure that the
@@ -228,12 +207,11 @@ public class PkiTestUtils {
* security provider instead of BouncyCastle. If we don't do this trick
* we might run into trouble when trying to use the CertPath validator.
*/
CertificateFactory certificateFactory = CertificateFactory
.getInstance("X.509");
certificate = (X509Certificate) certificateFactory
.generateCertificate(new ByteArrayInputStream(certificate
.getEncoded()));
return certificate;
// CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// certificate = (X509Certificate) certificateFactory
// .generateCertificate(new ByteArrayInputStream(certificate
// .getEncoded()));
return new JcaX509CertificateConverter().getCertificate(certHolder);
}
static Document loadDocument(InputStream documentInputStream)
@@ -264,93 +242,79 @@ public class PkiTestUtils {
return stringWriter.getBuffer().toString();
}
public static X509CRL generateCrl(X509Certificate issuer,
PrivateKey issuerPrivateKey) throws InvalidKeyException,
CRLException, IllegalStateException, NoSuchAlgorithmException,
SignatureException, InvocationTargetException, IllegalAccessException,
InstantiationException, NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
X509V2CRLGeneratorIf crlGenerator = newProxy(X509V2CRLGeneratorIf.class);
crlGenerator.setIssuerDN(issuer.getSubjectX500Principal());
Date now = new Date();
crlGenerator.setThisUpdate(now);
crlGenerator.setNextUpdate(new Date(now.getTime() + 100000));
crlGenerator.setSignatureAlgorithm("SHA1withRSA");
public static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey)
throws CertificateEncodingException, IOException, CRLException, OperatorCreationException {
X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded());
X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date());
crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000));
JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC");
X509ExtensionsIf X509Extensions = newProxy(X509ExtensionsIf.class);
CRLNumberIf crlNumber = newProxy(CRLNumberIf.class, new BigInteger("1234"));
CRLNumber crlNumber = new CRLNumber(new BigInteger("1234"));
crlGenerator.addExtension(X509Extensions.CRLNumber(), false, crlNumber);
X509CRL x509Crl = crlGenerator.generate(issuerPrivateKey);
return x509Crl;
crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber);
X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey));
return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl);
}
public static OCSPRespIf createOcspResp(X509Certificate certificate,
public static OCSPResp createOcspResp(X509Certificate certificate,
boolean revoked, X509Certificate issuerCertificate,
X509Certificate ocspResponderCertificate,
PrivateKey ocspResponderPrivateKey, String signatureAlgorithm,
long nonceTimeinMillis)
throws Exception {
CertificateIDIf certId = newProxy(CertificateIDIf.class);
DigestCalculatorIf digestCalc =
newProxy(JcaDigestCalculatorProviderBuilderIf.class)
.setProvider("BC").build().get(certId.HASH_SHA1());
X509CertificateHolderIf issuerHolder = newProxy(X509CertificateHolderIf.class, issuerCertificate.getEncoded());
certId = newProxy(CertificateIDIf.class, digestCalc, issuerHolder, certificate.getSerialNumber());
DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
.setProvider("BC").build().get(CertificateID.HASH_SHA1);
X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded());
CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber());
// request
//create a nonce to avoid replay attack
BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis);
OCSPObjectIdentifiersIf oidIf = newProxy(OCSPObjectIdentifiersIf.class);
DEROctetStringIf nonceDer = newProxy(DEROctetStringIf.class, nonce.toByteArray());
ExtensionIf ext = newProxy(ExtensionIf.class, oidIf.id_pkix_ocsp_nonce(), true, nonceDer);
ExtensionsIf exts = newProxy(ExtensionsIf.class, ext);
DEROctetString nonceDer = new DEROctetString(nonce.toByteArray());
Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer);
Extensions exts = new Extensions(ext);
OCSPReqBuilderIf ocspReqBuilder = newProxy(OCSPReqBuilderIf.class);
OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
ocspReqBuilder.addRequest(certId);
ocspReqBuilder.setRequestExtensions(exts);
OCSPReqIf ocspReq = ocspReqBuilder.build();
OCSPReq ocspReq = ocspReqBuilder.build();
SubjectPublicKeyInfoIf keyInfo = newProxy(SubjectPublicKeyInfoIf.class
, certId.HASH_SHA1(), ocspResponderCertificate.getPublicKey().getEncoded());
SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo
(CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded());
BasicOCSPRespBuilderIf basicOCSPRespBuilder =
newProxy(BasicOCSPRespBuilderIf.class, keyInfo, digestCalc);
BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc);
basicOCSPRespBuilder.setResponseExtensions(exts);
// request processing
ReqIf[] requestList = ocspReq.getRequestList();
for (ReqIf ocspRequest : requestList) {
CertificateIDIf certificateID = ocspRequest.getCertID();
CertificateStatusIf certificateStatus;
Req[] requestList = ocspReq.getRequestList();
for (Req ocspRequest : requestList) {
CertificateID certificateID = ocspRequest.getCertID();
CertificateStatus certificateStatus = CertificateStatus.GOOD;
if (revoked) {
CRLReasonIf crlr = newProxy(CRLReasonIf.class);
RevokedStatusIf rs = newProxy(RevokedStatusIf.class, new Date(), crlr.privilegeWithdrawn());
certificateStatus = newProxy(CertificateStatusIf.class, rs.getDelegate());
} else {
CertificateStatusIf cs = newProxy(CertificateStatusIf.class);
certificateStatus = cs.GOOD();
certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn);
}
basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
}
// basic response generation
X509CertificateHolderIf[] chain = null;
X509CertificateHolder[] chain = null;
if (!ocspResponderCertificate.equals(issuerCertificate)) {
// TODO: HorribleProxy can't convert array input params yet
chain = new X509CertificateHolderIf[] {
newProxy(X509CertificateHolderIf.class, ocspResponderCertificate),
chain = new X509CertificateHolder[] {
new X509CertificateHolder(ocspResponderCertificate.getEncoded()),
issuerHolder
};
}
ContentSignerIf contentSigner = newProxy(JcaContentSignerBuilderIf.class, "SHA1withRSA")
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA")
.setProvider("BC").build(ocspResponderPrivateKey);
BasicOCSPRespIf basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
OCSPRespBuilderIf ocspRespBuilder = newProxy(OCSPRespBuilderIf.class);
OCSPRespIf ocspResp = ocspRespBuilder.build(ocspRespBuilder.SUCCESSFUL(), basicOCSPResp);
OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
OCSPResp ocspResp = ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp);
return ocspResp;
}

+ 48
- 29
src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java View File

@@ -52,13 +52,11 @@ 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 javax.xml.parsers.DocumentBuilderFactory;
import org.apache.poi.POIDataSamples;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.KeyUsageIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
@@ -75,12 +73,17 @@ import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.SAXHelper;
import org.apache.xmlbeans.XmlObject;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.w3.x2000.x09.xmldsig.SignatureDocument;
import org.w3c.dom.Document;
public class TestSignatureInfo {
private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);
@@ -199,7 +202,9 @@ public class TestSignatureInfo {
pkg.close();
}
@SuppressWarnings("unused")
@Test
@Ignore
public void testSignEnvelopingDocument() throws Exception {
String testFile = "hello-world-unsigned.xlsx";
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);
@@ -213,28 +218,37 @@ public class TestSignatureInfo {
XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(null, null, signaturePolicyService);
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
// TimeStampService timeStampService = new TimeStampService(){
// public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception {
// revocationData.addCRL(crl);
// return "time-stamp-token".getBytes();
// }
// };
// http://timestamping.edelweb.fr/service/tsp
// http://tsa.belgium.be/connect
String tspServiceUrl = "http://timestamping.edelweb.fr/service/tsp";
TimeStampServiceValidator tspValidator = new TimeStampServiceValidator() {
@Override
public void validate(List<X509Certificate> certificateChain,
RevocationData revocationData) throws Exception {
for (X509Certificate certificate : certificateChain) {
LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal());
LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter());
TimeStampService timeStampService;
if (tspServiceUrl == null) {
timeStampService = new TimeStampService(){
public byte[] timeStamp(byte[] data, RevocationData revocationData) throws Exception {
revocationData.addCRL(crl);
return "time-stamp-token".getBytes();
}
};
} else {
TimeStampServiceValidator tspValidator = new TimeStampServiceValidator() {
@Override
public void validate(List<X509Certificate> certificateChain,
RevocationData revocationData) throws Exception {
for (X509Certificate certificate : certificateChain) {
LOG.log(POILogger.DEBUG, "certificate: " + certificate.getSubjectX500Principal());
LOG.log(POILogger.DEBUG, "validity: " + certificate.getNotBefore() + " - " + certificate.getNotAfter());
}
}
};
TSPTimeStampService tspService = new TSPTimeStampService(tspServiceUrl, tspValidator);
if (tspServiceUrl.contains("edelweb")) {
tspService.setRequestContentType("application/timestamp-request");
tspService.setResponseContentType("application/timestamp-response");
}
};
TimeStampService timeStampService = new TSPTimeStampService(tspServiceUrl, tspValidator);
timeStampService = tspService;
}
List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();
/*
@@ -246,7 +260,7 @@ public class TestSignatureInfo {
final RevocationData revocationData = new RevocationData();
revocationData.addCRL(crl);
OCSPRespIf ocspResp = PkiTestUtils.createOcspResp(x509, false,
OCSPResp ocspResp = PkiTestUtils.createOcspResp(x509, false,
x509, x509, keyPair.getPrivate(), "SHA1withRSA", cal.getTimeInMillis());
revocationData.addOCSP(ocspResp.getEncoded());
@@ -263,16 +277,19 @@ public class TestSignatureInfo {
xadesSignatureFacet, xadesXLSignatureFacet);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document document = dbf.newDocumentBuilder().newDocument();
// operate
DigestInfo digestInfo = testedInstance.preSign(null, certificateChain, null, null, null);
DigestInfo digestInfo = testedInstance.preSign(document, null, keyPair.getPrivate(), certificateChain, null, null, null);
// verify
assertNotNull(digestInfo);
assertEquals(HashAlgorithm.sha1, digestInfo.hashAlgo);
assertNotNull(digestInfo.digestValue);
SignatureDocument sigDoc = testedInstance.getSignatureDocument();
SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);
String certDigestXQuery =
"declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; "
+ "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; "
@@ -286,17 +303,18 @@ public class TestSignatureInfo {
byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);
// Operate: postSign
testedInstance.postSign(signatureValue, certificateChain);
testedInstance.postSign(document, signatureValue, certificateChain);
DOMValidateContext domValidateContext = new DOMValidateContext(
KeySelector.singletonKeySelector(keyPair.getPublic()),
testedInstance.getSignatureDocument().getDomNode());
document);
XMLSignatureFactory xmlSignatureFactory = SignatureInfo.getSignatureFactory();
XMLSignature xmlSignature = xmlSignatureFactory
.unmarshalXMLSignature(domValidateContext);
boolean validity = xmlSignature.validate(domValidateContext);
assertTrue(validity);
sigDoc = SignatureDocument.Factory.parse(document);
xoList = sigDoc.selectPath(certDigestXQuery);
assertEquals(xoList.length, 1);
certDigest = (DigestAlgAndValueType)xoList[0];
@@ -320,9 +338,11 @@ public class TestSignatureInfo {
signatureService.initFacets(cal.getTime());
initKeyPair(alias, signerDn);
Document document = SAXHelper.getDocumentBuilder().newDocument();
// operate
List<X509Certificate> x509Chain = Collections.singletonList(x509);
DigestInfo digestInfo = signatureService.preSign(null, x509Chain, null, null, null);
DigestInfo digestInfo = signatureService.preSign(document, null, keyPair.getPrivate(), x509Chain, null, null, null);
// verify
assertNotNull(digestInfo);
@@ -336,7 +356,7 @@ public class TestSignatureInfo {
byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);
// operate: postSign
signatureService.postSign(signatureValue, Collections.singletonList(x509));
signatureService.postSign(document, signatureValue, Collections.singletonList(x509));
// verify: signature
SignatureInfo si = new SignatureInfo(pkgCopy);
@@ -370,8 +390,7 @@ public class TestSignatureInfo {
Date notBefore = cal.getTime();
cal.add(Calendar.YEAR, 1);
Date notAfter = cal.getTime();
KeyUsageIf keyUsage = HorribleProxy.newProxy(KeyUsageIf.class);
keyUsage = HorribleProxy.newProxy(KeyUsageIf.class, keyUsage.digitalSignature());
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature);
x509 = PkiTestUtils.generateCertificate(keyPair.getPublic(), subjectDN
, notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage);

Loading…
Cancel
Save