2

We store patient and care provider records in our database. We need some kind of public identifier for each user that uniquely identifies them, and with some kind of check digit to minimize the chance of wrong inputs.

In my research I have found the Luhn alhorithm, used for credit card numbers; and some variants.

But I am wondering if there are other alternatives, maybe with shorter identifiers or containing alpha numeric characters as well, that might be more suited to use with public user identifiers?

Or would it be a valid option to use the credit card number format for user identifiers as well?

L-Four
  • 13,345
  • 9
  • 65
  • 109
  • Perhaps a hexadecimal identifier might make things easier? – ProgrammingLlama Nov 12 '19 at 08:00
  • 1
    If you don't want to use a GUID or an auto-incremented number, is that can help you? [Unique random string generation](https://stackoverflow.com/questions/730268/unique-random-string-generation) –  Nov 12 '19 at 08:24
  • 5
    Does this answer your question? [How to generate a verification code/number?](https://stackoverflow.com/questions/46231/how-to-generate-a-verification-code-number) – Sinatr Nov 12 '19 at 08:26
  • Thank you all, I have answered my own question based on your comments. – L-Four Nov 12 '19 at 10:59
  • First thing's first, how many patients you expect to have? Meaning, what's the maximum number of unique identifiers you'll need? – Zohar Peled Nov 12 '19 at 12:46
  • Also, what if you simply [pre-populate a random strings pool?](https://zoharpeled.wordpress.com/2019/09/15/pre-populate-a-random-strings-pool/) – Zohar Peled Nov 12 '19 at 12:58

1 Answers1

3

Based on the comments, I came to the following solution.

First, I render a LUID of 8 characters as described by nathanchere in this SO thread.

public class LUID
{
    private static readonly RNGCryptoServiceProvider RandomGenerator 
               = new RNGCryptoServiceProvider();
    private static readonly char[] ValidCharacters = 
               "ABCDEFGHJKLMNPQRSTUVWXYZ23456789".ToCharArray();
    public const int DefaultLength = 6;
    private static int counter = 0;

    public static string Generate(int length = DefaultLength)
    {
        var randomData = new byte[length];
        RandomGenerator.GetNonZeroBytes(randomData);

        var result = new StringBuilder(DefaultLength);
        foreach (var value in randomData)
        {
            counter = (counter + value) % (ValidCharacters.Length - 1);
            result.Append(ValidCharacters[counter]);
        }
        return result.ToString();
    }
}

Then I append a check digit calculated with the iso7064 MOD 1271,36 standard as described here.

I also added a small check that if the calculated check digit contains O, 0, I or 1, I regenerate the code again until it doesn't contain these characters anymore.

The result is a code like 6VXA35YDCE that is fairly unique (if my math is correct there should be like 1.099.511.627.776 possible combinations). It also does not contain I, 1, O and 0; to avoid confusion.

Also, I make sure that any generated LUID does not exist yet in the database before I create a new user with it, just to be sure that it keeps working in case collisions occur.

I think this meets the requirements I was looking for...

L-Four
  • 13,345
  • 9
  • 65
  • 109
  • Glad to see the LUID was helpful :) I would be interested to see how you added the checksum as well. I have done something similar for a previous client but with a strictly numeric checksum digit, so it didn't matter about removing 1/0 (if manual input was required it's easy to enforce the last digit as numeric or convert O->0 and I->1 to suit the use case) and didn't require repeated passes to avoid these digits. – nathanchere Mar 05 '20 at 10:53
  • Also something overlooked when I extracted that example, the class should probably be `static` if you don't have it implementing an `ILUID` interface for automated tests etc. – nathanchere Mar 05 '20 at 11:05
  • @nathanchere For check digit, I used the implementation of https://archive.codeplex.com/?p=iso7064. It has all the ISO 7064 check digit algorithms. – L-Four Mar 06 '20 at 12:01