1 /* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.File; 25 import java.io.FileInputStream; 26 import java.io.FileOutputStream; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.OutputStream; 30 import java.io.PrintWriter; 31 import static java.lang.System.out; 32 import java.security.InvalidKeyException; 33 import java.security.KeyPair; 34 import java.security.KeyPairGenerator; 35 import java.security.MessageDigest; 36 import java.security.NoSuchAlgorithmException; 37 import java.security.NoSuchProviderException; 38 import java.security.PrivateKey; 39 import java.security.PublicKey; 40 import java.security.Signature; 41 import java.security.SignatureException; 42 import java.security.cert.CertificateException; 43 import java.security.cert.CertificateFactory; 44 import java.security.cert.X509Certificate; 45 import java.util.Calendar; 46 import java.util.Date; 47 import java.util.TimeZone; 48 import sun.misc.BASE64Encoder; 49 import sun.security.util.BitArray; 50 import sun.security.util.ObjectIdentifier; 51 import sun.security.x509.*; 52 53 /** 54 * @test 55 * @bug 8049237 56 * @summary This test generates V3 certificate with all the supported 57 * extensions. Writes back the generated certificate in to a file and checks for 58 * equality with the original certificate. 59 */ 60 public class V3Certificate { 61 62 public static final String V3_FILE = "certV3"; 63 public static final String V3_B64_FILE = "certV3.b64"; 64 main(String[] args)65 public static void main(String[] args) throws IOException, 66 NoSuchAlgorithmException, InvalidKeyException, CertificateException, 67 NoSuchProviderException, SignatureException { 68 69 boolean success = true; 70 71 success &= test("RSA", "SHA256withRSA", 2048); 72 success &= test("DSA", "SHA256withDSA", 2048); 73 success &= test("EC", "SHA256withECDSA", 384); 74 75 if (!success) { 76 throw new RuntimeException("At least one test case failed"); 77 } 78 } 79 test(String algorithm, String sigAlg, int keyLength)80 public static boolean test(String algorithm, String sigAlg, int keyLength) 81 throws IOException, 82 NoSuchAlgorithmException, 83 InvalidKeyException, 84 CertificateException, 85 NoSuchProviderException, 86 SignatureException { 87 88 byte[] issuerId = {1, 2, 3, 4, 5}; 89 byte[] subjectId = {6, 7, 8, 9, 10}; 90 boolean testResult = true; 91 92 // Subject and Issuer 93 X500Name subject = new X500Name("test", "Oracle", "Santa Clara", 94 "US"); 95 X500Name issuer = subject; 96 97 // Generate keys and sign 98 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm); 99 keyGen.initialize(keyLength); 100 KeyPair pair = keyGen.generateKeyPair(); 101 PublicKey publicKey = pair.getPublic(); 102 PrivateKey privateKey = pair.getPrivate(); 103 MessageDigest md = MessageDigest.getInstance("SHA"); 104 byte[] keyId = md.digest(publicKey.getEncoded()); 105 106 Signature signature = Signature.getInstance(sigAlg); 107 signature.initSign(privateKey); 108 109 // Validity interval 110 Date firstDate = new Date(); 111 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); 112 cal.set(2014, 03, 10, 12, 30, 30); 113 Date lastDate = cal.getTime(); 114 CertificateValidity interval = new CertificateValidity(firstDate, 115 lastDate); 116 117 // Certificate Info 118 X509CertInfo cert = new X509CertInfo(); 119 120 cert.set(X509CertInfo.VERSION, 121 new CertificateVersion(CertificateVersion.V3)); 122 cert.set(X509CertInfo.SERIAL_NUMBER, 123 new CertificateSerialNumber((int) (firstDate.getTime() / 1000))); 124 cert.set(X509CertInfo.ALGORITHM_ID, 125 new CertificateAlgorithmId(AlgorithmId.get(sigAlg))); 126 cert.set(X509CertInfo.SUBJECT, subject); 127 cert.set(X509CertInfo.KEY, new CertificateX509Key(publicKey)); 128 cert.set(X509CertInfo.VALIDITY, interval); 129 cert.set(X509CertInfo.ISSUER, issuer); 130 131 cert.set(X509CertInfo.ISSUER_ID, 132 new UniqueIdentity( 133 new BitArray(issuerId.length * 8 - 2, issuerId))); 134 cert.set(X509CertInfo.SUBJECT_ID, new UniqueIdentity(subjectId)); 135 136 // Create Extensions 137 CertificateExtensions exts = new CertificateExtensions(); 138 139 GeneralNameInterface mailInf = new RFC822Name("test@Oracle.com"); 140 GeneralName mail = new GeneralName(mailInf); 141 GeneralNameInterface dnsInf = new DNSName("Oracle.com"); 142 GeneralName dns = new GeneralName(dnsInf); 143 GeneralNameInterface uriInf = new URIName("http://www.Oracle.com"); 144 GeneralName uri = new GeneralName(uriInf); 145 146 // localhost 147 byte[] address = new byte[]{127, 0, 0, 1}; 148 149 GeneralNameInterface ipInf = new IPAddressName(address); 150 GeneralName ip = new GeneralName(ipInf); 151 int[] oidData = new int[]{1, 2, 3, 4}; 152 153 GeneralNameInterface oidInf = new OIDName(new ObjectIdentifier(oidData)); 154 GeneralName oid = new GeneralName(oidInf); 155 156 SubjectAlternativeNameExtension subjectName 157 = new SubjectAlternativeNameExtension(); 158 IssuerAlternativeNameExtension issuerName 159 = new IssuerAlternativeNameExtension(); 160 161 GeneralNames subjectNames 162 = (GeneralNames) subjectName. 163 get(SubjectAlternativeNameExtension.SUBJECT_NAME); 164 165 GeneralNames issuerNames 166 = (GeneralNames) issuerName. 167 get(IssuerAlternativeNameExtension.ISSUER_NAME); 168 169 subjectNames.add(mail); 170 subjectNames.add(dns); 171 subjectNames.add(uri); 172 173 issuerNames.add(ip); 174 issuerNames.add(oid); 175 176 cal.set(2000, 11, 15, 12, 30, 30); 177 lastDate = cal.getTime(); 178 PrivateKeyUsageExtension pkusage 179 = new PrivateKeyUsageExtension(firstDate, lastDate); 180 181 KeyUsageExtension usage = new KeyUsageExtension(); 182 usage.set(KeyUsageExtension.CRL_SIGN, true); 183 usage.set(KeyUsageExtension.DIGITAL_SIGNATURE, true); 184 usage.set(KeyUsageExtension.NON_REPUDIATION, true); 185 186 KeyIdentifier kid = new KeyIdentifier(keyId); 187 SerialNumber sn = new SerialNumber(42); 188 AuthorityKeyIdentifierExtension aki 189 = new AuthorityKeyIdentifierExtension(kid, subjectNames, sn); 190 191 SubjectKeyIdentifierExtension ski 192 = new SubjectKeyIdentifierExtension(keyId); 193 194 BasicConstraintsExtension cons 195 = new BasicConstraintsExtension(true, 10); 196 197 PolicyConstraintsExtension pce = new PolicyConstraintsExtension(2, 4); 198 199 exts.set(SubjectAlternativeNameExtension.NAME, subjectName); 200 exts.set(IssuerAlternativeNameExtension.NAME, issuerName); 201 exts.set(PrivateKeyUsageExtension.NAME, pkusage); 202 exts.set(KeyUsageExtension.NAME, usage); 203 exts.set(AuthorityKeyIdentifierExtension.NAME, aki); 204 exts.set(SubjectKeyIdentifierExtension.NAME, ski); 205 exts.set(BasicConstraintsExtension.NAME, cons); 206 exts.set(PolicyConstraintsExtension.NAME, pce); 207 cert.set(X509CertInfo.EXTENSIONS, exts); 208 209 // Generate and sign X509CertImpl 210 X509CertImpl crt = new X509CertImpl(cert); 211 crt.sign(privateKey, sigAlg); 212 crt.verify(publicKey); 213 214 try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE)); 215 FileOutputStream fos_b64 216 = new FileOutputStream(new File(V3_B64_FILE)); 217 PrintWriter pw = new PrintWriter(fos_b64)) { 218 crt.encode((OutputStream) fos); 219 fos.flush(); 220 221 // Certificate boundaries/ 222 pw.println("-----BEGIN CERTIFICATE-----"); 223 pw.flush(); 224 new BASE64Encoder().encodeBuffer(crt.getEncoded(), fos_b64); 225 fos_b64.flush(); 226 pw.println("-----END CERTIFICATE-----"); 227 } 228 229 out.println("*** Certificate ***"); 230 out.println(crt); 231 out.println("*** End Certificate ***"); 232 233 X509Certificate x2 = generateCertificate(V3_FILE); 234 if (!x2.equals(crt)) { 235 out.println("*** Certificate mismatch ***"); 236 testResult = false; 237 } 238 239 X509Certificate x3 = generateCertificate(V3_B64_FILE); 240 if (!x3.equals(crt)) { 241 out.println("*** Certificate mismatch ***"); 242 testResult = false; 243 } 244 245 return testResult; 246 } 247 generateCertificate(String certFile)248 static X509Certificate generateCertificate(String certFile) { 249 try (InputStream inStrm = new FileInputStream(certFile)) { 250 CertificateFactory cf = CertificateFactory.getInstance("X509"); 251 X509Certificate x2 252 = (X509Certificate) cf.generateCertificate(inStrm); 253 return x2; 254 } catch (CertificateException | IOException e) { 255 throw new RuntimeException("Exception while " 256 + "genrating certificate for " + certFile, e); 257 } 258 } 259 } 260