1 /* 2 * Copyright (c) 2015 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.Base64; 46 import java.util.Calendar; 47 import java.util.Date; 48 import java.util.TimeZone; 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 * @modules java.base/sun.security.x509 57 * java.base/sun.security.util 58 * @summary This test generates V3 certificate with all the supported 59 * extensions. Writes back the generated certificate in to a file and checks for 60 * equality with the original certificate. 61 */ 62 public class V3Certificate { 63 64 public static final String V3_FILE = "certV3"; 65 public static final String V3_B64_FILE = "certV3.b64"; 66 67 public static void main(String[] args) throws IOException, 68 NoSuchAlgorithmException, InvalidKeyException, CertificateException, 69 NoSuchProviderException, SignatureException { 70 71 boolean success = true; 72 73 success &= test("RSA", "SHA256withRSA", 2048); 74 success &= test("DSA", "SHA256withDSA", 2048); 75 success &= test("EC", "SHA256withECDSA", 384); 76 77 if (!success) { 78 throw new RuntimeException("At least one test case failed"); 79 } 80 } 81 82 public static boolean test(String algorithm, String sigAlg, int keyLength) 83 throws IOException, 84 NoSuchAlgorithmException, 85 InvalidKeyException, 86 CertificateException, 87 NoSuchProviderException, 88 SignatureException { 89 90 byte[] issuerId = {1, 2, 3, 4, 5}; 91 byte[] subjectId = {6, 7, 8, 9, 10}; 92 boolean testResult = true; 93 94 // Subject and Issuer 95 X500Name subject = new X500Name("test", "Oracle", "Santa Clara", 96 "US"); 97 X500Name issuer = subject; 98 99 // Generate keys and sign 100 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm); 101 keyGen.initialize(keyLength); 102 KeyPair pair = keyGen.generateKeyPair(); 103 PublicKey publicKey = pair.getPublic(); 104 PrivateKey privateKey = pair.getPrivate(); 105 MessageDigest md = MessageDigest.getInstance("SHA"); 106 byte[] keyId = md.digest(publicKey.getEncoded()); 107 108 Signature signature = Signature.getInstance(sigAlg); 109 signature.initSign(privateKey); 110 111 // Validity interval 112 Date firstDate = new Date(); 113 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("PST")); 114 cal.set(2014, 03, 10, 12, 30, 30); 115 Date lastDate = cal.getTime(); 116 CertificateValidity interval = new CertificateValidity(firstDate, 117 lastDate); 118 119 // Certificate Info 120 X509CertInfo cert = new X509CertInfo(); 121 122 cert.set(X509CertInfo.VERSION, 123 new CertificateVersion(CertificateVersion.V3)); 124 cert.set(X509CertInfo.SERIAL_NUMBER, 125 new CertificateSerialNumber((int) (firstDate.getTime() / 1000))); 126 cert.set(X509CertInfo.ALGORITHM_ID, 127 new CertificateAlgorithmId(AlgorithmId.get(sigAlg))); 128 cert.set(X509CertInfo.SUBJECT, subject); 129 cert.set(X509CertInfo.KEY, new CertificateX509Key(publicKey)); 130 cert.set(X509CertInfo.VALIDITY, interval); 131 cert.set(X509CertInfo.ISSUER, issuer); 132 133 cert.set(X509CertInfo.ISSUER_ID, 134 new UniqueIdentity( 135 new BitArray(issuerId.length * 8 - 2, issuerId))); 136 cert.set(X509CertInfo.SUBJECT_ID, new UniqueIdentity(subjectId)); 137 138 // Create Extensions 139 CertificateExtensions exts = new CertificateExtensions(); 140 141 GeneralNameInterface mailInf = new RFC822Name("test@Oracle.com"); 142 GeneralName mail = new GeneralName(mailInf); 143 GeneralNameInterface dnsInf = new DNSName("Oracle.com"); 144 GeneralName dns = new GeneralName(dnsInf); 145 GeneralNameInterface uriInf = new URIName("http://www.Oracle.com"); 146 GeneralName uri = new GeneralName(uriInf); 147 148 // localhost 149 byte[] address = new byte[]{127, 0, 0, 1}; 150 151 GeneralNameInterface ipInf = new IPAddressName(address); 152 GeneralName ip = new GeneralName(ipInf); 153 int[] oidData = new int[]{1, 2, 3, 4}; 154 155 GeneralNameInterface oidInf = new OIDName(new ObjectIdentifier(oidData)); 156 GeneralName oid = new GeneralName(oidInf); 157 158 SubjectAlternativeNameExtension subjectName 159 = new SubjectAlternativeNameExtension(); 160 IssuerAlternativeNameExtension issuerName 161 = new IssuerAlternativeNameExtension(); 162 163 GeneralNames subjectNames 164 = (GeneralNames) subjectName. 165 get(SubjectAlternativeNameExtension.SUBJECT_NAME); 166 167 GeneralNames issuerNames 168 = (GeneralNames) issuerName. 169 get(IssuerAlternativeNameExtension.ISSUER_NAME); 170 171 subjectNames.add(mail); 172 subjectNames.add(dns); 173 subjectNames.add(uri); 174 175 issuerNames.add(ip); 176 issuerNames.add(oid); 177 178 cal.set(2000, 11, 15, 12, 30, 30); 179 lastDate = cal.getTime(); 180 PrivateKeyUsageExtension pkusage 181 = new PrivateKeyUsageExtension(firstDate, lastDate); 182 183 KeyUsageExtension usage = new KeyUsageExtension(); 184 usage.set(KeyUsageExtension.CRL_SIGN, true); 185 usage.set(KeyUsageExtension.DIGITAL_SIGNATURE, true); 186 usage.set(KeyUsageExtension.NON_REPUDIATION, true); 187 188 KeyIdentifier kid = new KeyIdentifier(keyId); 189 SerialNumber sn = new SerialNumber(42); 190 AuthorityKeyIdentifierExtension aki 191 = new AuthorityKeyIdentifierExtension(kid, subjectNames, sn); 192 193 SubjectKeyIdentifierExtension ski 194 = new SubjectKeyIdentifierExtension(keyId); 195 196 BasicConstraintsExtension cons 197 = new BasicConstraintsExtension(true, 10); 198 199 PolicyConstraintsExtension pce = new PolicyConstraintsExtension(2, 4); 200 201 exts.set(SubjectAlternativeNameExtension.NAME, subjectName); 202 exts.set(IssuerAlternativeNameExtension.NAME, issuerName); 203 exts.set(PrivateKeyUsageExtension.NAME, pkusage); 204 exts.set(KeyUsageExtension.NAME, usage); 205 exts.set(AuthorityKeyIdentifierExtension.NAME, aki); 206 exts.set(SubjectKeyIdentifierExtension.NAME, ski); 207 exts.set(BasicConstraintsExtension.NAME, cons); 208 exts.set(PolicyConstraintsExtension.NAME, pce); 209 cert.set(X509CertInfo.EXTENSIONS, exts); 210 211 // Generate and sign X509CertImpl 212 X509CertImpl crt = new X509CertImpl(cert); 213 crt.sign(privateKey, sigAlg); 214 crt.verify(publicKey); 215 216 try (FileOutputStream fos = new FileOutputStream(new File(V3_FILE)); 217 FileOutputStream fos_b64 218 = new FileOutputStream(new File(V3_B64_FILE)); 219 PrintWriter pw = new PrintWriter(fos_b64)) { 220 crt.encode((OutputStream) fos); 221 fos.flush(); 222 223 // Certificate boundaries/ 224 pw.println("-----BEGIN CERTIFICATE-----"); 225 pw.flush(); 226 fos_b64.write(Base64.getMimeEncoder().encode(crt.getEncoded())); 227 fos_b64.flush(); 228 pw.println("-----END CERTIFICATE-----"); 229 } 230 231 out.println("*** Certificate ***"); 232 out.println(crt); 233 out.println("*** End Certificate ***"); 234 235 X509Certificate x2 = generateCertificate(V3_FILE); 236 if (!x2.equals(crt)) { 237 out.println("*** Certificate mismatch ***"); 238 testResult = false; 239 } 240 241 X509Certificate x3 = generateCertificate(V3_B64_FILE); 242 if (!x3.equals(crt)) { 243 out.println("*** Certificate mismatch ***"); 244 testResult = false; 245 } 246 247 return testResult; 248 } 249 250 static X509Certificate generateCertificate(String certFile) { 251 try (InputStream inStrm = new FileInputStream(certFile)) { 252 CertificateFactory cf = CertificateFactory.getInstance("X509"); 253 X509Certificate x2 254 = (X509Certificate) cf.generateCertificate(inStrm); 255 return x2; 256 } catch (CertificateException | IOException e) { 257 throw new RuntimeException("Exception while " 258 + "genrating certificate for " + certFile, e); 259 } 260 } 261 }