如何制作一个简单的公钥加密算法?

20

我想制作一个简单的公钥(非对称)加密。它不需要是安全的,我只想理解其背后的概念。例如,我知道可以使用XOR创建简单的对称密码。我在stackexchange上的一个帖子中看到需要使用陷门函数,但我找不到太多相关信息。我想说,取一组字节,并能以某种方式分割它们以获得公钥/私钥。我理解共享秘密的想法。比如,我生成了256的随机数(并不随机:P),并将其分成200和56。如果我使用200进行XOR,则只能使用200进行解密。我希望能够随机地分割数字等来进行非对称加密。


2
我只是想知道它是如何工作的,我没有任何加密的用途。所有在线上的东西都解释了外壳,但没有公钥系统的生成等方面的内容。 - user2507230
3
这个问题似乎不适合此处,因为它涉及加密理论。 - President James K. Polk
1
你需要阅读一些有关加密的内容。找一本好书。你不可能指望在一个专门解决编程问题的网站上学习PK加密的基础知识。 - Jonathon Reinhart
似乎你可以几乎同样容易地说,“你需要阅读一些关于[LINQ/SQL游标/代码注入/JavaScript原型...]的内容”;^)我可能会建议建议一本好书。虽然我理解OT关闭,但是对于使用它的应用程序进行编程而言,基本了解加密可能是相关的。如果您的问题通常涵盖...软件算法...那么您就可以在此处提出您的问题! - ruffin
3个回答

30

好的,这只是一个简单的演示想法,基于加/模运算。

  1. 假设我们有一个模数值,例如256。这是一个公开已知的常见值。

  2. 假设您在区间[1-255]中生成一个随机的私钥,例如pri=133。将秘密密钥保密。

  3. 生成公钥,pub = 256 - pri = 123。此公钥(123)可以与全世界共享。想象一下,第三方不知道如何从公钥计算出私钥。因此,他们只知道公钥(123)。

  4. 来自公众的某个人想要向您发送经过加密的ASCII字节。他得到了字节,并通过模256运算将其与公钥相加:

  5. encrypted = (input_value + pub) % modulto;
    

举个例子,我想要以加密形式发送给你字母 "X",ASCII码为88。因此,我进行计算:

(88 + 123) % 256 = 211;
  1. 我正在发送加密字节值为211给你。

  2. 你可以通过使用你的私钥相同的方案来解密它:

decrypted = (input_value + pri) % 256 = (211 + 133) % 256 = 88;
当然,这个例子中使用简单的生成对是薄弱的,因为有一种众所周知的从公钥生成私钥的算法,任何人都可以轻松地使用模数和公钥恢复私钥。但在实际的加密中,这个算法是未知的。不过理论上,它将来可能会被发现。

1
我必须补充:“最好的密码术是众所周知的”,这方面有很多经验证据(尽管有些形式会更名为“模糊化”)。 - Alec Teal
模数是共享密钥还是与其相关的字节大小?解密后的值为:decrypted = (input_value + pri) % 256 = (221 + 123) % 256 = 88;如果这个%256是共享密钥,那么简单地计算256-123将得到私钥吗? - user2507230
我完全搞定了!谢谢,伙计! - user2507230
2
modulto是共享信息。我选择256,因为在uint8_t中自动执行modulto 256的操作。因此,在简单实现中,不需要使用此操作。但是您可以使用任何另一个modulto,该modulto大于max_you_byte_value,例如150。如果pri = 50,则pub = 150-50 = 100。将使用相同的数学运算:enc =(88 + 100)%150 = 38; dec =(38 + 50)%150 = 88。 - olegarch
非常好的解释。 - Abu Sadat Mohammed Yasin
这个答案是错误的。如果模数是公共信息,那么私钥也是公共信息,因为你可以从模数中减去公钥来得到它(正如@user2507230在上面指出的那样)。 - Sod Almighty

4
这是一个纯数学领域,有一本书叫做“密码学的数学”,它很短但是是一个很好的入门。我建议你不要自己实现密码学,特别是在Java中(你需要一个针对真实机器的编译器来处理所涉及的数学问题,并进行相应的优化)。你应该在数学或计算机科学堆栈交换上询问此事。
我确实收到了一个负分,所以我想澄清一下。我并不是没有同情心,但密码学坚定地处于数学领域,而不是编程领域(即使是离散数学或计算机科学的数学方面),它需要对代数结构有很好的理解,一些统计知识,它肯定是一个迷人的领域,我鼓励你阅读。我确实是指上面的话,不要使用你自己制作的任何东西,那些“发明”这些密码的人已经忘记了比你或我更多的东西,最多只能按照他们说的实现。在Java中,你应该预期吞吐量非常低。关于寄存器压力和分配的优化可以大大提高密码吞吐量。Java首先是基于堆栈的。
补充(约6年后):
Java在某些方面已经有所改进(我有一个编译器嗜好,这很奇怪),但回顾过去,我是对的,但理由有点不对,Java更容易通过时间攻击,例如我见过一些依赖跟踪编译技术的巨大用途,以确定正在使用的软件版本。它也很难处理Spectre,这种情况不会很快消失(我喜欢高速缓存...现在说出来感觉很不舒服) 然而:最重要的是,不要自己做!最多只是玩一下 - 这非常属于数学领域,我必须说它可能更适合在纸上完成,除非你喜欢欣赏数字散布在终端上。

@ntoskrnl,实现没有任何JIT的义务,即使有JIT,它也必须快速,只对少量代码进行最有益的优化。考虑一个真正的编译器,拥有所有编译时间和链接时间优化以及关键字const,你真的得到了一些东西。例如,GCC在减少抽象惩罚方面投入了大量工作。Java可能比仅使用VM更快,但绝不算快。 - Alec Teal
不需要JIT,但是只有一个广泛使用的虚拟机HotSpot,并且自1998年版本1.2发布以来就具有JIT。在足够的运行时间下,现代版本的HotSpot最终会编译程序中所有需要编译的部分,而不仅仅是一些小片段。与GCC等静态编译器相比,JIT还具有更多关于代码的运行时信息,因此可以动态省略不必要的分支、冗余边界检查、空检查甚至同步。虽然Java在某些方面(如浮点数)缺乏性能,但总体上与C++一样快。 - ntoskrnl
@ntoskrnl 几个词,配置指导优化。你也不能说“C++总体来说”,因为它可能意味着太多东西了。我们应该避免这场辩论,但是众所周知,C(++), Fortran, Go...等等,甚至虚函数表都是不同的。还有内存管理等等。C++在小数方面并不更好,只是编译器会分配实际的机器寄存器等等。我对GCC(和它的Java编译器)的内部非常了解,真是迷人的东西 :) - Alec Teal
GCJ与HotSpot JIT没有任何关系,它们是完全不同的东西。说“你不应该在Java中进行加密,因为它很慢”是误导性的,因为它的速度不是像PHP那样缓慢。 - ntoskrnl
@ntoskrnl,使用LTO的GCJ已经是最好的选择了。我认为你需要接受这一点:如果你想要一种快速的语言,那么你必须学习一种。你一直在说“Java很快”,但它不可能像GCJ一样快。因为GCJ是GCC,所以后端的东西(-O3、-lto)都可以工作,还有基于配置文件的优化。我用这个告诉你高速Java的最佳选择。无论如何,请不要回复这个评论,我还有其他事情要做。请自己研究这个问题,不要回复这个评论。 - Alec Teal
显示剩余4条评论

3

1
考虑到它是在GCHQ发明的,而且英国政府甚至不允许其发明者在R、S和A提交专利时声称功劳,我认为我们可以确定它非常安全。现在你的随机质数生成器可能确实存在漏洞。 - James Robinson
这告诉我它如何生成密钥,但是它如何使用密钥进行加密/解密呢? - user2507230
2
你读了这篇文章吗?即顶部标记为加密和解密的段落。 - James Robinson
我搞定了,谢谢。:) - user2507230

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接