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