2 * //******************************************************************
4 * // Copyright 2016 Samsung Electronics All Rights Reserved.
6 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8 * // Licensed under the Apache License, Version 2.0 (the "License");
9 * // you may not use this file except in compliance with the License.
10 * // You may obtain a copy of the License at
12 * // http://www.apache.org/licenses/LICENSE-2.0
14 * // Unless required by applicable law or agreed to in writing, software
15 * // distributed under the License is distributed on an "AS IS" BASIS,
16 * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * // See the License for the specific language governing permissions and
18 * // limitations under the License.
20 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 package org.iotivity.cloud.accountserver.x509.cert;
24 import java.math.BigInteger;
25 import java.security.GeneralSecurityException;
26 import java.security.KeyPair;
27 import java.security.KeyPairGenerator;
28 import java.security.PrivateKey;
29 import java.security.PublicKey;
30 import java.security.SecureRandom;
31 import java.security.Security;
32 import java.security.cert.X509Certificate;
33 import java.util.Date;
35 import org.bouncycastle.asn1.DEROctetString;
36 import org.bouncycastle.asn1.x500.RDN;
37 import org.bouncycastle.asn1.x500.X500Name;
38 import org.bouncycastle.asn1.x500.X500NameBuilder;
39 import org.bouncycastle.asn1.x500.style.BCStyle;
40 import org.bouncycastle.asn1.x500.style.IETFUtils;
41 import org.bouncycastle.asn1.x509.Extension;
42 import org.bouncycastle.cert.CertIOException;
43 import org.bouncycastle.cert.X509v3CertificateBuilder;
44 import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
45 import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
46 import org.bouncycastle.jce.ECNamedCurveTable;
47 import org.bouncycastle.jce.provider.BouncyCastleProvider;
48 import org.bouncycastle.jce.spec.ECParameterSpec;
49 import org.bouncycastle.operator.ContentSigner;
50 import org.bouncycastle.operator.OperatorCreationException;
51 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
53 public class CertificateBuilder {
54 private String issuer;
55 private String subjectCN;
56 private String subjectC;
57 private String subjectO;
58 private String subjectOU;
59 private String subjectAltName;
60 private Date notBefore;
61 private Date notAfter;
62 private PrivateKey privKey;
63 private PublicKey pubKey;
64 private BigInteger serial;
65 private static final String SIGNATURE_ALGORITHM = "SHA256withECDSA";
66 private static final String CURVE = "secp256r1";
67 private static final String KEY_GENERATOR_ALGORITHM = "ECDSA";
69 public CertificateBuilder(String subject, Date notBefore, Date notAfter,
71 Security.addProvider(new BouncyCastleProvider());
72 init(subject, null, notBefore, notAfter, null, null, serial);
75 public CertificateBuilder(String subject, PublicKey pubKey, Date notBefore,
76 Date notAfter, BigInteger serial, CertificatePrivateKeyPair root) {
77 X500Name x500name = new X500Name(
78 root.getCertificate().getSubjectX500Principal().getName());
79 RDN cn = x500name.getRDNs(BCStyle.CN)[0];
80 init(subject, IETFUtils.valueToString(cn.getFirst().getValue()),
81 notBefore, notAfter, root.getKey(), pubKey, serial);
84 public CertificateBuilder(String subject, String issuer, Date notBefore,
85 Date notAfter, PrivateKey privKey, PublicKey pubKey,
87 Security.addProvider(new BouncyCastleProvider());
88 init(subject, issuer, notBefore, notAfter, privKey, pubKey, serial);
91 private void init(String subject, String issuer, Date notBefore,
92 Date notAfter, PrivateKey privKey, PublicKey pubKey,
94 this.subjectCN = subject;
96 this.notBefore = notBefore;
97 this.notAfter = notAfter;
98 this.privKey = privKey;
100 this.serial = serial;
103 public void setSubjectC(String subjectC) {
104 this.subjectC = subjectC;
107 public void setSubjectO(String subjectO) {
108 this.subjectO = subjectO;
111 public void setSubjectOU(String subjectOU) {
112 this.subjectOU = subjectOU;
115 public void setSubjectAltName(String subjectAltName) {
116 this.subjectAltName = subjectAltName;
119 public CertificatePrivateKeyPair build() throws GeneralSecurityException,
120 OperatorCreationException, CertIOException {
121 if (null == privKey && null == pubKey) {
122 ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE);
123 KeyPairGenerator g = null;
125 g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, "BC");
126 g.initialize(ecSpec, new SecureRandom());
128 KeyPair pair = g.generateKeyPair();
129 privKey = pair.getPrivate();
130 pubKey = pair.getPublic();
134 X509Certificate cert = null;
135 X500NameBuilder subjectNameBld = new X500NameBuilder(BCStyle.INSTANCE);
137 subjectNameBld.addRDN(BCStyle.CN, subjectCN);
139 if (null != subjectOU) {
140 subjectNameBld.addRDN(BCStyle.OU, subjectOU);
143 if (null != subjectO) {
144 subjectNameBld.addRDN(BCStyle.O, subjectO);
147 if (null != subjectC) {
148 subjectNameBld.addRDN(BCStyle.C, subjectC);
151 X500NameBuilder issuerNameBld = new X500NameBuilder(BCStyle.INSTANCE);
152 issuerNameBld.addRDN(BCStyle.CN, issuer);
154 ContentSigner sigGen = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM)
155 .setProvider("BC").build(privKey);
157 X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
158 issuerNameBld.build(), serial, notBefore, notAfter,
159 subjectNameBld.build(), pubKey);
161 if (null != subjectAltName) {
162 certGen.addExtension(Extension.subjectAlternativeName, false,
163 new DEROctetString(subjectAltName.getBytes()));
166 cert = new JcaX509CertificateConverter().setProvider("BC")
167 .getCertificate(certGen.build(sigGen));
169 return new CertificatePrivateKeyPair(cert, privKey);