Thursday, May 5, 2011

Generating a random key

I want to keep this little block of code around as it might just come in handy in the future, not that it's terribly complex.

The key generator relies on /dev/urandom to help generate a random key. There's another file on the system call /dev/random. The difference between these two is that the command to open and read from /dev/random will block until enough system entropy has occurred on the system, whereas a call to open /dev/urandom will immediately succeed regardless of the entropy on the system. Meaning your key may not be secure at the point the value is read.

This should only really be of concern if the key is being generated somewhere close in time during the boot process.



std::string
Utility::generate_token()
{
  string ret = string("");;
  //if tok is empty then generate a new one                                                                  
  unsigned long val;
  char buf[80];

  int ct = 5; //will try 5 times in case of failure.                                                         
  FILE *fp = NULL;
  while (fp == NULL && ct > 0) {
    fp = fopen("/dev/urandom", "r");
    if (fp) {
      char *ptr = (char*)&val;
      *ptr = fgetc(fp); if (*ptr == EOF) 
         {fclose(fp);fp = NULL;continue;}
      *(ptr+1) = fgetc(fp); if (*(ptr+1) == EOF) 
         {fclose(fp);fp = NULL;continue;}
      *(ptr+2) = fgetc(fp); if (*(ptr+2) == EOF) 
         {fclose(fp);fp = NULL;continue;}
      *(ptr+3) = fgetc(fp); if (*(ptr+3) == EOF) 
         {fclose(fp);fp = NULL;continue;}
      unsigned long id1 = unsigned(val);

      *ptr = fgetc(fp); if (*ptr == EOF) 
         {fclose(fp);fp = NULL;continue;}
      *(ptr+1) = fgetc(fp); if (*(ptr+1) == EOF) 
         {fclose(fp);fp = NULL;continue;}
      *(ptr+2) = fgetc(fp); if (*(ptr+2) == EOF) 
         {fclose(fp);fp = NULL;continue;}
      *(ptr+3) = fgetc(fp); if (*(ptr+3) == EOF) 
         {fclose(fp);fp = NULL;continue;}
      unsigned long id2 = unsigned(val);

      fclose(fp);

      sprintf(buf, "%.8lX%.8lX",id1,id2);
      return string(buf);
    }
    else {
      //      printf("failure to get filehandle\n");                                                         
    }
    --ct;
    usleep(20 * 1000); //20 millisleep between tries                                                         
  }
  //  printf("failure to get random value: %d\n",ct);                                                        
  return ret;
}
rn false;
}

Gives 5 tries at generating a random key and then will fail.

Returns 2 bytes of pure randomness formatted as all caps hex values, which is nice to look at too (in full hex glory).

No comments:

Post a Comment