You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PkiTestUtils.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.poifs.crypt;
  16. import java.io.IOException;
  17. import java.io.InputStream;
  18. import java.io.StringWriter;
  19. import java.math.BigInteger;
  20. import java.security.KeyPair;
  21. import java.security.KeyPairGenerator;
  22. import java.security.PrivateKey;
  23. import java.security.PublicKey;
  24. import java.security.SecureRandom;
  25. import java.security.cert.CRLException;
  26. import java.security.cert.CertificateEncodingException;
  27. import java.security.cert.CertificateException;
  28. import java.security.cert.X509CRL;
  29. import java.security.cert.X509Certificate;
  30. import java.security.interfaces.RSAPublicKey;
  31. import java.security.spec.RSAKeyGenParameterSpec;
  32. import java.util.Date;
  33. import javax.xml.parsers.DocumentBuilder;
  34. import javax.xml.parsers.DocumentBuilderFactory;
  35. import javax.xml.parsers.ParserConfigurationException;
  36. import javax.xml.transform.OutputKeys;
  37. import javax.xml.transform.Result;
  38. import javax.xml.transform.Source;
  39. import javax.xml.transform.Transformer;
  40. import javax.xml.transform.TransformerException;
  41. import javax.xml.transform.TransformerFactory;
  42. import javax.xml.transform.dom.DOMSource;
  43. import javax.xml.transform.stream.StreamResult;
  44. import org.bouncycastle.asn1.DERIA5String;
  45. import org.bouncycastle.asn1.DEROctetString;
  46. import org.bouncycastle.asn1.DERSequence;
  47. import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
  48. import org.bouncycastle.asn1.x500.X500Name;
  49. import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
  50. import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
  51. import org.bouncycastle.asn1.x509.BasicConstraints;
  52. import org.bouncycastle.asn1.x509.CRLNumber;
  53. import org.bouncycastle.asn1.x509.CRLReason;
  54. import org.bouncycastle.asn1.x509.DistributionPoint;
  55. import org.bouncycastle.asn1.x509.DistributionPointName;
  56. import org.bouncycastle.asn1.x509.Extension;
  57. import org.bouncycastle.asn1.x509.Extensions;
  58. import org.bouncycastle.asn1.x509.GeneralName;
  59. import org.bouncycastle.asn1.x509.GeneralNames;
  60. import org.bouncycastle.asn1.x509.KeyUsage;
  61. import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
  62. import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
  63. import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
  64. import org.bouncycastle.cert.X509CRLHolder;
  65. import org.bouncycastle.cert.X509CertificateHolder;
  66. import org.bouncycastle.cert.X509ExtensionUtils;
  67. import org.bouncycastle.cert.X509v2CRLBuilder;
  68. import org.bouncycastle.cert.X509v3CertificateBuilder;
  69. import org.bouncycastle.cert.jcajce.JcaX509CRLConverter;
  70. import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
  71. import org.bouncycastle.cert.ocsp.BasicOCSPResp;
  72. import org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
  73. import org.bouncycastle.cert.ocsp.CertificateID;
  74. import org.bouncycastle.cert.ocsp.CertificateStatus;
  75. import org.bouncycastle.cert.ocsp.OCSPReq;
  76. import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
  77. import org.bouncycastle.cert.ocsp.OCSPResp;
  78. import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
  79. import org.bouncycastle.cert.ocsp.Req;
  80. import org.bouncycastle.cert.ocsp.RevokedStatus;
  81. import org.bouncycastle.crypto.params.RSAKeyParameters;
  82. import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
  83. import org.bouncycastle.operator.ContentSigner;
  84. import org.bouncycastle.operator.DigestCalculator;
  85. import org.bouncycastle.operator.OperatorCreationException;
  86. import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
  87. import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
  88. import org.w3c.dom.Document;
  89. import org.w3c.dom.Node;
  90. import org.xml.sax.InputSource;
  91. import org.xml.sax.SAXException;
  92. public class PkiTestUtils {
  93. private PkiTestUtils() {
  94. super();
  95. }
  96. static KeyPair generateKeyPair() throws Exception {
  97. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  98. SecureRandom random = new SecureRandom();
  99. keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024,
  100. RSAKeyGenParameterSpec.F4), random);
  101. return keyPairGenerator.generateKeyPair();
  102. }
  103. static X509Certificate generateCertificate(PublicKey subjectPublicKey,
  104. String subjectDn, Date notBefore, Date notAfter,
  105. X509Certificate issuerCertificate, PrivateKey issuerPrivateKey,
  106. boolean caFlag, int pathLength, String crlUri, String ocspUri,
  107. KeyUsage keyUsage)
  108. throws IOException, OperatorCreationException, CertificateException
  109. {
  110. String signatureAlgorithm = "SHA1withRSA";
  111. X500Name issuerName;
  112. if (issuerCertificate != null) {
  113. issuerName = new X509CertificateHolder(issuerCertificate.getEncoded()).getIssuer();
  114. } else {
  115. issuerName = new X500Name(subjectDn);
  116. }
  117. RSAPublicKey rsaPubKey = (RSAPublicKey)subjectPublicKey;
  118. RSAKeyParameters rsaSpec = new RSAKeyParameters(false, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent());
  119. SubjectPublicKeyInfo subjectPublicKeyInfo =
  120. SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(rsaSpec);
  121. DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
  122. .setProvider("BC").build().get(CertificateID.HASH_SHA1);
  123. X509v3CertificateBuilder certificateGenerator = new X509v3CertificateBuilder(
  124. issuerName
  125. , new BigInteger(128, new SecureRandom())
  126. , notBefore
  127. , notAfter
  128. , new X500Name(subjectDn)
  129. , subjectPublicKeyInfo
  130. );
  131. X509ExtensionUtils exUtils = new X509ExtensionUtils(digestCalc);
  132. SubjectKeyIdentifier subKeyId = exUtils.createSubjectKeyIdentifier(subjectPublicKeyInfo);
  133. AuthorityKeyIdentifier autKeyId = (issuerCertificate != null)
  134. ? exUtils.createAuthorityKeyIdentifier(new X509CertificateHolder(issuerCertificate.getEncoded()))
  135. : exUtils.createAuthorityKeyIdentifier(subjectPublicKeyInfo);
  136. certificateGenerator.addExtension(Extension.subjectKeyIdentifier, false, subKeyId);
  137. certificateGenerator.addExtension(Extension.authorityKeyIdentifier, false, autKeyId);
  138. if (caFlag) {
  139. BasicConstraints bc;
  140. if (-1 == pathLength) {
  141. bc = new BasicConstraints(true);
  142. } else {
  143. bc = new BasicConstraints(pathLength);
  144. }
  145. certificateGenerator.addExtension(Extension.basicConstraints, false, bc);
  146. }
  147. if (null != crlUri) {
  148. int uri = GeneralName.uniformResourceIdentifier;
  149. DERIA5String crlUriDer = new DERIA5String(crlUri);
  150. GeneralName gn = new GeneralName(uri, crlUriDer);
  151. DERSequence gnDer = new DERSequence(gn);
  152. GeneralNames gns = GeneralNames.getInstance(gnDer);
  153. DistributionPointName dpn = new DistributionPointName(0, gns);
  154. DistributionPoint distp = new DistributionPoint(dpn, null, null);
  155. DERSequence distpDer = new DERSequence(distp);
  156. certificateGenerator.addExtension(Extension.cRLDistributionPoints, false, distpDer);
  157. }
  158. if (null != ocspUri) {
  159. int uri = GeneralName.uniformResourceIdentifier;
  160. GeneralName ocspName = new GeneralName(uri, ocspUri);
  161. AuthorityInformationAccess authorityInformationAccess =
  162. new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
  163. certificateGenerator.addExtension(Extension.authorityInfoAccess, false, authorityInformationAccess);
  164. }
  165. if (null != keyUsage) {
  166. certificateGenerator.addExtension(Extension.keyUsage, true, keyUsage);
  167. }
  168. JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlgorithm);
  169. signerBuilder.setProvider("BC");
  170. X509CertificateHolder certHolder =
  171. certificateGenerator.build(signerBuilder.build(issuerPrivateKey));
  172. /*
  173. * Next certificate factory trick is needed to make sure that the
  174. * certificate delivered to the caller is provided by the default
  175. * security provider instead of BouncyCastle. If we don't do this trick
  176. * we might run into trouble when trying to use the CertPath validator.
  177. */
  178. // CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
  179. // certificate = (X509Certificate) certificateFactory
  180. // .generateCertificate(new ByteArrayInputStream(certificate
  181. // .getEncoded()));
  182. return new JcaX509CertificateConverter().getCertificate(certHolder);
  183. }
  184. static Document loadDocument(InputStream documentInputStream)
  185. throws ParserConfigurationException, SAXException, IOException {
  186. InputSource inputSource = new InputSource(documentInputStream);
  187. DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
  188. .newInstance();
  189. documentBuilderFactory.setNamespaceAware(true);
  190. DocumentBuilder documentBuilder = documentBuilderFactory
  191. .newDocumentBuilder();
  192. return documentBuilder.parse(inputSource);
  193. }
  194. static String toString(Node dom) throws TransformerException {
  195. Source source = new DOMSource(dom);
  196. StringWriter stringWriter = new StringWriter();
  197. Result result = new StreamResult(stringWriter);
  198. TransformerFactory transformerFactory = TransformerFactory
  199. .newInstance();
  200. Transformer transformer = transformerFactory.newTransformer();
  201. /*
  202. * We have to omit the ?xml declaration if we want to embed the
  203. * document.
  204. */
  205. transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
  206. transformer.transform(source, result);
  207. return stringWriter.getBuffer().toString();
  208. }
  209. public static X509CRL generateCrl(X509Certificate issuer, PrivateKey issuerPrivateKey)
  210. throws CertificateEncodingException, IOException, CRLException, OperatorCreationException {
  211. X509CertificateHolder holder = new X509CertificateHolder(issuer.getEncoded());
  212. X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(holder.getIssuer(), new Date());
  213. crlBuilder.setNextUpdate(new Date(new Date().getTime() + 100000));
  214. JcaContentSignerBuilder contentBuilder = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC");
  215. CRLNumber crlNumber = new CRLNumber(new BigInteger("1234"));
  216. crlBuilder.addExtension(Extension.cRLNumber, false, crlNumber);
  217. X509CRLHolder x509Crl = crlBuilder.build(contentBuilder.build(issuerPrivateKey));
  218. return new JcaX509CRLConverter().setProvider("BC").getCRL(x509Crl);
  219. }
  220. public static OCSPResp createOcspResp(X509Certificate certificate,
  221. boolean revoked, X509Certificate issuerCertificate,
  222. X509Certificate ocspResponderCertificate,
  223. PrivateKey ocspResponderPrivateKey, String signatureAlgorithm,
  224. long nonceTimeinMillis)
  225. throws Exception {
  226. DigestCalculator digestCalc = new JcaDigestCalculatorProviderBuilder()
  227. .setProvider("BC").build().get(CertificateID.HASH_SHA1);
  228. X509CertificateHolder issuerHolder = new X509CertificateHolder(issuerCertificate.getEncoded());
  229. CertificateID certId = new CertificateID(digestCalc, issuerHolder, certificate.getSerialNumber());
  230. // request
  231. //create a nonce to avoid replay attack
  232. BigInteger nonce = BigInteger.valueOf(nonceTimeinMillis);
  233. DEROctetString nonceDer = new DEROctetString(nonce.toByteArray());
  234. Extension ext = new Extension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, true, nonceDer);
  235. Extensions exts = new Extensions(ext);
  236. OCSPReqBuilder ocspReqBuilder = new OCSPReqBuilder();
  237. ocspReqBuilder.addRequest(certId);
  238. ocspReqBuilder.setRequestExtensions(exts);
  239. OCSPReq ocspReq = ocspReqBuilder.build();
  240. SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo
  241. (CertificateID.HASH_SHA1, ocspResponderCertificate.getPublicKey().getEncoded());
  242. BasicOCSPRespBuilder basicOCSPRespBuilder = new BasicOCSPRespBuilder(keyInfo, digestCalc);
  243. basicOCSPRespBuilder.setResponseExtensions(exts);
  244. // request processing
  245. Req[] requestList = ocspReq.getRequestList();
  246. for (Req ocspRequest : requestList) {
  247. CertificateID certificateID = ocspRequest.getCertID();
  248. CertificateStatus certificateStatus = CertificateStatus.GOOD;
  249. if (revoked) {
  250. certificateStatus = new RevokedStatus(new Date(), CRLReason.privilegeWithdrawn);
  251. }
  252. basicOCSPRespBuilder.addResponse(certificateID, certificateStatus);
  253. }
  254. // basic response generation
  255. X509CertificateHolder[] chain = null;
  256. if (!ocspResponderCertificate.equals(issuerCertificate)) {
  257. // TODO: HorribleProxy can't convert array input params yet
  258. chain = new X509CertificateHolder[] {
  259. new X509CertificateHolder(ocspResponderCertificate.getEncoded()),
  260. issuerHolder
  261. };
  262. }
  263. ContentSigner contentSigner = new JcaContentSignerBuilder("SHA1withRSA")
  264. .setProvider("BC").build(ocspResponderPrivateKey);
  265. BasicOCSPResp basicOCSPResp = basicOCSPRespBuilder.build(contentSigner, chain, new Date(nonceTimeinMillis));
  266. OCSPRespBuilder ocspRespBuilder = new OCSPRespBuilder();
  267. return ocspRespBuilder.build(OCSPRespBuilder.SUCCESSFUL, basicOCSPResp);
  268. }
  269. }