关于 RSA 加密解密的疑惑

2022-02-15 11:37:17 +08:00
 thinkershare

RSA 算法从原理上说, 可以使用 private key 加密, public key 解密, 但为什么各个语言的实现都只允许 public key 加密, private key 解密? private key 加密可以保障数据不被篡改, 但无法保证数据无法被读取, 但部分场景我只需要数据不被篡改, 内容可以是透明的, 但各个库都只允许对原内容的 HASH 进行加密(就是签名), 而不允许对原内容加密(库的实现就只允许使用 Public Key 加密), 这是处于什么安全方面的考虑呢? 我理解 public key 是公开的, 谁都可以解密内容, 因此签名就可以保证数据不被篡改, 但我很疑惑为什么不能通过 public key 能否解密和解密后的内容来预防篡改?

4084 次点击
所在节点    信息安全
26 条回复
datoujiejie221
2022-02-15 14:45:19 +08:00
先看个公钥和私钥的公式
第一步,随机选择两个不相等的质数 p 和 q 。
第二步,计算 p 和 q 的乘积 n 。
第三步,计算 n 的欧拉函数φ(n)。
第四步,随机选择一个整数 e ,条件是 1< e < φ(n),且 e 与φ(n) 互质。(常常选择 65537 )
第五步,计算 e 对于φ(n)的模反元素 d 。
第六步,将 n 和 e 封装成公钥,n 和 d 封装成私钥。

在实际使用中 e 是常量也就是 65537 因此有了私钥也就推导出了公钥 不支持私钥加密应该是为了安全考虑

内容加密场景是 我发出去的消息 只有对方能解 所以用公钥加密
签名的场景是 我发出的消息并且把公钥发给对方 对方要用公钥认证是我发出去的消息 如果发送的是私钥的话 公钥也就暴露了
GeruzoniAnsasu
2022-02-15 15:41:57 +08:00
总结 Q&A:

>
但部分场景我只需要数据不被篡改, 内容可以是透明的, 但各个库都只允许对原内容的 HASH 进行加密(就是签名), 而不允许对原内容加密(库的实现就只允许使用 Public Key 加密), 这是处于什么安全方面的考虑呢

答:并不出于安全方面的考虑,而是效率和通用性

>
但我很疑惑为什么不能通过 public key 能否解密和解密后的内容来预防篡改

答: 原文是否被篡改过并不影响解密过程,在没有附带摘要( hash )的情况下是无法得知解密结果是否「正确」或者「能否解密」的。hash 的作用就是告诉你原文写了什么,解密后的原文 rehash 比对加密过的「真·原 hash 」一致,这才是签名防篡改的关键逻辑。你的设想是否漏掉了什么?
thinkershare
2022-02-15 16:22:10 +08:00
@GeruzoniAnsasu 嗯, 你说到了关键, 就是在不知道私钥的情况下, 能否对私钥加密的内容定向篡改? 否则随意篡改的内容解密后结果就是未知的,攻击者没法定向伪造, 这样解密后的内容, 将无法按照预定义的格式还原. 嗯, 加密的确不能当作签名使用, 是我想错了. 我原本以为内容被修改后解密会失败😅
lucybenz
2022-02-15 16:25:46 +08:00
加密通信 等于 我把我家信箱全部打开,任何一个人都可以过来 选择其中一个信箱扔进去一封信 一摔门锁上,这封信只有我自己可以打开,投信人可以确保 不被其他人截取;

数字签名 等于 我做了一幅字画,加上了我自己的签名和私章,所有人都能看到,且能够判断是我的原作 还是仿品

这是两个不同场景
kxuanobj
2022-02-15 16:32:31 +08:00
假设你有条消息,m 。要生成他们的密文,c 。你没有用 HASH ,也没有添加随机数。使用了原始的 RSA 做了 “加密”。
```
c = m ^ d
```
然后你把这东西,通过中间路由,发给了公钥方。
这时候,通信中间,有个路由算了个 s ,把消息改了,传给了公钥方
```
c' = c ^ 123 = (m ^ d) ^ 123 = m ^ (d * 123) = m ^ (123 * d) = (m ^ 123) ^ d [mod n]
```
公钥方做解密过程
```
m' = c' ^ e = (m ^ 123) ^ d ^ e = (m ^ 123) ^ (d * e) = (m ^ 123) [mod n]
```

m ^ 123 对你的业务有没有影响呢。。说不准。万一有影响呢?有影响不就被中间这货坑了么。

那 RSA 签名咋能用的呢?签名主要把 m 换成了 HASH(m) 。(实际应用时还有 padding 等更多运算)。最后验签方也是计算消息的 HASH 值,对比 HASH 值是不是相等。

即便中间这货给换了签名,那公钥方最后做解密得到的 也是 HASH(m) ^ 123 。

中间这货需要构造一个 123 ,使得 `HASH(?) = HASH(m) ^ 123` 里的 ? 有意义是很困难的。

这里唯一好找的就俩解,一个 把 123 换成 0 ,一个 把 123 换成 1 。

换成 0 的话,整个 HASH 值就是 0 ,然后 就看 HASH 0 为 0 的消息对业务有没有影响。(实际应用时,会通过加入随机数等操作避免这种情况。)

换成 1 的话,那就是原消息。中间人无害转发,也挺好。
youngbug
2022-03-04 16:54:03 +08:00
rsa 签名方案,是先对待签名数据进行 hash ,再进行私钥运算是,因为待签名数据长度不确定,如果长度大于 rsa 的模长,那么一次 RSA 运算,如果是 1024bit 密钥,理论上只能对 128 字节待签名数据进行签名,如果你对一个很大的数据进行签名,要执行多次 RSA 私钥运算,会产生一堆签名结果数据,很不合理。

对待签名数据进行 hash ,保证了最后只用做一次 rsa 私钥运算,也保证签名结果数据长度是固定的。

你的要防止篡改的内容长度是固定的么?如果固定且长度小于 rsa 密钥的模长,那你可以直接对原文进行私钥运算。如果你要签名的数据很长,你自己设计的 rsa 签名,那你就把代签名的数据分组,一组一组的做私钥运算,生成一组一组的签名数据,验签的时候一组一组验签,也没问题。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/833947

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX