生成带有校验位的唯一 public 用户标识符

Generate unique public user identifier with check digit

我们将患者和护理提供者的记录存储在我们的数据库中。我们需要某种 public 标识符 为每个用户 唯一地 标识他们,并使用某种校验位来最小化机会错误的输入。

在我的研究中,我发现了用于信用卡号码的 Luhn 算法;和一些变体。

但我想知道是否还有其他替代方案,可能具有更短的标识符或也包含字母数字字符,可能更适合与 public 用户标识符一起使用?

或者将信用卡号格式也用于用户标识符也是一个有效的选择吗?

根据评论,我得出以下解决方案。

首先,我渲染了一个 8 个字符的 LUID,如 nathanchere 在 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();
    }
}

然后我按照 here.

的描述附加一个用 iso7064 MOD 1271,36 标准计算的校验位

我还添加了一个小检查,如果计算出的校验位包含 O、0、I 或 1,我会再次重新生成代码,直到它不再包含这些字符为止。

结果是类似于 6VXA35YDCE 的代码,它非常独特(如果我的数学是正确的,应该有 1.099.511.627.776 种可能的组合)。它也不包含I、1、O和0;以免混淆。

此外,在我使用它创建新用户之前,我确保数据库中不存在任何生成的 LUID,以确保它在发生冲突时继续工作。

我认为这符合我一直在寻找的要求...