Convert string to Guid

This blog describes how you can convert a string like "Alex" to a Guid with value: 1fe62611-cd3f-46e3-1e09-0ccb19e446e7. The same string always results in the same guid.

The business case

Towns in the Netherlands exchange information about (soil)locations with a unique ID that start with a unique part of the town, following by a number. Something like "Amsterdam512" and "TheHague881". This is not a handy as locaties sometimes becomes part of to an other town. The towns decided to use guids to make an ID unique for the whole country.

All guid's needs to be converted once, new guid's can be created with "Guid.NewGuid();" (If created in C#);

The suggested solution

To convert al ID's to guids, they created a webservice. It creates a new guid for each new ID and put the combination in a database. If request contains a ID already in the database, the guid is returned from the database.

A better solution

A webservice is not needed if you use (part) of a secure hash. This performs much better and a method is easier to call than a webservice. Also you don't have to deal with concurrency issues.

Example calling client:


      var id1 = CreateGuid("Amsterdam512"); // Always 84af3ffe-44d0-44b5-06e9-6a77e21adeda
      var id2 = CreateGuid("TheHague881"); // Always f58b4e99-a1ab-40b5-d43a-e7537e283dab
      

The implementation

The guid is created this way:

  • Take the first 16 byes of a the SHA512 hash
  • Change the 4 bits used for version to 4
  • Convert the bytes to a guid

      public static Guid CreateGuid(string text)
      {
        const int guidLength = 16;
        var bytes = text.Sha512Bytes().Take(guidLength).ToArray();

        var result = CreateGuidWithVersion4(bytes);
        return result;
      }

      private static Guid CreateGuidWithVersion4(byte[] bytes)
      {
        const int indexVersionNumber = 7;
        const int guidVersion = 0x40; // Version 4

        var bytesClone = bytes.CloneArray(); // Do not change the parameter of the method,

        // Change first 4 bits of the version byte to Guid version 4
        bytesClone[indexVersionNumber] = (byte)(bytesClone[indexVersionNumber] & 0x0f | guidVersion);

        var result = new Guid(bytesClone);
        return result;
      }
      

using these extension methods:


      static class Extentions
      {
        public static T[] CloneArray<T>(this T[] original)
        {
          var result = new T[original.Length];
          Array.Copy(original, result, original.Length);
          return result;
        }


        public static byte[] Sha512Bytes(this string tekst)
        {
          byte[] result;
          var encoder = new ASCIIEncoding();
          byte[] encodeBytes = encoder.GetBytes(tekst);
          using (var sha512Managed = new SHA512Managed())
          {
            result = sha512Managed.ComputeHash(encodeBytes);
          }
          return result;
        }

        // Bonus method, not needed in this blog
        public static string Sha512(this string tekst)
        {
          var bytes = Sha512Bytes(tekst);
          return Convert.ToBase64String(bytes);
        }
      }
      

Leave a Comment

Comment

Comments