1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.keystore.cts;
18 
19 import org.bouncycastle.asn1.x500.X500Name;
20 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
21 import org.bouncycastle.cert.X509CertificateHolder;
22 import org.bouncycastle.cert.X509v3CertificateBuilder;
23 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
24 import java.io.ByteArrayInputStream;
25 import java.math.BigInteger;
26 import java.security.KeyPair;
27 import java.security.SecureRandom;
28 import java.security.cert.CertificateFactory;
29 import java.security.cert.X509Certificate;
30 import java.util.Date;
31 import javax.security.auth.x500.X500Principal;
32 
33 public class CertificateUtils {
34     /** Creates a self-signed X.509 certificate, given a key pair, subject and issuer. */
createCertificate( KeyPair keyPair, X500Principal subject, X500Principal issuer)35     public static X509Certificate createCertificate(
36             KeyPair keyPair, X500Principal subject, X500Principal issuer) throws Exception {
37         // Make the certificate valid for two days.
38         long millisPerDay = 24 * 60 * 60 * 1000;
39         long now = System.currentTimeMillis();
40         Date start = new Date(now - millisPerDay);
41         Date end = new Date(now + millisPerDay);
42 
43         // Assign a random serial number.
44         byte[] serialBytes = new byte[16];
45         new SecureRandom().nextBytes(serialBytes);
46         BigInteger serialNumber = new BigInteger(1, serialBytes);
47 
48         // Create the certificate builder
49         X509v3CertificateBuilder x509cg =
50                 new X509v3CertificateBuilder(
51                         X500Name.getInstance(issuer.getEncoded()),
52                         serialNumber,
53                         start,
54                         end,
55                         X500Name.getInstance(subject.getEncoded()),
56                         SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
57 
58         // Choose a signature algorithm matching the key format.
59         String keyAlgorithm = keyPair.getPrivate().getAlgorithm();
60         String signatureAlgorithm;
61         if (keyAlgorithm.equals("RSA")) {
62             signatureAlgorithm = "SHA256withRSA";
63         } else if (keyAlgorithm.equals("EC")) {
64             signatureAlgorithm = "SHA256withECDSA";
65         } else {
66             throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm);
67         }
68 
69         // Sign the certificate and generate it.
70         X509CertificateHolder x509holder =
71                 x509cg.build(
72                         new JcaContentSignerBuilder(signatureAlgorithm)
73                                 .build(keyPair.getPrivate()));
74         CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
75         X509Certificate x509c =
76                 (X509Certificate)
77                         certFactory.generateCertificate(
78                                 new ByteArrayInputStream(x509holder.getEncoded()));
79         return x509c;
80     }
81 }
82