'Generating a random UUID in C

How would I go about generating an entropy-based UUID in C and storing it as a string (char pointer)?

I'm hoping that there is an easy way to do this internally, but system("uuidgen -r") will work if not.



Solution 1:[1]

This functionality is provided by libuuid. (Packages libuuid1 and uuid-dev on Debian.)

This is a simple program that generates an entropy-based (random) UUID and writes it to stdout, then exits with status 0.

/* For malloc() */
#include <stdlib.h>
/* For puts()/printf() */
#include <stdio.h>
/* For uuid_generate() and uuid_unparse() */
#include <uuid/uuid.h>


/* Uncomment to always generate capital UUIDs. */
//#define capitaluuid true

/* Uncomment to always generate lower-case UUIDs. */
//#define lowercaseuuid true

/*
 * Don't uncomment either if you don't care (the case of the letters
 * in the 'unparsed' UUID will depend on your system's locale).
 */


int main(void) {
    uuid_t binuuid;
    /*
     * Generate a UUID. We're not done yet, though,
     * for the UUID generated is in binary format 
     * (hence the variable name). We must 'unparse' 
     * binuuid to get a usable 36-character string.
     */
    uuid_generate_random(binuuid);

    /*
     * uuid_unparse() doesn't allocate memory for itself, so do that with
     * malloc(). 37 is the length of a UUID (36 characters), plus '\0'.
     */
    char *uuid = malloc(37);

#ifdef capitaluuid
    /* Produces a UUID string at uuid consisting of capital letters. */
    uuid_unparse_upper(binuuid, uuid);
#elif lowercaseuuid
    /* Produces a UUID string at uuid consisting of lower-case letters. */
    uuid_unparse_lower(binuuid, uuid);
#else
    /*
     * Produces a UUID string at uuid consisting of letters
     * whose case depends on the system's locale.
     */
    uuid_unparse(binuuid, uuid);
#endif

    // Equivalent of printf("%s\n", uuid); - just my personal preference
    puts(uuid);

    return 0;
}

uuid_unparse() doesn't allocate it's own memory; to avoid a segmentation fault upon execution you must do that with manually with uuid = malloc(37); (you can also store the UUID in a char array of that length: char uuid[37];). Make sure to compile with -luuid so that the linker knows that uuid_generate_random() and uuid_unparse() are defined in libuuid.

Solution 2:[2]

Since everyone is saying to use a library, I figured I'd write a fast-and-dirty-C-only version using C's rand(). Make sure to call srand somewhere so the random UUIDs are actually somewhat random.

There's no guarantees that it won't generate two identical UUIDs, and there's no guarantee this meets whatever standard UUIDs have. As far as I know, they're just random hexadecimal strings with dashes between blocks. Also, this isn't multithreading safe.

char* gen_uuid() {
    char v[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    //3fb17ebc-bc38-4939-bc8b-74f2443281d4
    //8 dash 4 dash 4 dash 4 dash 12
    static char buf[37] = {0};

    //gen random for all spaces because lazy
    for(int i = 0; i < 36; ++i) {
        buf[i] = v[rand()%16];
    }

    //put dashes in place
    buf[8] = '-';
    buf[13] = '-';
    buf[18] = '-';
    buf[23] = '-';

    //needs end byte
    buf[36] = '\0';

    return buf;
}

Solution 3:[3]

On Linux, you can use <uuid/uuid.h>, which for me on Ubuntu 20.x is located in /usr/include/uuid/.

/* uuid.c
 * 
 * Defines function uuid
 *
 * Print a universally unique identifer, created using Linux uuid_generate.
 *
 * 
 * Compile
 *
 * gcc uuid.c -o uuid -luuid -Wall -g
 *
 *
 * Run
 * 
 * ./uuid
 * 
 *
 * Debug
 *
 * gdb uuid
 * b main
 * r
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <uuid/uuid.h>

char* uuid(char out[UUID_STR_LEN]){
  uuid_t b;
  uuid_generate(b);
  uuid_unparse_lower(b, out);
  return out;
}

int main(){
  char out[UUID_STR_LEN]={0};
  puts(uuid(out));
  return EXIT_SUCCESS;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 angstyloop