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