【问题标题】:Finding the minimum value to satisfy a modulus找到满足模数的最小值
【发布时间】:2014-02-21 01:17:22
【问题描述】:

我遇到的问题是 x = (16807 x k) % 65536

即 16807k ≡ x (mod 65536)

我需要在知道 x 的情况下计算 k。 到目前为止,我的最大努力是蛮力。有计算k的数学方法吗? 如果不是对我当前的代码进行任何优化,我们将不胜感激。

t = x;
while ( t += 15115 ) // 16807k = 65536n + x - this is the n
{
    if (t%16807 == 0)
    return t/16807;
}
return x;

编辑:将 += 更改为 15115

【问题讨论】:

  • x = (16807 x k) % 65536 和 16807k = x mod 65536 不等价。
  • @Roecrew 评论的补充:第一个方程有多个 k 作为答案,第二个方程有一个 k。你需要找到所有k的吗?
  • 老兄对不起,你没有任何意义。你能至少告诉我们这段代码的应用是什么吗?
  • 抱歉,忽略第二个等式 - 它应该是 16807k ≡ x (mod 65536)。它来自加密功能。应用的函数 ((16807 x k) % 65536) ^ plaintext for 16bit k and plaintext 是两个字符。我有明文的前几个字节,并试图尽可能有效地解密它。明文^密文给了我上面我所说的x
  • * 用于大学作业。他们希望我们暴力破解它。因此我需要提供原始密钥以及明文

标签: c math optimization hash modulus


【解决方案1】:

奇数的乘法逆模是 2 的幂。

16807 mod 216的倒数是22039。

这意味着(16807 * 22039) % 65536 == 1,因此,

(16807 * 22039 * x) % 65536 == x

k = (22039 * x) % 65536

所以你不必尝试任何东西,你可以直接计算k

【讨论】:

  • 如果正确引用来源(Warren, Henry S., Jr.. Hacker's Delight。波士顿:Addison-Wesley,2003 年。“mulinv” , pp. 195-197.),声明代码已针对特定情况进行了修改,说明了修改代码的限制,并解释了代码工作的原因。像这样的神秘代码被传递并插入程序中,导致代码无法维护,这是软件开发的祸根。此代码仅限于 2 的小幂。循环将其扩展到 2 的其他幂,并且扩展的欧几里得算法支持任何数字。
【解决方案2】:

您使用 16807 和 65536 的 GCD 的扩展欧几里得算法解决此类问题

余数序列以

开始
R0=65536
R1=16807

以及用

计算逆
V0=0  (V0*16807 == R0 mod 65536)
V1=1  (V1*16807 == R1 mod 65536)

然后使用整数长除法,

Q1=R0/R1=3,
R2=R0-Q1*R1=15115
V2=V0-Q*V1=-3 (V2*16807 == R2 mod 65536)

Q2=R1/R2=1,  
R3=R1-Q2*R2=1692
V3=V1-Q2*V2=4

Q3=8,  R4=1579,  V4=-35
Q4=1,  R5=113,   V5=39
Q5=13, R6=110,   V6=-542
Q6=1,  R7=3,     V7=581
Q7=36, R8=2,     V8=-21458
Q8=1,  R9=1,     V9=22039

所以 22039 是 15115 模 65536 的模逆。

【讨论】:

    【解决方案3】:

    如果您必须反复查找k 以获得不同的x,您可以在开始解码之前构建一个解决方案表:

    uint16_t g = 16807u;
    uint16_t *mods = malloc(0x10000 * sizeof(*mods));
    int i;
    
    for (i = 0; i < 0x10000; i++) {
        uint16_t x = g * i;    // x is effectively x mod 2**16
    
        mods[x] = i;
    };
    

    那么你的方程在 16 位范围内的解是:

    uint16_t k = mods[x];
    

    假设x是一个16位无符号整数。完成后别忘了free(mods)

    【讨论】:

      【解决方案4】:

      如果k 是一个解决方案,那么k+65536 也是一个解决方案。

      找到第一个 k (k>= 0) 的直接蛮力方法是:

      for (k=0; k < 65536; k++) {
          if ( (k*16807) % 65536 == x ) {
              // Found it!
              break;
          }
      }
      if (k=65536) {
          // No solution found
      }
      return k;
      

      【讨论】:

        猜你喜欢
        • 2020-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多