Added CRL issuer (move from x.509 to x509 folder and restructure)
[platform/upstream/iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / x509 / cert / CertificateBuilder.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
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
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
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.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.accountserver.x509.cert;
23
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;
34
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;
52
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";
68
69     public CertificateBuilder(String subject, Date notBefore, Date notAfter,
70             BigInteger serial) {
71         Security.addProvider(new BouncyCastleProvider());
72         init(subject, null, notBefore, notAfter, null, null, serial);
73     }
74
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);
82     }
83
84     public CertificateBuilder(String subject, String issuer, Date notBefore,
85             Date notAfter, PrivateKey privKey, PublicKey pubKey,
86             BigInteger serial) {
87         Security.addProvider(new BouncyCastleProvider());
88         init(subject, issuer, notBefore, notAfter, privKey, pubKey, serial);
89     }
90
91     private void init(String subject, String issuer, Date notBefore,
92             Date notAfter, PrivateKey privKey, PublicKey pubKey,
93             BigInteger serial) {
94         this.subjectCN = subject;
95         this.issuer = issuer;
96         this.notBefore = notBefore;
97         this.notAfter = notAfter;
98         this.privKey = privKey;
99         this.pubKey = pubKey;
100         this.serial = serial;
101     }
102
103     public void setSubjectC(String subjectC) {
104         this.subjectC = subjectC;
105     }
106
107     public void setSubjectO(String subjectO) {
108         this.subjectO = subjectO;
109     }
110
111     public void setSubjectOU(String subjectOU) {
112         this.subjectOU = subjectOU;
113     }
114
115     public void setSubjectAltName(String subjectAltName) {
116         this.subjectAltName = subjectAltName;
117     }
118
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;
124
125             g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, "BC");
126             g.initialize(ecSpec, new SecureRandom());
127
128             KeyPair pair = g.generateKeyPair();
129             privKey = pair.getPrivate();
130             pubKey = pair.getPublic();
131             issuer = subjectCN;
132         }
133
134         X509Certificate cert = null;
135         X500NameBuilder subjectNameBld = new X500NameBuilder(BCStyle.INSTANCE);
136
137         subjectNameBld.addRDN(BCStyle.CN, subjectCN);
138
139         if (null != subjectOU) {
140             subjectNameBld.addRDN(BCStyle.OU, subjectOU);
141         }
142
143         if (null != subjectO) {
144             subjectNameBld.addRDN(BCStyle.O, subjectO);
145         }
146
147         if (null != subjectC) {
148             subjectNameBld.addRDN(BCStyle.C, subjectC);
149         }
150
151         X500NameBuilder issuerNameBld = new X500NameBuilder(BCStyle.INSTANCE);
152         issuerNameBld.addRDN(BCStyle.CN, issuer);
153
154         ContentSigner sigGen = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM)
155                 .setProvider("BC").build(privKey);
156
157         X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
158                 issuerNameBld.build(), serial, notBefore, notAfter,
159                 subjectNameBld.build(), pubKey);
160
161         if (null != subjectAltName) {
162             certGen.addExtension(Extension.subjectAlternativeName, false,
163                     new DEROctetString(subjectAltName.getBytes()));
164         }
165
166         cert = new JcaX509CertificateConverter().setProvider("BC")
167                 .getCertificate(certGen.build(sigGen));
168
169         return new CertificatePrivateKeyPair(cert, privKey);
170     }
171
172 }