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
This commit is contained in:
Andreas Beeker 2014-08-24 23:05:26 +00:00
parent 8962fa8310
commit d0cc2e4267
7 changed files with 275 additions and 942 deletions

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>

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>

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();
}
}

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;
}
}

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,20 +54,25 @@ 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,15 +235,30 @@ 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) {
@ -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);
}

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 {
X509ExtensionsIf X509Extensions = newProxy(X509ExtensionsIf.class);
CRLNumberIf crlNumber = newProxy(CRLNumberIf.class, new BigInteger("1234"));
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");
crlGenerator.addExtension(X509Extensions.CRLNumber(), false, crlNumber);
X509CRL x509Crl = crlGenerator.generate(issuerPrivateKey);
return x509Crl;
CRLNumber crlNumber = new CRLNumber(new BigInteger("1234"));
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;
}

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 = new TSPTimeStampService(tspServiceUrl, tspValidator);
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 = 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);