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 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. /*
  16. * Based on the eID Applet Project code.
  17. * Original Copyright (C) 2008-2009 FedICT.
  18. */
  19. package org.apache.poi.ooxml.signature.service.signer;
  20. import java.io.ByteArrayInputStream;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.StringWriter;
  24. import java.math.BigInteger;
  25. import java.security.InvalidKeyException;
  26. import java.security.KeyPair;
  27. import java.security.KeyPairGenerator;
  28. import java.security.NoSuchAlgorithmException;
  29. import java.security.PrivateKey;
  30. import java.security.PublicKey;
  31. import java.security.SecureRandom;
  32. import java.security.SignatureException;
  33. import java.security.cert.CertificateException;
  34. import java.security.cert.CertificateFactory;
  35. import java.security.cert.X509Certificate;
  36. import java.security.spec.RSAKeyGenParameterSpec;
  37. import java.util.Calendar;
  38. import java.util.Date;
  39. import javax.xml.parsers.DocumentBuilder;
  40. import javax.xml.parsers.DocumentBuilderFactory;
  41. import javax.xml.parsers.ParserConfigurationException;
  42. import javax.xml.transform.OutputKeys;
  43. import javax.xml.transform.Result;
  44. import javax.xml.transform.Source;
  45. import javax.xml.transform.Transformer;
  46. import javax.xml.transform.TransformerException;
  47. import javax.xml.transform.TransformerFactory;
  48. import javax.xml.transform.dom.DOMSource;
  49. import javax.xml.transform.stream.StreamResult;
  50. import org.apache.poi.util.HexRead;
  51. import org.bouncycastle.asn1.ASN1InputStream;
  52. import org.bouncycastle.asn1.ASN1Sequence;
  53. import org.bouncycastle.asn1.DERIA5String;
  54. import org.bouncycastle.asn1.DERSequence;
  55. import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
  56. import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
  57. import org.bouncycastle.asn1.x509.BasicConstraints;
  58. import org.bouncycastle.asn1.x509.DistributionPoint;
  59. import org.bouncycastle.asn1.x509.DistributionPointName;
  60. import org.bouncycastle.asn1.x509.GeneralName;
  61. import org.bouncycastle.asn1.x509.GeneralNames;
  62. import org.bouncycastle.asn1.x509.KeyUsage;
  63. import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
  64. import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
  65. import org.bouncycastle.asn1.x509.X509Extensions;
  66. import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
  67. import org.bouncycastle.jce.X509Principal;
  68. import org.bouncycastle.x509.X509V3CertificateGenerator;
  69. import org.w3c.dom.Document;
  70. import org.w3c.dom.Node;
  71. import org.xml.sax.InputSource;
  72. import org.xml.sax.SAXException;
  73. final class PkiTestUtils {
  74. public static final byte[] SHA1_DIGEST_INFO_PREFIX =
  75. HexRead.readFromString( "30 1f 30 07 06 05 2b 0e 03 02 1a 04 14");
  76. private PkiTestUtils() {
  77. // no instances of this class
  78. }
  79. static KeyPair generateKeyPair() throws Exception {
  80. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  81. SecureRandom random = new SecureRandom();
  82. keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024, RSAKeyGenParameterSpec.F4), random);
  83. KeyPair keyPair = keyPairGenerator.generateKeyPair();
  84. return keyPair;
  85. }
  86. private static SubjectKeyIdentifier createSubjectKeyId(PublicKey publicKey) throws IOException {
  87. ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
  88. SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(bais).readObject());
  89. return new SubjectKeyIdentifier(info);
  90. }
  91. private static AuthorityKeyIdentifier createAuthorityKeyId(PublicKey publicKey) throws IOException {
  92. ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
  93. SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(bais).readObject());
  94. return new AuthorityKeyIdentifier(info);
  95. }
  96. public static X509Certificate generateCertificate(PublicKey subjectPublicKey, String subjectDn,
  97. X509Certificate issuerCertificate, PrivateKey issuerPrivateKey, boolean caFlag, int pathLength, String crlUri,
  98. String ocspUri, KeyUsage keyUsage) throws IOException, InvalidKeyException, IllegalStateException,
  99. NoSuchAlgorithmException, SignatureException, CertificateException {
  100. Date notBefore = makeDate(2010, 1, 1);
  101. Date notAfter = makeDate(2011, 1, 1);
  102. String signatureAlgorithm = "SHA1withRSA";
  103. X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
  104. certificateGenerator.reset();
  105. certificateGenerator.setPublicKey(subjectPublicKey);
  106. certificateGenerator.setSignatureAlgorithm(signatureAlgorithm);
  107. certificateGenerator.setNotBefore(notBefore);
  108. certificateGenerator.setNotAfter(notAfter);
  109. X509Principal issuerDN;
  110. if (null != issuerCertificate) {
  111. issuerDN = new X509Principal(issuerCertificate.getSubjectX500Principal().toString());
  112. } else {
  113. issuerDN = new X509Principal(subjectDn);
  114. }
  115. certificateGenerator.setIssuerDN(issuerDN);
  116. certificateGenerator.setSubjectDN(new X509Principal(subjectDn));
  117. certificateGenerator.setSerialNumber(new BigInteger(128, new SecureRandom()));
  118. certificateGenerator.addExtension(X509Extensions.SubjectKeyIdentifier, false, createSubjectKeyId(subjectPublicKey));
  119. PublicKey issuerPublicKey;
  120. issuerPublicKey = subjectPublicKey;
  121. certificateGenerator.addExtension(X509Extensions.AuthorityKeyIdentifier, false, createAuthorityKeyId(issuerPublicKey));
  122. if (caFlag) {
  123. if (-1 == pathLength) {
  124. certificateGenerator.addExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(true));
  125. } else {
  126. certificateGenerator.addExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(pathLength));
  127. }
  128. }
  129. if (null != crlUri) {
  130. GeneralName gn = new GeneralName(GeneralName.uniformResourceIdentifier, new DERIA5String(crlUri));
  131. GeneralNames gns = new GeneralNames(new DERSequence(gn));
  132. DistributionPointName dpn = new DistributionPointName(0, gns);
  133. DistributionPoint distp = new DistributionPoint(dpn, null, null);
  134. certificateGenerator.addExtension(X509Extensions.CRLDistributionPoints, false, new DERSequence(distp));
  135. }
  136. if (null != ocspUri) {
  137. GeneralName ocspName = new GeneralName(GeneralName.uniformResourceIdentifier, ocspUri);
  138. AuthorityInformationAccess authorityInformationAccess = new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
  139. certificateGenerator.addExtension(X509Extensions.AuthorityInfoAccess.getId(), false, authorityInformationAccess);
  140. }
  141. if (null != keyUsage) {
  142. certificateGenerator.addExtension(X509Extensions.KeyUsage, true, keyUsage);
  143. }
  144. X509Certificate certificate;
  145. certificate = certificateGenerator.generate(issuerPrivateKey);
  146. /*
  147. * Next certificate factory trick is needed to make sure that the
  148. * certificate delivered to the caller is provided by the default
  149. * security provider instead of BouncyCastle. If we don't do this trick
  150. * we might run into trouble when trying to use the CertPath validator.
  151. */
  152. CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
  153. certificate = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certificate.getEncoded()));
  154. return certificate;
  155. }
  156. private static Date makeDate(int year, int month, int day) {
  157. Calendar c = Calendar.getInstance();
  158. c.set(year, month, day, 0, 0, 0);
  159. c.set(Calendar.MILLISECOND, 0);
  160. return c.getTime();
  161. }
  162. static Document loadDocument(InputStream documentInputStream) throws ParserConfigurationException, SAXException, IOException {
  163. InputSource inputSource = new InputSource(documentInputStream);
  164. DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  165. documentBuilderFactory.setNamespaceAware(true);
  166. DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
  167. Document document = documentBuilder.parse(inputSource);
  168. return document;
  169. }
  170. static String toString(Node dom) throws TransformerException {
  171. Source source = new DOMSource(dom);
  172. StringWriter stringWriter = new StringWriter();
  173. Result result = new StreamResult(stringWriter);
  174. TransformerFactory transformerFactory = TransformerFactory.newInstance();
  175. Transformer transformer = transformerFactory.newTransformer();
  176. /*
  177. * We have to omit the ?xml declaration if we want to embed the
  178. * document.
  179. */
  180. transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
  181. transformer.transform(source, result);
  182. return stringWriter.getBuffer().toString();
  183. }
  184. }