KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > core > ejb > ca > sign > SernoGenerator


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13  
14 package org.ejbca.core.ejb.ca.sign;
15
16 import java.math.BigInteger JavaDoc;
17 import java.security.SecureRandom JavaDoc;
18 import java.util.Date JavaDoc;
19
20 import org.apache.log4j.Logger;
21 import org.ejbca.core.model.InternalResources;
22
23
24 /**
25  * Implements a singleton serial number generator using SecureRandom.
26  * This generator generates random 8 octec (64 bits) serial numbers.
27  *
28  * RFC3280 defines serialNumber be positive INTEGER, and X.690 defines
29  * INTEGER consist of one or more octets. X.690 also defines as follows:
30  *
31  * If the contents octets of an integer value encoding consist of more than
32  * one octet, then the bits of the first octet and bit 8 of the second
33  * octet:
34  * a) shall not all be ones; and
35  * b) shall not all be zero.
36  *
37  * Therefore, minimum 8 octets value is 0080000000000000 and maximum value
38  * is 7FFFFFFFFFFFFFFF."
39  *
40  * @version $Id: SernoGenerator.java,v 1.6 2006/12/21 15:55:55 anatom Exp $
41  */

42 public class SernoGenerator implements ISernoGenerator {
43     /** Log4j instance */
44     private static Logger log = Logger.getLogger(SernoGenerator.class);
45     /** Internal localization of logs and errors */
46     private static final InternalResources intres = InternalResources.getInstance();
47
48     /** random generator algorithm */
49     private static String JavaDoc algorithm = "SHA1PRNG";
50     
51     /** random generator */
52     private SecureRandom JavaDoc random;
53
54     /** A handle to the unique Singleton instance. */
55     private static SernoGenerator instance = null;
56
57     private static final BigInteger JavaDoc lowest = new BigInteger JavaDoc("0080000000000000", 16);
58     private static final BigInteger JavaDoc highest = new BigInteger JavaDoc("7FFFFFFFFFFFFFFF", 16);
59
60     /**
61      * Creates a serialn number generator using SecureRandom
62      */

63     protected SernoGenerator() throws Exception JavaDoc {
64         log.debug(">SernoGenerator()");
65
66         // Init random number generator for random serialnumbers
67
random = SecureRandom.getInstance(algorithm);
68
69         // Using this seed we should get a different seed every time.
70
// We are not concerned about the security of the random bits, only that they are different every time.
71
// Extracting 64 bit random numbers out of this should give us 2^32 (4 294 967 296) serialnumbers before
72
// collisions (which are seriously BAD), well anyhow sufficient for pretty large scale installations.
73
// Design criteria: 1. No counter to keep track on. 2. Multiple threads can generate numbers at once, in
74
// a clustered environment etc.
75
long seed = Math.abs((new Date JavaDoc().getTime()) + this.hashCode());
76         random.setSeed(seed);
77
78         /* Another possibility is to use SecureRandom's default seeding which is designed to be secure:
79         * <p>The seed is produced by counting the number of times the VM
80         * manages to loop in a given period. This number roughly
81         * reflects the machine load at that point in time.
82         * The samples are translated using a permutation (s-box)
83         * and then XORed together. This process is non linear and
84         * should prevent the samples from "averaging out". The s-box
85         * was designed to have even statistical distribution; it's specific
86         * values are not crucial for the security of the seed.
87         * We also create a number of sleeper threads which add entropy
88         * to the system by keeping the scheduler busy.
89         * Twenty such samples should give us roughly 160 bits of randomness.
90         * <P> These values are gathered in the background by a daemon thread
91         * thus allowing the system to continue performing it's different
92         * activites, which in turn add entropy to the random seed.
93         * <p> The class also gathers miscellaneous system information, some
94         * machine dependent, some not. This information is then hashed together
95         * with the 20 seed bytes. */

96         log.debug("<SernoGenerator()");
97     }
98
99     /**
100      * Creates (if needed) the serial number generator and returns the object.
101      *
102      * @return An instance of the serial number generator.
103      */

104     public static synchronized ISernoGenerator instance()
105         throws Exception JavaDoc {
106         if (instance == null) {
107             instance = new SernoGenerator();
108         }
109         return instance;
110     }
111
112     /**
113      * Generates a number of serial number bytes. The number returned should be a positive number.
114      *
115      * @return a BigInteger with a new random serial number.
116      */

117     public synchronized BigInteger JavaDoc getSerno() {
118         byte[] sernobytes = new byte[8];
119         boolean ok = false;
120         BigInteger JavaDoc serno = null;
121         while (!ok) {
122             random.nextBytes(sernobytes);
123             serno = (new java.math.BigInteger JavaDoc(sernobytes)).abs();
124             // Must be within the range 0080000000000000 - 7FFFFFFFFFFFFFFF
125
if ( (serno.compareTo(lowest) >= 0) && (serno.compareTo(highest) <= 0) ) {
126                 ok = true;
127             } else {
128                 String JavaDoc msg = intres.getLocalizedMessage("sernogenerator.discarding");
129                 log.info(msg);
130             }
131         }
132         return serno;
133     }
134
135     /**
136      * Returns the number of serial number byutes generated by this generator.
137      *
138      * @return The number of serial number byutes generated by this generator.
139      */

140     public int getNoSernoBytes() {
141         return 8;
142     }
143
144     /**
145      * Sets an optional seed needed by the serno generator. This can be different things, for a
146      * sequential generator it can for instance be the first number to be generated and for a
147      * random generator it can be a random seed. The constructor may seed the generator enough so
148      * this method may not be nessecary to call.
149      *
150      * @param seed seed used to initilize the serno generator.
151      */

152     public void setSeed(long seed) {
153         random.setSeed(seed);
154     }
155     
156     /**
157      * Set the random number algorithm used to something different than the default SHA1PRNG.
158      */

159      public static void setAlgorithm(String JavaDoc algo) {
160          algorithm = algo;
161      }
162 }
163
Popular Tags