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