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.net.InetAddress;
27 import java.security.KeyFactory;
28 import java.security.KeyPair;
29 import java.security.KeyPairGenerator;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.PrivateKey;
32 import java.security.PublicKey;
33 import java.security.Security;
34 import java.security.cert.CertificateException;
35 import java.security.cert.CertificateFactory;
36 import java.security.cert.X509Certificate;
37 import java.security.spec.EncodedKeySpec;
38 import java.security.spec.InvalidKeySpecException;
39 import java.security.spec.PKCS8EncodedKeySpec;
40 import java.security.spec.X509EncodedKeySpec;
41 import java.util.Date;
42
43 import javax.security.auth.x500.X500Principal;
44
45 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
46 import org.apache.directory.api.ldap.model.entry.Attribute;
47 import org.apache.directory.api.ldap.model.entry.Entry;
48 import org.apache.directory.api.ldap.model.exception.LdapException;
49 import org.apache.directory.server.i18n.I18n;
50 import org.bouncycastle.jce.provider.BouncyCastleProvider;
51 import org.bouncycastle.x509.X509V1CertificateGenerator;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
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 private static final String BASE_DN = "OU=Directory, O=ASF, C=US";
74
75 public static final String CERTIFICATE_PRINCIPAL_DN = "CN=ApacheDS," + BASE_DN;
76
77 private static final String ALGORITHM = "RSA";
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 private static final int KEY_SIZE = 512;
94 private static final long YEAR_MILLIS = 365L * 24L * 3600L * 1000L;
95
96 static
97 {
98 Security.addProvider( new BouncyCastleProvider() );
99 }
100
101
102
103
104
105
106
107
108
109
110 public static X509Certificate getCertificate( Entry entry ) throws LdapException
111 {
112 X509Certificate cert = null;
113 CertificateFactory certFactory = null;
114
115 try
116 {
117 certFactory = CertificateFactory.getInstance( "X.509", "BC" );
118 }
119 catch ( Exception e )
120 {
121 LdapException ne = new LdapException( I18n.err( I18n.ERR_286 ) );
122 ne.initCause( e );
123 throw ne;
124 }
125
126 byte[] certBytes = entry.get( USER_CERTIFICATE_AT ).getBytes();
127 InputStream in = new ByteArrayInputStream( certBytes );
128
129 try
130 {
131 cert = ( X509Certificate ) certFactory.generateCertificate( in );
132 }
133 catch ( CertificateException e )
134 {
135 LdapException ne = new LdapException( I18n.err( I18n.ERR_287 ) );
136 ne.initCause( e );
137 throw ne;
138 }
139
140 return cert;
141 }
142
143
144
145
146
147
148
149
150
151 public static KeyPair getKeyPair( Entry entry ) throws LdapException
152 {
153 PublicKey publicKey = null;
154 PrivateKey privateKey = null;
155
156 KeyFactory keyFactory = null;
157 try
158 {
159 keyFactory = KeyFactory.getInstance( ALGORITHM );
160 }
161 catch ( Exception e )
162 {
163 LdapException ne = new LdapException( I18n.err( I18n.ERR_288, ALGORITHM ) );
164 ne.initCause( e );
165 throw ne;
166 }
167
168 EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec( entry.get( PRIVATE_KEY_AT ).getBytes() );
169 try
170 {
171 privateKey = keyFactory.generatePrivate( privateKeySpec );
172 }
173 catch ( Exception e )
174 {
175 LdapException ne = new LdapException( I18n.err( I18n.ERR_289 ) );
176 ne.initCause( e );
177 throw ne;
178 }
179
180 EncodedKeySpec publicKeySpec = new X509EncodedKeySpec( entry.get( PUBLIC_KEY_AT ).getBytes() );
181 try
182 {
183 publicKey = keyFactory.generatePublic( publicKeySpec );
184 }
185 catch ( InvalidKeySpecException e )
186 {
187 LdapException ne = new LdapException( I18n.err( I18n.ERR_290 ) );
188 ne.initCause( e );
189 throw ne;
190 }
191
192 return new KeyPair( publicKey, privateKey );
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 public static void addKeyPair( Entry entry ) throws LdapException
211 {
212 Attribute objectClass = entry.get( SchemaConstants.OBJECT_CLASS_AT );
213
214 if ( objectClass == null )
215 {
216 entry.put( SchemaConstants.OBJECT_CLASS_AT, TLS_KEY_INFO_OC, SchemaConstants.INET_ORG_PERSON_OC );
217 }
218 else if ( !objectClass.contains( SchemaConstants.INET_ORG_PERSON_OC ) )
219 {
220 objectClass.add( SchemaConstants.INET_ORG_PERSON_OC );
221 }
222 else if ( !objectClass.contains( TLS_KEY_INFO_OC ) )
223 {
224 objectClass.add( TLS_KEY_INFO_OC );
225 }
226
227 KeyPairGenerator generator = null;
228 try
229 {
230 generator = KeyPairGenerator.getInstance( ALGORITHM );
231 }
232 catch ( NoSuchAlgorithmException e )
233 {
234 LdapException ne = new LdapException( I18n.err( I18n.ERR_291 ) );
235 ne.initCause( e );
236 throw ne;
237 }
238
239 generator.initialize( KEY_SIZE );
240 KeyPair keypair = generator.genKeyPair();
241 entry.put( KEY_ALGORITHM_AT, ALGORITHM );
242
243
244 PrivateKey privateKey = keypair.getPrivate();
245 entry.put( PRIVATE_KEY_AT, privateKey.getEncoded() );
246 entry.put( PRIVATE_KEY_FORMAT_AT, privateKey.getFormat() );
247 LOG.debug( "PrivateKey: {}", privateKey );
248
249 PublicKey publicKey = keypair.getPublic();
250 entry.put( PUBLIC_KEY_AT, publicKey.getEncoded() );
251 entry.put( PUBLIC_KEY_FORMAT_AT, publicKey.getFormat() );
252 LOG.debug( "PublicKey: {}", publicKey );
253
254
255 Date startDate = new Date();
256 Date expiryDate = new Date( System.currentTimeMillis() + YEAR_MILLIS );
257 BigInteger serialNumber = BigInteger.valueOf( System.currentTimeMillis() );
258
259 X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
260 X500Principal issuerDn = new X500Principal( CERTIFICATE_PRINCIPAL_DN );
261
262 X500Principal subjectDn = null;
263
264 try
265 {
266 String hostName = InetAddress.getLocalHost().getHostName();
267 subjectDn = new X500Principal( "CN=" + hostName + "," + BASE_DN );
268 }
269 catch ( Exception e )
270 {
271 LOG.warn( "failed to create certificate subject name from host name", e );
272 subjectDn = issuerDn;
273 }
274
275 certGen.setSerialNumber( serialNumber );
276 certGen.setIssuerDN( issuerDn );
277 certGen.setNotBefore( startDate );
278 certGen.setNotAfter( expiryDate );
279 certGen.setSubjectDN( subjectDn );
280 certGen.setPublicKey( publicKey );
281 certGen.setSignatureAlgorithm( "SHA1With" + ALGORITHM );
282
283 try
284 {
285 X509Certificate cert = certGen.generate( privateKey, "BC" );
286 entry.put( USER_CERTIFICATE_AT, cert.getEncoded() );
287 LOG.debug( "X509 Certificate: {}", cert );
288 }
289 catch ( Exception e )
290 {
291 LdapException ne = new LdapException( I18n.err( I18n.ERR_292 ) );
292 ne.initCause( e );
293 throw ne;
294 }
295
296 LOG.info( "Keys and self signed certificate successfully generated." );
297 }
298
299
300
301
302
303
304
305
306 public static void addKeyPair( Entry entry, String issuerDN, String subjectDN, String keyAlgo )
307 throws LdapException
308 {
309 Attribute objectClass = entry.get( SchemaConstants.OBJECT_CLASS_AT );
310
311 if ( objectClass == null )
312 {
313 entry.put( SchemaConstants.OBJECT_CLASS_AT, TLS_KEY_INFO_OC, SchemaConstants.INET_ORG_PERSON_OC );
314 }
315 else
316 {
317 objectClass.add( TLS_KEY_INFO_OC, SchemaConstants.INET_ORG_PERSON_OC );
318 }
319
320 KeyPairGenerator generator = null;
321 try
322 {
323 generator = KeyPairGenerator.getInstance( keyAlgo );
324 }
325 catch ( NoSuchAlgorithmException e )
326 {
327 LdapException ne = new LdapException( I18n.err( I18n.ERR_291 ) );
328 ne.initCause( e );
329 throw ne;
330 }
331
332 generator.initialize( KEY_SIZE );
333 KeyPair keypair = generator.genKeyPair();
334 entry.put( KEY_ALGORITHM_AT, keyAlgo );
335
336
337 PrivateKey privateKey = keypair.getPrivate();
338 entry.put( PRIVATE_KEY_AT, privateKey.getEncoded() );
339 entry.put( PRIVATE_KEY_FORMAT_AT, privateKey.getFormat() );
340 LOG.debug( "PrivateKey: {}", privateKey );
341
342 PublicKey publicKey = keypair.getPublic();
343 entry.put( PUBLIC_KEY_AT, publicKey.getEncoded() );
344 entry.put( PUBLIC_KEY_FORMAT_AT, publicKey.getFormat() );
345 LOG.debug( "PublicKey: {}", publicKey );
346
347
348 Date startDate = new Date();
349 Date expiryDate = new Date( System.currentTimeMillis() + YEAR_MILLIS );
350 BigInteger serialNumber = BigInteger.valueOf( System.currentTimeMillis() );
351
352 X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
353 X500Principal issuerName = new X500Principal( issuerDN );
354 X500Principal subjectName = new X500Principal( subjectDN );
355
356 certGen.setSerialNumber( serialNumber );
357 certGen.setIssuerDN( issuerName );
358 certGen.setNotBefore( startDate );
359 certGen.setNotAfter( expiryDate );
360 certGen.setSubjectDN( subjectName );
361 certGen.setPublicKey( publicKey );
362 certGen.setSignatureAlgorithm( "SHA1With" + keyAlgo );
363
364 try
365 {
366 X509Certificate cert = certGen.generate( privateKey, "BC" );
367 entry.put( USER_CERTIFICATE_AT, cert.getEncoded() );
368 LOG.debug( "X509 Certificate: {}", cert );
369 }
370 catch ( Exception e )
371 {
372 LdapException ne = new LdapException( I18n.err( I18n.ERR_292 ) );
373 ne.initCause( e );
374 throw ne;
375 }
376
377 LOG.info( "Keys and self signed certificate successfully generated." );
378 }
379
380 }