Tuesday, May 29, 2012

How to create a GUID / UUID in Javascript?


I'm trying to create globally-unique identifiers in Javascript. I'm not sure what routines are available on all browsers, how "random" and seeded the built-in random number generator is, etc..



The GUID / UUID should be at least 32 characters and should stay in the ASCII range to avoid trouble when passing them around.


Source: Tips4all

21 comments:

  1. There have been a couple attempts at this. The question is: do you want actual GUIDs, or just random numbers that look like GUIDs? It's easy enough to generate random numbers. From http://note19.com/2007/05/27/javascript-guid-generator/:

    function S4() {
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    }
    function guid() {
    return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
    }


    However, note in the comments that such values are not genuine GUIDs. There's no way to generate real GUIDs in Javascript, because they depend on properties of the local computer that browsers do not expose. You'll need to use OS-specific services like ActiveX: http://p2p.wrox.com/topicindex/20339.htm

    Group to one function:

    function guidGenerator() {
    var S4 = function() {
    return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    };
    return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
    }


    Use:

    guidGenerator();

    ReplyDelete
  2. For an rfc4122 version 4 compliant solution, this one-liner(ish) solution is the most compact I could come up with.:

    'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
    return v.toString(16);
    });


    E.g:

    >>> 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {var r = Math.random()*16|0,v=c=='x'?r:r&0x3|0x8;return v.toString(16);});
    "3bce4931-6c75-41ab-afe0-2ec108a30860"

    ReplyDelete
  3. Here's some code based on RFC 4122, section 4.4 (Algorithms for Creating a UUID from Truly Random or Pseudo-Random Number).

    function createUUID() {
    // http://www.ietf.org/rfc/rfc4122.txt
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
    }

    ReplyDelete
  4. There's a nice compact function for creating rfc4122-compliant random UUIDs posted on my blog at:

    http://www.broofa.com/2008/09/javascript-uuid-function/

    Math.uuid.js is small (~400bytes), and has no dependencies on other libs, so can drop into just about any JS project. It can be used to produce either RFC4122-compliant v4 (random) uuids, or more compact, non-standard IDs of arbitrary length and base. For example:


    >>> Math.uuid() // RFC4122 v4 UUID
    "4FAC90E7-8CF1-4180-B47B-09C3A246CB67"

    >>> Math.uuid(17) // 17 digits, base 62 (0-9,a-Z,A-Z)
    "GaohlDbGYvOKd11p2"

    >>> Math.uuid(5, 10) // 5 digits, base 10
    "84274"

    >>> Math.uuid(8, 16) // 8 digits, base 16
    "19D954C3"


    P.S. That blog post also links to a test page that shows the number of possible UUIDs there are for a variety of arguments, and that includes a performance test for those that care about that sort of thing.

    ReplyDelete
  5. A web service would be useful.

    Quick Google found: http://www.hoskinson.net/GuidGenerator/

    Can't vouch for this implementation, but SOMEONE must publish a bonafide GUID generator.

    With such a web service, you could develop a REST web interface that consumes the GUID web service, and serves it through AJAX to javascript in a browser.

    ReplyDelete
  6. Here's a solution dated Oct. 9, 2011 from a comment by user jed at https://gist.github.com/982883:

    UUIDv4 = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}


    This accomplishes the same goal as the current highest-rated answer, but in 50+ fewer bytes by exploiting coercion, recursion, and exponential notation. For those curious how it works, here's the annotated form of an older version of the function:

    UUIDv4 =

    function b(
    a // placeholder
    ){
    return a // if the placeholder was passed, return
    ? ( // a random number from 0 to 15
    a ^ // unless b is 8,
    Math.random() // in which case
    * 16 // a random number from
    >> a/4 // 8 to 11
    ).toString(16) // in hexadecimal
    : ( // or otherwise a concatenated string:
    [1e7] + // 10000000 +
    -1e3 + // -1000 +
    -4e3 + // -4000 +
    -8e3 + // -80000000 +
    -1e11 // -100000000000,
    ).replace( // replacing
    /[018]/g, // zeroes, ones, and eights with
    b // random hex digits
    )
    }

    ReplyDelete
  7. From good ol' wikipedia there's a link to a javascript implementation of UUID.

    It looks fairly elegant, and could perhaps be improved by salting with a hash of the client's IP address. This hash could perhaps be inserted into the html document server-side for use by the client-side javascript.

    UPDATE : The original site has had a shuffle, here is the updated version

    ReplyDelete
  8. This create version 4 UUID (created from pseudo random numbers) :

    function uuid()
    {
    var chars = '0123456789abcdef'.split('');

    var uuid = [], rnd = Math.random, r;
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
    uuid[14] = '4'; // version 4

    for (var i = 0; i < 36; i++)
    {
    if (!uuid[i])
    {
    r = 0 | rnd()*16;

    uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
    }
    }

    return uuid.join('');
    }


    Here is a sample of the UUIDs generated :

    682db637-0f31-4847-9cdf-25ba9613a75c
    97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
    2eed04c9-2692-456d-a0fd-51012f947136

    ReplyDelete
  9. From sagi shkedy's technical blog:

    function generateGuid() {
    var result, i, j;
    result = '';
    for(j=0; j<32; j++) {
    if( j == 8 || j == 12|| j == 16|| j == 20)
    result = result + '-';
    i = Math.floor(Math.random()*16).toString(16).toUpperCase();
    result = result + i;
    }
    return result;
    }


    There are other methods that involve using an ActiveX control, but stay away from these!

    EDIT: I thought it was worth pointing out that no GUID generator can guarantee unique keys (check the wikipedia article). There is always a chance of collisions. A GUID simply offers a large enough universe of keys to reduce the change of collisions to almost nil.

    That being said, I think that the note19 solution posted by John Millikin is much more elegant that the one I found. Go with that.

    ReplyDelete
  10. It's just a simple AJAX call...

    If anyone is still interested, here's my solution.

    On the server side:

    [WebMethod()]
    public static string GenerateGuid()
    {
    return Guid.NewGuid().ToString();
    }


    On the client side:

    var myNewGuid = null;
    PageMethods.GenerateGuid(
    function(result, userContext, methodName)
    {
    myNewGuid = result;
    },
    function()
    {
    alert("WebService call failed.");
    }
    );

    ReplyDelete
  11. David Bau provides a much better, seedable random number generator at http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html

    I wrote up a slightly different approach to generating UUIDs at http://blogs.cozi.com/tech/2010/04/generating-uuids-in-javascript.html

    ReplyDelete
  12. // RFC 4122
    //
    // A UUID is 128 bits long
    //
    // String representation is five fields of 4, 2, 2, 2, and 6 bytes.
    // Fields represented as lowercase, zero-filled, hexadecimal strings, and
    // are separated by dash characters
    //
    // A version 4 UUID is generated by setting all but six bits to randomly
    // chosen values
    var uuid = [
    Math.random().toString(16).slice(2, 10),
    Math.random().toString(16).slice(2, 6),

    // Set the four most significant bits (bits 12 through 15) of the
    // time_hi_and_version field to the 4-bit version number from Section
    // 4.1.3
    (Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),

    // Set the two most significant bits (bits 6 and 7) of the
    // clock_seq_hi_and_reserved to zero and one, respectively
    (Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),

    Math.random().toString(16).slice(2, 14)].join('-');

    ReplyDelete
  13. function guidGenerator() {
    var buf = new Uint16Array(8);
    window.crypto.getRandomValues(buf);
    var S4 = function(num) {
    var ret = num.toString(16);
    while(ret.length < 4){
    ret = "0"+ret;
    };
    return ret;
    };
    return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
    }


    Done with the proposed, and in Chrome, Firefox available, API for secure random numbers. I have not read the RFC, korpus taken from John Millikin.

    ReplyDelete
  14. Here is a combination of the most voted answer, with a workaround for Chrome's collisions:

    generateGUID = (typeof(window.crypto) != 'undefined' &&
    typeof(window.crypto.getRandomValues) != 'undefined') ?
    function() {
    // If we have a cryptographically secure PRNG, use that
    // http://stackoverflow.com/questions/6906916/collisions-when-generating-uuids-in-javascript
    var buf = new Uint16Array(8);
    window.crypto.getRandomValues(buf);
    var S4 = function(num) {
    var ret = num.toString(16);
    while(ret.length < 4){
    ret = "0"+ret;
    }
    return ret;
    };
    return (S4(buf[0])+S4(buf[1])+"-"+S4(buf[2])+"-"+S4(buf[3])+"-"+S4(buf[4])+"-"+S4(buf[5])+S4(buf[6])+S4(buf[7]));
    }

    :

    function() {
    // Otherwise, just use Math.random
    // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
    return v.toString(16);
    });
    };


    On jsbin if you want to test it.

    ReplyDelete
  15. When looking about for a solution, don't just search on "GUID" but also try "UUID".

    ReplyDelete
  16. I really like how clean Broofa's answer is, but it's unfortunate that poor implementations of Math.random leave the chance for collision.

    Here's a similar RFC4122 version 4 compliant solution that solves that issue by offsetting the first 13 hex numbers by a hex portion of the timestamp. That way, even if Math.random is on the same seed, both clients would have to generate the UUID at the exact same millisecond (or 10,000+ years later) to get the same UUID:

    function generateUUID(){
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = (d + Math.random()*16)%16 | 0;
    d = d/16 | 0;
    return (c=='x' ? r : (r&0x7|0x8)).toString(16);
    });
    return uuid;
    };



    Here's a fiddle to test.

    ReplyDelete
  17. Adjusted my own UUID/GUID generator with some extras here.

    I'm using the following Kybos random number generator to be a bit more cryptographically sound.

    Below is my script with the Mash and Kybos methods from baagoe.com excluded.

    //UUID/Guid Generator
    // use: UUID.create() or UUID.createSequential()
    // convenience: UUID.empty, UUID.tryParse(string)
    (function(w){
    // From http://baagoe.com/en/RandomMusings/javascript/
    // Johannes Baagøe <baagoe@baagoe.com>, 2010
    //function Mash() {...};

    // From http://baagoe.com/en/RandomMusings/javascript/
    //function Kybos() {...};

    var rnd = Kybos();

    //UUID/GUID Implementation from http://frugalcoder.us/post/2012/01/13/javascript-guid-uuid-generator.aspx
    var UUID = {
    "empty": "00000000-0000-0000-0000-000000000000"
    ,"parse": function(input) {
    var ret = input.toString().trim().toLowerCase().replace(/^[\s\r\n]+|[\{\}]|[\s\r\n]+$/g, "");
    if ((/[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12}/).test(ret))
    return ret;
    else
    throw new Error("Unable to parse UUID");
    }
    ,"createSequential": function() {
    var ret = new Date().valueOf().toString(16).replace("-","")
    for (;ret.length < 12; ret = "0" + ret);
    ret = ret.substr(ret.length-12,12); //only least significant part
    for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
    return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-");
    }
    ,"create": function() {
    var ret = "";
    for (;ret.length < 32;ret += Math.floor(rnd() * 0xffffffff).toString(16));
    return [ret.substr(0,8), ret.substr(8,4), "4" + ret.substr(12,3), "89AB"[Math.floor(Math.random()*4)] + ret.substr(16,3), ret.substr(20,12)].join("-");
    }
    ,"random": function() {
    return rnd();
    }
    ,"tryParse": function(input) {
    try {
    return UUID.parse(input);
    } catch(ex) {
    return UUID.empty;
    }
    }
    };
    UUID["new"] = UUID.create;

    w.UUID = w.Guid = UUID;
    }(window || this));

    ReplyDelete
  18. Check this out if you are generating random GUIDs in Google Chrome http://devoluk.com/google-chrome-math-random-issue.html

    ReplyDelete
  19. There is a jQuery plugin that handles Guid's nicely @ http://plugins.jquery.com/project/GUID_Helper

    jQuery.Guid.Value()
    Returns value of internal Guid. If no guid has been specified, returns a new one (value is then stored internally).

    jQuery.Guid.New()
    Returns a new Guid and sets it's value internally.

    jQuery.Guid.Empty()
    Returns an empty Guid 00000000-0000-0000-0000-000000000000.

    jQuery.Guid.IsEmpty()
    Returns boolean. True if empty/undefined/blank/null.

    jQuery.Guid.IsValid()
    Returns boolean. True valid guid, false if not.

    jQuery.Guid.Set()
    Retrns Guid. Sets Guid to user specified Guid, if invalid, returns an empty guid.

    ReplyDelete
  20. The better way:

    function(
    a,b // placeholders
    ){
    for( // loop :)
    b=a=''; // b - result , a - numeric variable
    a++<36; //
    b+=a*51&52 // if "a" is not 9 or 14 or 19 or 24
    ? // return a random number or 4
    (
    a^15 // if "a" is not 15
    ? // genetate a random number from 0 to 15
    8^Math.random()*
    (a^20?16:4) // unless "a" is 20, in which case a random number from 8 to 11
    :
    4 // otherwise 4
    ).toString(16)
    :
    '-' // in other cases (if "a" is 9,14,19,24) insert "-"
    );
    return b
    }


    Minimized:

    function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b}

    ReplyDelete
  21. I know this topic is old but if you really wanted to create a GUID you could obvioulsy do it without straight javascript. You could cause a page expiration every load and create a GUID on the server side then populate that into a javascript variable at page run time. Just an idea.

    ReplyDelete