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-ffa450edef68pull/11/head
@@ -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> |
@@ -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> | |||
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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; | |||
} |
@@ -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); |