【问题标题】:The inverse of modular multiplication in code代码中模乘的逆
【发布时间】:2015-09-29 13:58:49
【问题描述】:

我已经阅读了很多关于这个主题的文章,关于欧几里得算法,我在这里找到了这个主题所需的所有参考资料:

(我的问题的最佳来源)-> Math Explanation

另一个很好的例子 -> Math Explanation 2

维基 -> Extended Euclidean

添加值的好答案 -> Add Operation

这是我完全失去它的地方 -> AFFINE CIPHERS

但是,在所有这些来源中,我仍然无法理解如何通过代码(或伪代码)来实现它,或者至少找不到编写它的方法。

所以我会写基础知识,假设我有这个公式:

(x * key) % mod = 结果
0 0 0

keymod常量
* 表示 乘法 运算
% 表示 余数 运算(编辑澄清)
x 和 结果是动态的

我想创建一个公式,通过 Java 代码为我提供 x。

为我计算result的函数是:

private int MultModulus(int num, int key, int mod)
{
    return (num * key) % mod;
}

我怎样才能找到 X?我应该写什么来计算它?这是我不明白的地方,假设我的函数签名是:

private int InverseMultModulus(int result, int key, int mod)
{
    x = ...
    return x;
}

【问题讨论】:

  • 一个小信息。 % 是余数运算符,而不是模计算的数学表示。这就是例如Math#floorMod 的用途。
  • 哦,在那种情况下,请澄清我的意思是余数运算符。
  • 问题没有明确说明。通常有多个可能的x 值。你要哪个?
  • 没有唯一的答案。例如。如果result == 1mod == 2key == 3x 可以是任何正奇数。
  • 对于加法运算,只有一种解法,乘法有多个答案怎么办?我带来的消息来源表明,假设只有 1 个正确答案。如果我理解正确的话。

标签: java multiplication modulus inverse


【解决方案1】:

如果,如@ergonaut 的答案中的 cmets 所述,您需要能够仅针对相对较少的原始值 x 和相对较小的值 mod 解决此问题,那么一种合理的方法就是提前建一个解码表:对每个可能的x进行前向计算,并将起始x记录在一个数组中,索引在result上。然后,您可以执行简单的数组查找以获取每个结果的x。对于足够长的值序列(即足够长的加密消息中的字符)中的每个值,这肯定会优于单独计算x。当然,如果您本着 Vignere 密码的精神进行此操作,即使用多字节密钥,那么这将乘以预先计算解码表所需的输入长度。

但是请注意,使用您描述的函数来定义可行的密码取决于每个有效输入值都会产生不同的结果。然而,正如我们已经讨论过的,keymod 的某些组合会产生重复的结果。此外,如果可能的结果值的空间与可能的输入值的空间大小相同,那么您必须选择keymod 的组合,以使所有可能的result 值都被使用,否则您不能避免重复。

如果您想将字节加密为字节,并且如果您希望能够处理一般文件,那么唯一可能的mod256。如果您选择较小的一个,则必须至少有一对输入字节映射到相同的密码字节。另一方面,如果您选择更大的mod,则结果值的范围不能1:1 映射到byte 类型的范围内。您还必须确保选择与 256 互质的keys,但这很容易:因为 256 是 2 的幂,所以任何奇数键都可以。只要选择了这样一个键,任何 256 个连续整数范围内的两个输入值都不会映射到相同的结果。

【讨论】:

  • 感谢您的回答,您能否建议我可以创建此密码的任何其他方法?也许不包括任何模运算的东西。我确实通过将每个字符加密为 4 字节大小的数据来解决它。所以当我回读时,我确定我的加密文件是基于我可以读取的 4 字节数据,然后解密回来。但是,它会使每个文件大 4 倍,这不是一个好的转换。
  • @OriFrish,可以为任何大小的“字母表”实现 Vignere 密码的变体。特别是您可以为 256 个字符的字母表实现它。这通常涉及计算余数,但它是(x + key) % size 而不是(x * key) % size。给定一个已知的密钥,它更容易破译。也许这会适合你的目的。
【解决方案2】:

遍历 MultModulus,但在 [0, mod] 中使用 X 进行迭代以返回答案并将它们存储在数组中。

for (int i=0;i<mod;i++){
    if (MultModulus(i, key, mod) == result){
       // store answer in array
    }
}

return array;

【讨论】:

  • 您的解决方案有效,但是,它部分有效,因为由于某种原因,一些 ascii 字母(如 " 和 ' 根本没有被写回,它也以与添加操作解决方案相同的方式工作我带来了,你知道这是为什么吗?
  • @OriFrish,你提出了一个数字问题。 ASCII字符和它有什么关系?
  • 你说得对,基本上,我为“加密”文件编写了一个小型转换算法,因为它没有使用任何真正的加密算法。现在,算法用一个键替换文件中的任何 ascii 字母,该键可以添加到 char 中,或与它相乘。我已经写了一个 4 字节(对于每个字符)加密文件,但我想尝试用 1 字节和模函数来完成它,以节省空间。
  • 不确定 ascii,但您可以在任何不想使用/推导逆向计算的地方使用此技术,通过使用前向计算,并且您有一个小的有限输入集是。例如。如果 a^b (mod c) 是您的公式,并且您不想处理根/对数,并且您知道 lower
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-12
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 2022-01-04
相关资源
最近更新 更多