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.security.x509;
23 import java.math.BigInteger;
24 import java.security.GeneralSecurityException;
25 import java.security.KeyPair;
26 import java.security.KeyPairGenerator;
27 import java.security.PrivateKey;
28 import java.security.PublicKey;
29 import java.security.SecureRandom;
30 import java.security.Security;
31 import java.security.cert.X509Certificate;
32 import java.util.Date;
34 import org.bouncycastle.asn1.DEROctetString;
35 import org.bouncycastle.asn1.x500.RDN;
36 import org.bouncycastle.asn1.x500.X500Name;
37 import org.bouncycastle.asn1.x500.X500NameBuilder;
38 import org.bouncycastle.asn1.x500.style.BCStyle;
39 import org.bouncycastle.asn1.x500.style.IETFUtils;
40 import org.bouncycastle.asn1.x509.Extension;
41 import org.bouncycastle.cert.CertIOException;
42 import org.bouncycastle.cert.X509v3CertificateBuilder;
43 import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
44 import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
45 import org.bouncycastle.jce.ECNamedCurveTable;
46 import org.bouncycastle.jce.provider.BouncyCastleProvider;
47 import org.bouncycastle.jce.spec.ECParameterSpec;
48 import org.bouncycastle.operator.ContentSigner;
49 import org.bouncycastle.operator.OperatorCreationException;
50 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
52 public class CertificateBuilder {
53 private String issuer;
54 private String subjectCN;
55 private String subjectC;
56 private String subjectO;
57 private String subjectOU;
58 private String subjectAltName;
59 private Date notBefore;
60 private Date notAfter;
61 private PrivateKey privKey;
62 private PublicKey pubKey;
63 private BigInteger serial;
64 private static final String SIGNATURE_ALGORITHM = "SHA256withECDSA";
65 private static final String CURVE = "secp256r1";
66 private static final String KEY_GENERATOR_ALGORITHM = "ECDSA";
68 public CertificateBuilder(String subject, Date notBefore, Date notAfter, BigInteger serial) {
69 Security.addProvider(new BouncyCastleProvider());
70 init(subject, null, notBefore, notAfter, null, null, serial);
73 public CertificateBuilder(String subject, PublicKey pubKey, Date notBefore, Date notAfter,
74 BigInteger serial, CertificatePrivateKeyPair root) {
75 X500Name x500name = new X500Name( root.getCertificate().getSubjectX500Principal().getName() );
76 RDN cn = x500name.getRDNs(BCStyle.CN)[0];
77 init(subject, IETFUtils.valueToString(cn.getFirst().getValue()), notBefore, notAfter, root.getKey(), pubKey, serial);
80 public CertificateBuilder(String subject, String issuer, Date notBefore, Date notAfter,
81 PrivateKey privKey, PublicKey pubKey, BigInteger serial) {
82 Security.addProvider(new BouncyCastleProvider());
83 init(subject, issuer, notBefore, notAfter, privKey, pubKey, serial);
86 private void init(String subject, String issuer, Date notBefore, Date notAfter,
87 PrivateKey privKey, PublicKey pubKey, BigInteger serial) {
88 this.subjectCN = subject;
90 this.notBefore = notBefore;
91 this.notAfter = notAfter;
92 this.privKey = privKey;
97 public void setSubjectC(String subjectC) {
98 this.subjectC = subjectC;
101 public void setSubjectO(String subjectO) {
102 this.subjectO = subjectO;
105 public void setSubjectOU(String subjectOU) {
106 this.subjectOU = subjectOU;
109 public void setSubjectAltName(String subjectAltName) {
110 this.subjectAltName = subjectAltName;
113 public CertificatePrivateKeyPair build()
114 throws GeneralSecurityException, OperatorCreationException, CertIOException {
115 if(null == privKey && null == pubKey)
117 ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE);
118 KeyPairGenerator g = null;
120 g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, "BC");
121 g.initialize(ecSpec, new SecureRandom());
123 KeyPair pair = g.generateKeyPair();
124 privKey = pair.getPrivate();
125 pubKey = pair.getPublic();
129 X509Certificate cert = null;
130 X500NameBuilder subjectNameBld = new X500NameBuilder(BCStyle.INSTANCE);
132 subjectNameBld.addRDN(BCStyle.CN, subjectCN);
134 if(null != subjectOU) {
135 subjectNameBld.addRDN(BCStyle.OU, subjectOU);
138 if(null != subjectO) {
139 subjectNameBld.addRDN(BCStyle.O, subjectO);
142 if(null != subjectC) {
143 subjectNameBld.addRDN(BCStyle.C, subjectC);
146 X500NameBuilder issuerNameBld = new X500NameBuilder(BCStyle.INSTANCE);
147 issuerNameBld.addRDN(BCStyle.CN, issuer);
149 ContentSigner sigGen = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider("BC").build(privKey);
151 X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(issuerNameBld.build(),
152 serial, notBefore, notAfter ,subjectNameBld.build(), pubKey);
154 if(null != subjectAltName) {
155 certGen.addExtension(Extension.subjectAlternativeName, false, new DEROctetString(subjectAltName.getBytes()));
158 cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
160 return new CertificatePrivateKeyPair(cert, privKey);