/ *
* Randomguid
* @version 1.2.1 11/05/02
* @Author Marc A. Mnich
*
* From www.javaexchange.com, Open Software Licensing
*
* 11/05/02 - Performance enhancement from Mike Dubman.
* Moved inetaddr.getlocal to Static Block. Mike Has Measured
* A 10 Fold Improvement in Run Time.
* 01/29/02 - bug fix: improper seeding of nonsecure random object
* Caused duplicate guids to be produted. Random Object
* Is now Only create ONCE Per JVM.
* 01/19/02 - Modified Random SEEDING AND ADDED New Constructionor
* To allow secure random feature.
* 01/14/02 - Added Random Function SEEDING WITH JVM RUN TIME
*
* /
Import java.net. *;
Import java.util. *;
Import java.security. *;
/ *
* In The Multitude of Java Guid Generators, i Found None That
* Guaranteed Randomness. Guids Are Guaranteed to Be Globally Unique
* By Using Ethernet Macs, IP Addresses, Time Elements, And Sequential
* NumBers. Guids area NOT EXPECTED to Be Random and MOST OFTEN ARE
* Easy / Possible to Guess Given A Sample From A Given Generator.
* SQL Server, for Example Genereates Guid That Are Unique But
* SEQUENCIAL WITHIN A GIVEN Instance.
*
* Guids Can Be Used As Security Devices to Hide Things Such AS
* Files within a FileSystem Where Listings Are Unavailable (E.g. Files
* That Are Served Up from A Web Server with indexing turned off.
* This May Be desireable in case where standard authentication is not
* Appropriate. in this Scenario, The Randomguids Are Used as Directories.
* Another Example Is The Use of Guids for Primary Keys in A Database
* Where you want to ensure what the keys are secret. random guids can
* THEN BE USED IN A URL TO Prevent Hackers (Or Users) from accessing * records by Guesding or Simply by Incrementing Sequential NumBers.
*
* There Are Many Other Possiblities of Using Guids in The Realm of
* Security and encryption where the element of randomness is important.
* This class Was Written for these purposes but can also be used as a
* General Purpose Guid Generator As Well.
*
* Randomguid generates truly random guids by using the system's
* IP Address (Name / IP), System Time IN MilliseConds (as an integer),
* And a Very Large Random Number Joined TOGETHER IN A SINGLE STRING
* That Is Passed Through AN MD5 Hash. The IP Address and System Time
* Make The MD5 SEED GLOBALLY UNIQUE AND THE Random Number Guarantees
* That the generated guids will have no discrNable Pattern and
* Cannot Be Guest Given Any Number of Previously Generated Guids.
* It is generally not Possible to Access The Seed Information (IP, TIME,
* Random Number) from the resulting guids as the MD5 hash algorithm
* Provides One Way Encryption.
*
* ----> Security of randomguid: <-----
* Randomguid Can Be Called One of Two Ways - with the Basic Java Random
* Number Generator or a cryptographically strong Random Generator
* (Securerandom). The Choice is offered Because The Secure Random
* Generator Takes About 3.5 Times Longer to Generate Its Random Numbers
* And this Performance Hit May Not Be Worth The Added Security
* especially considering the Basic Generator is SEEDED WITH A
* Cryptographically strong Random Seed.
*
* SEEDING THE Basic Generator in this Way Effectively Decouples
* The Random Numbers from the Time Component Making IT Virtually Impossible
* To Predict The Random Number Component Even if One Had Absolute Knowledge * of the system time. Thanks to ashutosh Narhari for the suggestion
* of using the static method to prime the Basic Random Generator.
*
* Using The Secure Random Option, This Class Compies with the statistical
* Random Number Generator Tests Specified in FIPS 140-2, Security
* Requirements for Cryptographic Modules, Security 4.9.1.
*
* I conveilt all the point the seed to a string before handing
* It over to the md5 hash so you could print it out to make
* Sure It Contains The Data You Expect to See and To Give A Nice
* WARM Fuzzy. if you need better Performance, You May Want to Stick
* to byte [] arrays.
*
* I Believe That It Is Important That The Algorithm for
* Generating random guids be open for inspection and model.
* This class is free for all uses.
*
*
* - Marc
* /
Public class randomguid extends object {
Public String ValueBeForemd5 = "";
Public String ValueAftermd5 = "";
Private static random myrand;
Private statics; myscurerand;
Private static string s_id;
/ *
* Static block to take the take, one time, securerandom seed.
* IT Takes a few seconds to initialize securerandom. You might
* Want to Consider Removing this static block or replacing
* IT with a "Time Since First Load" Seed to Reduce this Time.
* This Block Will Run Only ONCE Per JVM Instance.
* /
STATIC {
Mysecurerand = new securerandom ();
Long SecureInitializer = mysecurerand.nextlong ();
Myrand = New Random (SecureInitializer);
Try {
S_ID = inetaddress.getlocalhost (). TOSTRING ();
} catch (unknownhostexception e) {
E.PrintStackTrace ();
}
}
/ *
* Default constructor. With no specification of security option, * this constructor defaults to limited, high performance.
* /
Public randomguid () {
Getrandomguid (False);
}
/ *
* Constructor with security option. Setting Secure True
* Enables Each Random Number Generated to Be Cryptographically
* Strong. Secure false defaults to the standard random function seeded
* with a single cryptographically strong random number.
* /
Public Randomguid (Boolean Secure) {
Getrandomguid (Secure);
}
/ *
* Method to Generate The Random GUID
* /
Private void getrandomguid (boolean secure) {
MessageDigest MD5 = NULL;
Stringbuffer sbvaluebeforemd5 = new stringbuffer ();
Try {
MD5 = MessageDigest.getInstance ("MD5");
} catch (nosuchalgorithmexception e) {
System.out.println ("Error:" E);
}
Try {
Long Time = system.currenttimemillis ();
Long Rand = 0;
IF (Secure) {
Rand = mysecurerand.nextlong ();
} else {
Rand = myrand.nextlong ();
}
// this StringBuffer Can Be a long as you need; the MD5
// Hash Will Always Return 128 Bits. You can change
// the seed to include anything you want here.
// You Could Even Stream A File Through The MD5 MAKING
// The Odds of Guessing It at Least As Great As That
// of guessing the contents of the file!
SBValueBeForemd5.Append (S_ID);
SBValueBeforeMD5.Append (":");
SBValueBeForemd5.Append (long.totring (time));
SBValueBeforeMD5.Append (":");
SBValueBeForemd5.Append (long.totring (rand));
ValuebeforeMD5 = sbvaluebeforemd5.toString ();
Md5.Upd5.getbytes ());
Byte [] array = md5.digest ();
StringBuffer SB = new stringbuffer ();
For (int J = 0; j INT b = array [j] & 0xff; if (b <0x10) sb.append ('0'); sb.append (integer.tohexstring (b)); } Valueaftermd5 = sb.toString (); } catch (exception e) { System.out.println ("Error:" E); } } / * * Convert to the Standard Format for GUID * (Useful for SQL Server Uniqueidentifiers, ETC.) * EXAMPLE: C2FEEEAC-CFCD-11D1-8B05-00600806D9B6 * / Public string toString () { String Raw = ValueAftermd5.touppercase (); StringBuffer SB = new stringbuffer (); sb.append (raw.substring (0, 8)); Sb.append ("-"); Sb.append (Raw.Substring (8, 12)); Sb.append ("-"); Sb.append (Raw.Substring (12, 16)); Sb.append ("-"); Sb.append (Raw.Substring (16, 20)); Sb.append ("-"); Sb.append (Raw.Substring (20)); Return sb.toString (); } / * * Demonstraton and Self Test of Class * / Public static void main (string args []) { For (int i = 0; i <100; i ) { Randomguid myguid = new randomguid (); System.out.println ("Seeding String =" MyGuid.ValueBeForemd5); System.out.println ("Rawguid =" myguid.valueaftermd5); System.out.println ("randomguid =" myguid.tostring ()); } } }