123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ==================================================================== */
- package org.apache.poi.poifs.crypt;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.StringWriter;
- import java.math.BigInteger;
- import java.security.KeyPair;
- import java.security.KeyPairGenerator;
- import java.security.PrivateKey;
- import java.security.PublicKey;
- import java.security.SecureRandom;
- import java.security.cert.CRLException;
- import java.security.cert.CertificateEncodingException;
- import java.security.cert.CertificateException;
- import java.security.cert.X509CRL;
- import java.security.cert.X509Certificate;
- import java.security.interfaces.RSAPublicKey;
- import java.security.spec.RSAKeyGenParameterSpec;
- import java.util.Date;
-
- import javax.xml.parsers.DocumentBuilder;
- import javax.xml.parsers.DocumentBuilderFactory;
- import javax.xml.parsers.ParserConfigurationException;
- import javax.xml.transform.OutputKeys;
- import javax.xml.transform.Result;
- import javax.xml.transform.Source;
- import javax.xml.transform.Transformer;
- import javax.xml.transform.TransformerException;
- import javax.xml.transform.TransformerFactory;
- import javax.xml.transform.dom.DOMSource;
- import javax.xml.transform.stream.StreamResult;
-
- 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.X509ExtensionUtils;
- 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.crypto.params.RSAKeyParameters;
- import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
- 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;
- import org.xml.sax.SAXException;
-
- public class PkiTestUtils {
-
- private PkiTestUtils() {
- super();
- }
-
- static KeyPair generateKeyPair() throws Exception {
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
- SecureRandom random = new SecureRandom();
- keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024,
- RSAKeyGenParameterSpec.F4), random);
- return keyPairGenerator.generateKeyPair();
- }
-
- static X509Certificate generateCertificate(PublicKey subjectPublicKey,
- String subjectDn, Date notBefore, Date notAfter,
- X509Certificate issuerCertificate, PrivateKey issuerPrivateKey,
- boolean caFlag, int pathLength, String crlUri, String ocspUri,
- KeyUsage keyUsage)
- throws IOException, OperatorCreationException, CertificateException
- {
- String signatureAlgorithm = "SHA1withRSA";
- X500Name issuerName;
- if (issuerCertificate != null) {
- issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer();
- } else {
- issuerName = new X500Name(subjectDn);
- }
-
- RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey;
- RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent());
-
- SubjectPublicKeyInfo subjectPublicKeyInfo =
- SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec);
-
- DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
- .setProvider("BC").build().get(CertificateID.HASH_SHA1);
-
- X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder(
- issuerName
- , new BigInteger(128, new SecureRandom())
- , notBefore
- , notAfter
- , new X500Name(subjectDn)
- , subjectPublicKeyInfo
- );
-
- X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc);
- SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo);
- AuthorityKeyIdentifier autKeyId = (issuerCertificate != null)
- ? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded()))
- : exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
-
- certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId);
- certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId);
-
- if (caFlag) {
- BasicConstraints bc;
-
- if (-1 == pathLength) {
- bc = new BasicConstraints(true);
- } else {
- bc = new BasicConstraints(pathLength);
- }
- certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
- }
-
- if (null != crlUri) {
- int uri = GeneralName.uniformResourceIdentifier;
- DERIA5String crlUriDer = new DERIA5String(crlUri);
- GeneralName gn = new GeneralName(uri, crlUriDer);
-
- DERSequence gnDer = new DERSequence(gn);
- GeneralNames gns = GeneralNames.getInstance(gnDer);
-
- 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) {
- int uri = GeneralName.uniformResourceIdentifier;
- GeneralName ocspName = new GeneralName(uri, ocspUri);
-
- AuthorityInformationAccess authorityInformationAccess =
- new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
-
- certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess);
- }
-
- if (null != keyUsage) {
- certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
- }
-
- 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
- * certificate delivered to the caller is provided by the default
- * 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 new JcaX509CertificateConverter().getCertificate(certHolder);
- }
-
- static Document loadDocument(InputStream documentInputStream)
- throws ParserConfigurationException, SAXException, IOException {
- InputSource inputSource = new InputSource(documentInputStream);
- DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
- .newInstance();
- documentBuilderFactory.setNamespaceAware(true);
- DocumentBuilder documentBuilder = documentBuilderFactory
- .newDocumentBuilder();
- return documentBuilder.parse(inputSource);
- }
-
- static String toString(Node dom) throws TransformerException {
- Source source = new DOMSource(dom);
- StringWriter stringWriter = new StringWriter();
- Result result = new StreamResult(stringWriter);
- TransformerFactory transformerFactory = TransformerFactory
- .newInstance();
- Transformer transformer = transformerFactory.newTransformer();
- /*
- * We have to omit the ?xml declaration if we want to embed the
- * document.
- */
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
- transformer.transform(source, result);
- return stringWriter.getBuffer().toString();
- }
-
- 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");
-
- 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 OCSPResp createOcspResp(X509Certificate certificate,
- boolean revoked, X509Certificate issuerCertificate,
- X509Certificate ocspResponderCertificate,
- PrivateKey ocspResponderPrivateKey, String signatureAlgorithm,
- long nonceTimeinMillis)
- throws Exception {
- 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);
- DEROctetString nonceDer = new DEROctetString(nonce.toByteArray());
- Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer);
- Extensions exts = new Extensions(ext);
-
- OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
- ocspReqBuilder.addRequest(certId);
- ocspReqBuilder.setRequestExtensions(exts);
- OCSPReq ocspReq = ocspReqBuilder.build();
-
-
- SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo
- (CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded());
-
- BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc);
- basicOCSPRespBuilder.setResponseExtensions(exts);
-
- // request processing
- Req[] requestList = ocspReq.getRequestList();
- for (Req ocspRequest : requestList) {
- CertificateID certificateID = ocspRequest.getCertID();
- CertificateStatus certificateStatus = CertificateStatus.GOOD;
- if (revoked) {
- certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn);
- }
- basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
- }
-
- // basic response generation
- X509CertificateHolder[] chain = null;
- if (!ocspResponderCertificate.equals(issuerCertificate)) {
- // TODO: HorribleProxy can't convert array input params yet
- chain = new X509CertificateHolder[] {
- new X509CertificateHolder(ocspResponderCertificate.getEncoded()),
- issuerHolder
- };
- }
-
- ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA")
- .setProvider("BC").build(ocspResponderPrivateKey);
- BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
-
-
- OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
-
- return ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp);
- }
- }
|