【问题标题】:Converting an int to a pseudo-random string and vice versa将 int 转换为伪随机字符串,反之亦然
【发布时间】:2021-06-15 23:42:24
【问题描述】:

我需要创建两个 C# 函数,一个(称为 f1)将整数转换为字符串,另一个(称为 f2)将该字符串转换为起始整数。字符串应该看起来像 5 个字符的随机集合(字母和数字)。必须确保至少前 1600 万个整数没有冲突(同一字符串有两个可能的整数)(我对转换太大的数字不感兴趣)。

//Where the "BytesToBase32" function converts a byte array to base 32 ()
string IntToString(int id) {
    byte[] bytes = BitConverter.GetBytes(id);
    return Utils.BytesToBase32(new byte[] {
        (byte)(004 + 145 * bytes[0] + 113 * bytes[1] + 051 * bytes[2]),
        (byte)(166 + 237 * bytes[0] + 010 * bytes[1] + 212 * bytes[2]),
        (byte)(122 + 171 * bytes[0] + 135 * bytes[1] + 020 * bytes[2])
    });
}

它返回如下值:

  • 0 --> 0ij7k
  • 1 --> im9ia
  • 2 --> 4q0d0
  • 3 --> mtmnm
  • ...

如您所见,字符串似乎是随机的(换句话说,无法理解“0ij7k”出现在“im9ia”之前,反之亦然)。

问题是函数f2不能通过简单的求解f1使用的3方程组得到。有没有更简单的方法来获取 f1 和 f2?

【问题讨论】:

  • 假设您使用 base-64 编码,因此每个符号 6 位。这意味着一个 5 字符的字符串有 30 位。一个整数是 32 位的,那你怎么能得到原来的数字呢?
  • 如果你注意到,在我上面写的函数中,整数的第四个字节被丢弃了。因此,可以仅为前 1600 万个整数(2 ^ 24 = 16,777,216)创建函数 f2。换句话说,我对转换太大的数字不感兴趣
  • 为了便于处理,使用 25 位而不是 24 位。然后将它们分成 5 个块和 5 位。将每个块的 32 个可能值与每个位置的 chars 数组中的 36 个可能的目标字符(只需省略未使用的 4 个)之间的映射写入。然后在两个方向上来回使用该映射。
  • 如果您要创建一个双向编码和解码函数对,其中前向编码的输入中的单个位变化会返回一个急剧变化的输出值,这将是非常困难的将其放入 5 个字符中。您是否考虑过只在问题上投入 80MB 内存并使用实际随机字符串的字典?
  • @El_Merendero 加密算法都会生成字节,你可以根据需要将它们编码成字符串。

标签: c# function hash base32


【解决方案1】:

在 cmets 中,我对流密码有误。您实际上需要一个分组密码,但您的分组大小必须是 24 位(对于 1600 万个整数)。看到这个问题和答案:https://crypto.stackexchange.com/q/18988

这些类型的密码称为Format-preserving encryption (FPE)。一种这样的 FPE 称为 FF1。

github上有FF1的C#实现:https://github.com/a-tze/FPE.Net

【讨论】:

    【解决方案2】:

    使用RC4(取自here 的代码示例)之类的密码算法来加密int 的字节,然后简单地对这些字节进行Base64 编码以生成字符串可能就足够了。对于任何 int,这将始终是相同的长度。

    var pwd = Encoding.UTF8.GetBytes("SomePassword");
    var enc = Convert.ToBase64String(RC4.Encrypt(pwd, BitConverter.GetBytes(input)));
    var dec = BitConverter.ToInt32(RC4.Decrypt(pwd, Convert.FromBase64String(enc)));
    

    现场示例:https://dotnetfiddle.net/gK593y

    此示例确实存在您的“相邻数字”问题

    16: SB8u1Q==
    17: SR8u1Q==
    18:Sh8u1Q==
    19: Sx8u1Q==

    我不确定这对你来说有多大问题。

    【讨论】:

    • 这几乎是我需要的,但问题是相邻的数字返回几乎相同的字符串
    猜你喜欢
    • 1970-01-01
    • 2011-05-27
    • 2014-07-22
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 2013-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多