I am trying to create a unique id number for a class of objects at
instantiation time. Currently I am using the following line in the
constructor....
this.id = Math.abs( new Random( System.currentTimeMillis() ).nextLong()
);
But when I instantiate a number of objects in a loop many have the same
ids. Is there a more robust way of doing this? Perhaps a RMI class
exposes this functionality statically?
Help,
PufferPhish
Every OS should have a good source of statistically pure random numbers
or gaussian noise. It is as important as the real time clock. None are
available yet.
So, you do something like watch the user move the mouse around and
generate a long string of bits from the x/y positions, then do an MD5 or
CRC32 or something on the result.
Roger Deran
Your problem is that you create a new Random every time. Since the
starting
value from currentTimeMillis is the same, it should come as no surprise
that the same long is repeatedly generated. Just create one
Random and keep using the nextLong() method on it.
WBB
Spiky Bloated Friends of the Ocean,
PufferPhish
Patricia
--
Michael Allen Latta
Sun Certified Java Programmer
Ohana Technologies Corporation
http://www.ohanatech.com
mla...@ohanatech.com
Voice: 303-661-9837
Fax: 303-661-0958
Thanks from the Spiky Bloated Friends of the Ocean,
PufferPhish
If you sometimes decide that your ID's indeed should be derived
from random values, then just do what the other people say plus store
each ID into a hashtable (or other kind of collection). If you generate
a new number just have a look if it's already present. If yes, try the
next one, until you have found a new ID. If you don't use the ID
anymore,
remove the entry in the hashtable/collection.
I use this to generate sessionID's for holding sessions, where the ID's
are encapsulated in URL's (URL rewriting). These ID's must be derived
from
random values, because otherwise someone could guess another user's
sessionID and pretend to be that user by just entering the sessionID
by hand into the URL line.
Usually a good random number generator should have a cycle big enough to
not produce several identical ID's too quickly, but I prefer a
water-proof
approach, which works for every random number generator, also for weak
ones.
I even don't know whether it is standardized which algorithm must be
implemented for generating random numbers by a JVM, so there might be
JVM's which return the same number much earlier than other ones.
bye
--
Sam Jordan
> Why bring random numbers into this at all?
> Why not just the next value
> of a counter that is incremented in a synchronized method?
simple increment is easily guessed. which may be a problem
if you use it to maintain session-id's for http connections
or something like that. random session id's are better
(especially if you use SecureRandom or some "random" Random).
random session-id's, ssl + remembering the client's public key
between connections would be even better (or overkill :-)
if it's only used for, say, generating customer-id's in
an intranet application, sequential id's are just fine.
cheers,
juergen
Is this safe?
java.util.Random uses a fixed algorithm, the same for all JVM
implementations and known to anyone who choses to unzip the source
files and read java/util/Random.java. I'm unclear about the
mathematics involved, but given some values calculated close together,
and knowlege of the constants embedded in the source code, would it be
possible to calculate the low order seed bits which are not part of
the result, and then forwards calculate values that are likely to be
returned at about the same time as the known values?
Patricia
/**
(C) 1999 B.Wieser, OMDI
GUIDs are Globally Unique IDentifiers.
A GUID is usually used for a unique handle for an
object on a network. The typical GUID is constructed
from a unique machine identifier (like the IP address
or ENET address), the system time, and a counter.
All three are required for uniqueness.
As such, OMDI GUIDs are 16 byte arrays with a convenient
GUID class wrapper. I call this the "accessor" patern.
The first 4 bytes of the GUID are the IP address,
the next 8 bytes are the system time, and the last
4 bytes are from a session level counter.
*/
public class GUID extends Object
{
static int counter = 0;
byte[] guts;
/**
Create a raw GUID.
@return the GUID byte array
*/
public static byte[] nextGUID()
{
try {
InetAddress id = InetAddress.getLocalHost();
byte[] ip = id.getAddress(); // 192.168.0.14
counter++;
long time = System.currentTimeMillis();
byte[] guid = new byte[16];
Memory.memset( guid, ip, 0, 0, 4 );
Memory.longToBytes( time, guid, 4 );
Memory.intToBytes( counter, guid, 12 );
return guid;
}
catch(Exception e)
{
return null;
}
}
/**
Create a new GUID.
*/
public GUID()
{
guts = nextGUID();
}
/**
Create a GUID given a byte array.
Typically this should only be called when
restoring externalized objects.
@param guts the contents
*/
public GUID( byte[] guts )
throws IllegalArgumentException
{
if( guts == null || guts.length != 16 )
throw new IllegalArgumentException();
this.guts = guts;
}
/**
Compare two GUIDs for equality.
@param obj GUID to compare to
@return true if equal, false if not equal
*/
public boolean equals( Object obj )
{
if( obj instanceof GUID )
{
if( this != obj )
for( int i = 0; i < 16; i++ )
if( ((GUID)obj).guts[i] != this.guts[i] )
return false;
return true;
}
return false;
}
/**
Convert this GUID to a hex string.
@return the string
*/
public String toString()
{
String str;
str = Long.toHexString( Memory.bytesToLong( guts, 0 ) ) +
Long.toHexString( Memory.bytesToLong( guts, 8 ) );
return str.toUpperCase();
}
/**
Get the raw GUID.
@return the raw GUID
*/
public byte[] getData()
{
return guts;
}
}
>Thanks for pointing out random numbers aren't the way to go ;). These id'ed
>objects are maintained over long times by servlets and possibly could span
servlet
>contexts via different servers. Unless I store the counter I lose that
info each
>time the servlet gets destroyed. I wanted to avoid saving the info if I
could and
>synchronizing across servers. See response to Michael's post please...
>
>Spiky Bloated Friends of the Ocean,
>PufferPhish
If each server has a unique number assigned to it then you have solved the
problem of needing to coordinate among the servers. The high-bits would be
the unique number and the low-bits would be values generated by each
server.
If you need randomness in your IDs (e.g., to prevent easy guessing) you can
include a random number in the ID. To avoid conflicts with existing numbers
you'd also need either to check against a table of allocated IDs or use a
value that is guaranteed to be unique for each allocation (e.g.,
sequentially incrementing a 64-bit value).
You can create a unique ID by combining the unique host number, a random
number, and an integer that is incremented after each allocation.
String id =
hostNumber.toString() + delim +
Long.toString(random.nextValue()) + delim +
Long.toString(sequence.nextValue());
where random and sequence are instances of some appropriate class and delim
is some delimiter that would not appear in the numbers (if no delimiter is
used then you would need to pad each number to an appropriate length).
You still need to maintain the sequences within a server across restarts of
your software. The clock is a sequentially incrementing number, and if you
add a loop and a delay you can almost ensure that it will increment for
each access. The clock, however, is an external variable that may be reset
at any time, so you cannot rely on the clock to really be an incrementing
value. The only solution I can think of is to maintain the sequence value
in some persistent store. You can avoid hitting the disk each time you
increment the value by loading the old value, incrementing it by some
amount greater than 1, and then storing it back to the persistent store.
Your sequence generator then uses this batch of preallocated numbers until
it needs more numbers, at which point it reserves a new batch and stores
the new maximum value. The number of IDs which you preallocate is a
compromise between efficiency and wasting IDs if your software is
restarted.
-- Ari Halberstadt (ariREMO...@shore.net, <http://www.magiccookie.com>)
> Is this safe?
>
> java.util.Random uses a fixed algorithm, the same for all JVM
> implementations and known to anyone who choses to unzip the source
> files and read java/util/Random.java. I'm unclear about the
> mathematics involved, but given some values calculated close together,
> and knowlege of the constants embedded in the source code, would it be
> possible to calculate the low order seed bits which are not part of
> the result, and then forwards calculate values that are likely to be
> returned at about the same time as the known values?
java.util.Random is not safe. it uses only 48 bits of seed,
the upper part constitutes your random, then the next seed is
calculated. if you simply call Random.nextInt(), that leaves
only 16 unknown bits ... easily brute-forced. if i know
2 consecutive 32bit randoms, brute-forcing the seed
takes about 0.5 seconds on my machine.
a much better aproach is using SecureRandom() which uses
SHA1 (instead of the easily attacked add & multiply scheme
of java.util.Random) and has a seed of 20 bytes.
this is cryptographically secure. if you're paranoid
you might consider seeding it with truyly random bits yourself
(/dev/urandom ?? on linux, i think), but if you're not careful,
chances are you do a worse job than the default seeding algorithm.
cheers,
juergen
On 03 May 1999 13:50:20 +0200, in <m1d80ii...@klondike.tiani.com>
Juergen Gmeiner <j...@tiani.com> wrote.....
> Patricia Shanahan <pa...@acm.org> writes:
>
> > Why bring random numbers into this at all?
> > Why not just the next value
> > of a counter that is incremented in a synchronized method?
>
> simple increment is easily guessed. which may be a problem
> if you use it to maintain session-id's for http connections
> or something like that. random session id's are better
> (especially if you use SecureRandom or some "random" Random).
> random session-id's, ssl + remembering the client's public key
> between connections would be even better (or overkill :-)
You can get the best of both worlds by taking your
incremented value and transforming it with some secret value;
this gives determinate results, but the sequence is
just as opaque as if random. Given that the random
number is generated by a black box at one end of the
link and the other end is not assumed to be able to
duplicate this, the use of a secret yet determinate
method doesn't add any complexity to the protocol,
but can guarantee against collision.
I've used this technique to take an incremented 64-bit
integer session number, and used a standard block cypher
with a 64-bit block, and a fixed secret key to permute the
sequence. As the start point of the sequence is arbitrary,
you don't even have known plaintext.
-- PGPfingerprint: BC01 5527 B493 7C9B 3C54 D1B7 248C 08BC --
_______ {pegwit v8 public key =581cbf05be9899262ab4bb6a08470}
/_ __(_)__ ___ ___ {69c10bcfbca894a5bf8d208d001b829d4d0}
/ / / / _ \/ -_|_-< www.geocities.com/SiliconValley/1394
/_/ /_/_//_/\__/___/@windsong.demon.co.uk PGP key on page
### end pegwit v8 signed text
c26802f60939903d7ececd547ceb4495b3043ad7aaca2c86e739fab115c8
e781feb0f97b9e7f7df734d65d854572bad7716f6acebbc0a932654f0480
I agree. Use SHA, RSA, MD5, RC2, or DES, take your pick. You can
generate a very random looking sequence using cypher block chaining that
is very very hard to guess. DES is the fastest. It is a standard cypher
that has a 56 bit secret key. Just be sure to use a truly random key.
One way to get a truly random, one-time key is to flip a coin 56 times!
I think some of these are native code, so should be quite fast.
Roger
--
Java Development Consulting.
Java since 1997, C++ since 1990, C since 1980, x86 Asm since 1973.
Custom AWT library.
Infinity Database Engine US Pats 5,010,478, 5,283,894.
--
Boiler Bay Java Development Consulting.
Thanks from Spiky Bloated Friends of the Ocean,
PufferPhish
Because this would require a lot of messing about, is there an easy way to
just copy everything associated with an object?
Thanks,
Ed.
p.s. Could replies also be sent to my email address!
It is a bit slower, but you could serialize the object and then
deserialize it. That would give you the effect of a deep copy.
Someone suggested, in a similar scenario, that you'd write them all out
(if all the sub-objects are Serializable) to a file, then read them back
in... that would create a complete new structure, with copies of all the
sub-objects.
It sounds like a hack, but it might help you out... Then again, I hope
theres a better way...
// ===============================================
/** @author Kent Dahl
* @url http://www.bigfoot.com/~MenThal/
*
* { Suicide in the cyberpunk era;
* run a Microsoft product
* on your cyberspace deck. } */
Ed.
Off course... that would be the reason to do a deep copy wouldn't it?
Now, your compare of 2 objects.. is that between the one in memory, and
the newly created copy from the Serialization? Cause those are supposed
to be seperate.
If you mean inside the copy structure, then you have "messed up". F. ex.
if you write two vectors to a file, theres a chance that every object
will be written twice, and the refrences will be garbled like you say.
But if the complete structure is hidden in a single object, (that is
Serializable of course) then saving only that object will retain the
internal referencing structure, so that every object is created only
once...
With mulitple writes, it can't see that it should just store a refrence,
and not the complete object, but by summoning it all in one place it
works.
Example from my project in Java-class
class Archive implements Serializable {
Vector listOfObjects;
Vector listOfPersons;
}
If the persons have refrences to objects, then simply serializing the
Archive object will keep the refrences intact... Serializing the Vectors
seperatly would probably make new copies of the objects that a person
refers to, and thusly, it wouldn't be the same object.
See:
http://java.sun.com/products/jdk/1.1/docs/api/java.io.Serializable.html#
_top_
for more details
This turned out to be very useful for me. Thanks for the tip!
Brent Brown
Elitus Prime
--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---