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