1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.security;
21
22
23 import java.io.ByteArrayInputStream;
24 import java.io.InputStream;
25 import java.math.BigInteger;
26 import java.security.KeyFactory;
27 import java.security.KeyPair;
28 import java.security.KeyPairGenerator;
29 import java.security.NoSuchAlgorithmException;
30 import java.security.PrivateKey;
31 import java.security.PublicKey;
32 import java.security.Security;
33 import java.util.Date;
34
35 import javax.naming.NamingException;
36 import javax.security.auth.x500.X500Principal;
37
38 import java.security.cert.CertificateException;
39 import java.security.cert.CertificateFactory;
40 import java.security.cert.X509Certificate;
41 import java.security.spec.EncodedKeySpec;
42 import java.security.spec.InvalidKeySpecException;
43 import java.security.spec.PKCS8EncodedKeySpec;
44 import java.security.spec.X509EncodedKeySpec;
45
46 import org.apache.directory.server.core.entry.ServerEntry;
47 import org.apache.directory.shared.ldap.constants.SchemaConstants;
48 import org.apache.directory.shared.ldap.entry.EntryAttribute;
49 import org.bouncycastle.jce.provider.BouncyCastleProvider;
50 import org.bouncycastle.x509.X509V1CertificateGenerator;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54
55
56
57
58
59
60
61 public class TlsKeyGenerator
62 {
63 private static final Logger LOG = LoggerFactory.getLogger( TlsKeyGenerator.class );
64
65 public static final String TLS_KEY_INFO_OC = "tlsKeyInfo";
66 public static final String PRIVATE_KEY_AT = "privateKey";
67 public static final String PUBLIC_KEY_AT = "publicKey";
68 public static final String KEY_ALGORITHM_AT = "keyAlgorithm";
69 public static final String PRIVATE_KEY_FORMAT_AT = "privateKeyFormat";
70 public static final String PUBLIC_KEY_FORMAT_AT = "publicKeyFormat";
71 public static final String USER_CERTIFICATE_AT = "userCertificate";
72
73 public static final String CERTIFICATE_PRINCIPAL_DN =
74 "CN=ApacheDS, OU=Directory, O=ASF, C=US";
75 private static final String ALGORITHM = "RSA";
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 private static final int KEY_SIZE = 512;
92 private static final long YEAR_MILLIS = 365*24*3600*1000;
93
94
95 static
96 {
97 Security.addProvider( new BouncyCastleProvider() );
98 }
99
100
101
102
103
104
105
106
107
108
109 public static X509Certificate getCertificate( ServerEntry entry ) throws NamingException
110 {
111 X509Certificate cert = null;
112 CertificateFactory certFactory = null;
113
114 try
115 {
116 certFactory = CertificateFactory.getInstance( "X.509", "BC" );
117 }
118 catch ( Exception e )
119 {
120 NamingException ne = new NamingException( "Failed to get BC Certificate factory for algorithm: X.509" );
121 ne.setRootCause( e );
122 throw ne;
123 }
124
125 byte[] certBytes = entry.get( USER_CERTIFICATE_AT ).getBytes();
126 InputStream in = new ByteArrayInputStream( certBytes );
127
128 try
129 {
130 cert = ( X509Certificate ) certFactory.generateCertificate( in );
131 }
132 catch ( CertificateException e )
133 {
134 NamingException ne = new NamingException( "Bad certificate format." );
135 ne.setRootCause( e );
136 throw ne;
137 }
138
139 return cert;
140 }
141
142
143
144
145
146
147
148
149
150 public static KeyPair getKeyPair( ServerEntry entry ) throws NamingException
151 {
152 PublicKey publicKey = null;
153 PrivateKey privateKey = null;
154
155 KeyFactory keyFactory = null;
156 try
157 {
158 keyFactory = KeyFactory.getInstance( ALGORITHM );
159 }
160 catch ( Exception e )
161 {
162 NamingException ne = new NamingException( "Failed to get key factory for algorithm: " + ALGORITHM );
163 ne.setRootCause( e );
164 throw ne;
165 }
166
167 EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec( entry.get( PRIVATE_KEY_AT ).getBytes() );
168 try
169 {
170 privateKey = keyFactory.generatePrivate( privateKeySpec );
171 }
172 catch ( Exception e )
173 {
174 NamingException ne = new NamingException( "Bad private key format." );
175 ne.setRootCause( e );
176 throw ne;
177 }
178
179 EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( entry.get( PUBLIC_KEY_AT ).getBytes() );
180 try
181 {
182 publicKey = keyFactory.generatePublic( publicKeySpec );
183 }
184 catch ( InvalidKeySpecException e )
185 {
186 NamingException ne = new NamingException( "Bad public key format." );
187 ne.setRootCause( e );
188 throw ne;
189 }
190
191 return new KeyPair( publicKey, privateKey );
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 public static void addKeyPair( ServerEntry entry ) throws NamingException
210 {
211 EntryAttribute objectClass = entry.get( SchemaConstants.OBJECT_CLASS_AT );
212
213 if ( objectClass == null )
214 {
215 entry.put( SchemaConstants.OBJECT_CLASS_AT, TLS_KEY_INFO_OC, SchemaConstants.INET_ORG_PERSON_OC );
216 }
217 else
218 {
219 objectClass.add( TLS_KEY_INFO_OC, SchemaConstants.INET_ORG_PERSON_OC );
220 }
221
222 KeyPairGenerator generator = null;
223 try
224 {
225 generator = KeyPairGenerator.getInstance( ALGORITHM );
226 }
227 catch ( NoSuchAlgorithmException e )
228 {
229 NamingException ne = new NamingException( "Cannot generate key pair for TLS" );
230 ne.setRootCause( e );
231 throw ne;
232 }
233
234 generator.initialize( KEY_SIZE );
235 KeyPair keypair = generator.genKeyPair();
236 entry.put( KEY_ALGORITHM_AT, ALGORITHM );
237
238
239 PrivateKey privateKey = keypair.getPrivate();
240 entry.put( PRIVATE_KEY_AT, privateKey.getEncoded() );
241 entry.put( PRIVATE_KEY_FORMAT_AT, privateKey.getFormat() );
242 LOG.debug( "PrivateKey: {}", privateKey );
243
244 PublicKey publicKey = keypair.getPublic();
245 entry.put( PUBLIC_KEY_AT, publicKey.getEncoded() );
246 entry.put( PUBLIC_KEY_FORMAT_AT, publicKey.getFormat() );
247 LOG.debug( "PublicKey: {}", publicKey );
248
249
250 Date startDate = new Date();
251 Date expiryDate = new Date( System.currentTimeMillis() + YEAR_MILLIS );
252 BigInteger serialNumber = BigInteger.valueOf( System.currentTimeMillis() );
253
254 X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
255 X500Principal dnName = new X500Principal( CERTIFICATE_PRINCIPAL_DN );
256
257 certGen.setSerialNumber( serialNumber );
258 certGen.setIssuerDN( dnName );
259 certGen.setNotBefore( startDate );
260 certGen.setNotAfter( expiryDate );
261 certGen.setSubjectDN( dnName );
262 certGen.setPublicKey( publicKey );
263 certGen.setSignatureAlgorithm( "SHA1With" + ALGORITHM );
264
265 try
266 {
267 X509Certificate cert = certGen.generate( privateKey, "BC" );
268 entry.put( USER_CERTIFICATE_AT, cert.getEncoded() );
269 LOG.debug( "X509 Certificate: {}", cert );
270 }
271 catch ( Exception e )
272 {
273 NamingException ne = new NamingException( "Cannot generate self signed certificate." );
274 ne.setRootCause( e );
275 throw ne;
276 }
277
278 LOG.info( "Keys and self signed certificate successfully generated." );
279 }
280 }