cb577d7cad67e1c85c99ccb98d41a7f9efc721a4
[platform/upstream/iotivity.git] / cloud / account / src / main / java / org / iotivity / cloud / accountserver / security / x509 / 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.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;
33
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;
51
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";
67
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);
71     }
72
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);
78     }
79
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);
84     }
85
86     private void init(String subject, String issuer, Date notBefore, Date notAfter,
87             PrivateKey privKey, PublicKey pubKey, BigInteger serial) {
88         this.subjectCN = subject;
89         this.issuer = issuer;
90         this.notBefore = notBefore;
91         this.notAfter = notAfter;
92         this.privKey = privKey;
93         this.pubKey = pubKey;
94         this.serial = serial;
95     }
96
97     public void setSubjectC(String subjectC) {
98         this.subjectC = subjectC;
99     }
100
101     public void setSubjectO(String subjectO) {
102         this.subjectO = subjectO;
103     }
104
105     public void setSubjectOU(String subjectOU) {
106         this.subjectOU = subjectOU;
107     }
108
109     public void setSubjectAltName(String subjectAltName) {
110         this.subjectAltName = subjectAltName;
111     }
112
113     public CertificatePrivateKeyPair build()
114             throws GeneralSecurityException, OperatorCreationException, CertIOException {
115         if(null == privKey && null == pubKey)
116         {
117             ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(CURVE);
118             KeyPairGenerator g = null;
119
120             g = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM, "BC");
121             g.initialize(ecSpec, new SecureRandom());
122
123             KeyPair pair = g.generateKeyPair();
124             privKey = pair.getPrivate();
125             pubKey = pair.getPublic();
126             issuer = subjectCN;
127         }
128
129         X509Certificate cert = null;
130         X500NameBuilder subjectNameBld = new X500NameBuilder(BCStyle.INSTANCE);
131
132         subjectNameBld.addRDN(BCStyle.CN, subjectCN);
133
134         if(null != subjectOU) {
135             subjectNameBld.addRDN(BCStyle.OU, subjectOU);
136         }
137
138         if(null != subjectO) {
139             subjectNameBld.addRDN(BCStyle.O, subjectO);
140         }
141
142         if(null != subjectC) {
143             subjectNameBld.addRDN(BCStyle.C, subjectC);
144         }
145
146         X500NameBuilder issuerNameBld = new X500NameBuilder(BCStyle.INSTANCE);
147         issuerNameBld.addRDN(BCStyle.CN, issuer);
148
149         ContentSigner sigGen = new JcaContentSignerBuilder(SIGNATURE_ALGORITHM).setProvider("BC").build(privKey);
150
151         X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(issuerNameBld.build(),
152                 serial, notBefore, notAfter ,subjectNameBld.build(), pubKey);
153
154         if(null != subjectAltName) {
155             certGen.addExtension(Extension.subjectAlternativeName, false, new DEROctetString(subjectAltName.getBytes()));
156         }
157
158         cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
159
160         return new CertificatePrivateKeyPair(cert, privKey);
161     }
162
163 }