/*
*
*
* Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.midp.crypto;
/**
* Implements a pseudo random number generator.
*/
final class PRand extends SecureRandom {
/** Local handle to message digest. */
private static MessageDigest md = null;
/**
* For an arbitrary choice of the default seed, we use bits from the
* binary expansion of pi.
* <p>
* This seed is just an example implementation and NOT
* considered for used in SECURE (unpredicable) protocols, for this class
* to be considered a secure source of random data the seed MUST
* be derived from unpredicatable data in a production
* device at the native level.
* (see IETF RFC 1750, Randomness Recommendations for Security,
* http://www.ietf.org/rfc/rfc1750.txt)
*/
private static byte[] seed = {
(byte) 0xC9, (byte) 0x0F, (byte) 0xDA, (byte) 0xA2,
(byte) 0x21, (byte) 0x68, (byte) 0xC2, (byte) 0x34,
(byte) 0xC4, (byte) 0xC6, (byte) 0x62, (byte) 0x8B,
(byte) 0x80, (byte) 0xDC, (byte) 0x1C, (byte) 0xD1
};
/** buffer of random bytes */
private static byte[] randomBytes;
/** number of random bytes currently available */
private static int bytesAvailable = 0;
/** Constructor for random data. */
public PRand() {
if (md != null)
return;
try {
md = MessageDigest.getInstance("MD5");
} catch (Exception e) {
throw new RuntimeException("MD5 missing");
}
randomBytes = new byte[seed.length];
updateSeed();
}
/**
* This does a reasonable job of producing unpredictable
* random data by using a one way hash as a mixing function and
* the current time in milliseconds as a source of entropy.
* @param b buffer of input data
* @param off offset into the provided buffer
* @param len length of the data to be processed
*/
public void nextBytes(byte[] b, int off, int len) {
synchronized (md) {
int i = 0;
while (true) {
// see if we need to buffer more random bytes
if (bytesAvailable == 0) {
md.update(seed, 0, seed.length);
try {
md.digest(randomBytes, 0, randomBytes.length);
} catch (DigestException de) {
// nothing to do
}
updateSeed();
bytesAvailable = randomBytes.length;
}
// hand out some of the random bytes from the buffer
while (bytesAvailable > 0) {
if (i == len)
return;
b[off + i] = randomBytes[--bytesAvailable];
i++;
}
}
}
}
/**
* Set the random number seed.
* @param b initial data to use as the seed
* @param off offset into the provided buffer
* @param len length of the data to be used
*/
public void setSeed(byte[] b, int off, int len) {
int j = 0;
if ((len <= 0) || (b.length < (off + len)))
return;
for (int i = 0; i < seed.length; i++, j++) {
if (j == len) j = 0;
seed[i] = b[off + j];
}
}
/**
* This does a reasonable job of producing unpredictable
* random data by using a one way hash as a mixing function and
* the current time in milliseconds as a source of entropy for the seed.
* This method assumes the original seed data is unpredicatble.
*/
private void updateSeed() {
long t = System.currentTimeMillis();
byte[] tmp = new byte[8];
// Convert the long value into a byte array
for (int i = 0; i < 8; i++) {
tmp[i] = (byte) (t & 0xff);
t = (t >>> 8);
}
md.update(seed, 0, seed.length);
md.update(tmp, 0, tmp.length);
try {
md.digest(seed, 0, seed.length);
} catch (DigestException de) {
// nothing to do
}
}
}
|