1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47:
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53:
54:
58: public class ICMRandomSpi
59: extends SecureRandomSpi
60: {
61: private static final Logger log = Configuration.DEBUG ?
62: Logger.getLogger(ICMRandomSpi.class.getName()) : null;
63:
64: private static final ICMGenerator prng;
65: static
66: {
67: prng = new ICMGenerator();
68: resetLocalPRNG();
69: }
70:
71:
72: private static final String MSG = "Exception while setting up an "
73: + Registry.ICM_PRNG + " SPI: ";
74: private static final String RETRY = "Retry...";
75: private static final String LIMIT_REACHED_MSG = "Limit reached: ";
76: private static final String RESEED = "Re-seed...";
77:
78: private ICMGenerator adaptee = new ICMGenerator();
79:
80:
81:
82: private static void resetLocalPRNG()
83: {
84: if (Configuration.DEBUG)
85: log.entering(ICMRandomSpi.class.getName(), "resetLocalPRNG");
86: HashMap attributes = new HashMap();
87: attributes.put(ICMGenerator.CIPHER, Registry.AES_CIPHER);
88: byte[] key = new byte[128 / 8];
89: Random rand = new Random(System.currentTimeMillis());
90: rand.nextBytes(key);
91: attributes.put(IBlockCipher.KEY_MATERIAL, key);
92: int aesBlockSize = 128 / 8;
93: byte[] offset = new byte[aesBlockSize];
94: rand.nextBytes(offset);
95: attributes.put(ICMGenerator.OFFSET, offset);
96: int ndxLen = 0;
97:
98: int limit = aesBlockSize / 2;
99: while (ndxLen < 1 || ndxLen > limit)
100: ndxLen = rand.nextInt(limit + 1);
101: attributes.put(ICMGenerator.SEGMENT_INDEX_LENGTH, Integer.valueOf(ndxLen));
102: byte[] index = new byte[ndxLen];
103: rand.nextBytes(index);
104: attributes.put(ICMGenerator.SEGMENT_INDEX, new BigInteger(1, index));
105: prng.setup(attributes);
106: if (Configuration.DEBUG)
107: log.exiting(ICMRandomSpi.class.getName(), "resetLocalPRNG");
108: }
109:
110: public byte[] engineGenerateSeed(int numBytes)
111: {
112: return SecureRandomAdapter.getSeed(numBytes);
113: }
114:
115: public void engineNextBytes(byte[] bytes)
116: {
117: if (Configuration.DEBUG)
118: log.entering(this.getClass().getName(), "engineNextBytes");
119: if (! adaptee.isInitialised())
120: this.engineSetSeed(engineGenerateSeed(32));
121: while (true)
122: {
123: try
124: {
125: adaptee.nextBytes(bytes, 0, bytes.length);
126: break;
127: }
128: catch (LimitReachedException x)
129: {
130: if (Configuration.DEBUG)
131: {
132: log.fine(LIMIT_REACHED_MSG + String.valueOf(x));
133: log.fine(RESEED);
134: }
135: resetLocalPRNG();
136: }
137: }
138: if (Configuration.DEBUG)
139: log.exiting(this.getClass().getName(), "engineNextBytes");
140: }
141:
142: public void engineSetSeed(byte[] seed)
143: {
144: if (Configuration.DEBUG)
145: log.entering(this.getClass().getName(), "engineSetSeed");
146:
147: int materialLength = 0;
148: materialLength += 16;
149: materialLength += 16;
150: materialLength += 8;
151: byte[] material = new byte[materialLength];
152:
153: int materialOffset = 0;
154: int materialLeft = material.length;
155: if (seed.length > 0)
156: {
157: int lenToCopy = Math.min(materialLength, seed.length);
158: System.arraycopy(seed, 0, material, 0, lenToCopy);
159: materialOffset += lenToCopy;
160: materialLeft -= lenToCopy;
161: }
162: if (materialOffset > 0)
163: {
164: while (true)
165: {
166: try
167: {
168: prng.nextBytes(material, materialOffset, materialLeft);
169: break;
170: }
171: catch (IllegalStateException x)
172: {
173: throw new InternalError(MSG + String.valueOf(x));
174: }
175: catch (LimitReachedException x)
176: {
177: if (Configuration.DEBUG)
178: {
179: log.fine(MSG + String.valueOf(x));
180: log.fine(RETRY);
181: }
182: }
183: }
184: }
185:
186: HashMap attributes = new HashMap();
187:
188: attributes.put(ICMGenerator.CIPHER, Registry.AES_CIPHER);
189:
190: attributes.put(ICMGenerator.SEGMENT_INDEX_LENGTH, Integer.valueOf(4));
191:
192: byte[] key = new byte[16];
193: System.arraycopy(material, 0, key, 0, 16);
194: attributes.put(IBlockCipher.KEY_MATERIAL, key);
195:
196: byte[] offset = new byte[16];
197: System.arraycopy(material, 16, offset, 0, 16);
198: attributes.put(ICMGenerator.OFFSET, offset);
199:
200: byte[] index = new byte[4];
201: System.arraycopy(material, 32, index, 0, 4);
202: attributes.put(ICMGenerator.SEGMENT_INDEX, new BigInteger(1, index));
203: adaptee.init(attributes);
204: if (Configuration.DEBUG)
205: log.exiting(this.getClass().getName(), "engineSetSeed");
206: }
207: }