确认下 RSA 加密签名的一些疑惑

2019-08-10 15:50:36 +08:00
 coolair
现在的需求是:把 public key 给客户机,服务器存 private key,服务器给客户机发消息,客户机响应后执行操作。
所以,我的想法是加密不行,加密是用 public key 加密,传给服务器,服务器用 private key 解密。
所以用签名,把消息(明文)和签名(用 private key 签名)发给客户机,客户机接收后用 public key 解签,成功,执行消息中的指令操作,解签失败则不执行。


另外:
1 )如果用签名的话,是不是消息被截获了,就被知道了?因为是明文的。
2 )用 private key 签名,用 private key 和 public key 都可以解签成功。
3 )用 private key 加密的数据,只能用 private key 解密,public key 不能解密。
4 )用 public key 加密的数据只能用 private key 解密,不能用 public key 解密。


我的以上说法正确吗???

以上测试代码来自于:
https://pycryptodome.readthedocs.io/en/latest/src/signature/pkcs1_pss.html
https://pycryptodome.readthedocs.io/en/latest/src/examples.html
1670 次点击
所在节点    问与答
13 条回复
HaoLan
2019-08-10 16:27:46 +08:00
设置两对 keys 不就可以了。
客户端服务端一对,服务端客户端一对
shansing
2019-08-10 16:29:26 +08:00
不是密码学专业,以我有限的知识先帮楼主消灭零回复。(未必正确,欢迎指正。)

楼主为什么说加密不行呢?加密未必是用公钥加密。公钥和私钥在数学上是对等的:可以用公钥加密,只有私钥能解密,也可以用私钥加密而只有公钥能解密。也就是 2、3 错误,4 正确。只是,一些 RSA 的实现,会在私钥文件中同时存储公钥(和私钥)。

如果想签名的的话,用明文暴露消息肯定是有被窃听的可能,也就是 1 正确。签名的意义在于校验消息完整性,防止消息被篡改。而如果你想防止窃听,需要将消息加密。既对消息加密,又认证消息的做法有几种(根据顺序区分),也就是 E&M、MtE、EtM。据说最后一种是最好的。AES 的 GCM 就可实现 EtM。(加密消息不太可能会用 RSA 这种非对称加密方法,因为慢,取而代之的是诸如 AES 的对称加密算法。)

呃,这样想来,不是很明白楼主这个需求是什么,为什么最初想用非对称加密算法加密消息。
lagoon
2019-08-10 16:31:49 +08:00
RSA 1 号公钥私钥。
lagoon
2019-08-10 16:32:59 +08:00
RSA 1 号公钥私钥。
RSA 2 号公钥私钥。
服务器持有 1 号私钥,2 号公钥。
客户端持有 2 号私钥,1 号公钥。
我错了,其实我没听到题主的问题。
Xbluer
2019-08-10 16:37:09 +08:00
1、4 正确,2、3 错误。
napsterwu
2019-08-10 16:39:00 +08:00
两对 key
不过两对 key 共四把密钥,攻击者自然可以看到三把
gimp
2019-08-10 16:41:40 +08:00
严格来说,RSA 算法中公钥加密和数字签名正好是完全相反的关系。

用私钥加密相当于生成签名,用公钥解密相当于验证签名。
同样加密来讲,公钥加密后,只有对应的私钥可以解密

1 )是的
2 )私钥签名后,只有配对的公钥能够进行验证,知道私钥可以生成公钥,反之不行
3 )同 2 )
4 )是的


其实明文加解密你可以用 AES,速度比非对称加密快很多。

RSA 可以用来分发 AES 加密用的 key

如果你想要确保消息是来自合法客户端的,那么生成一对密钥,客户端持有自己的私钥,服务端保存这个客户端的公钥(参考 Github 推送代码时,先添加自己的公钥到服务器,以便确认用户身份)

如果你想要确保指令消息时来自服务器,那么再生成一对密钥,客户端持有公钥,服务端自己保存私钥,服务器发送消息用私钥加密,也就是签名,公钥能解密就说明来自服务器

用 AES 加密消息,那么这个 key 怎么分发是个问题,这就可以借助于 RSA 来分发 key,服务器用客户端的公钥来对 key 进行加密,客户端用私钥进行解密,获取里面的 key。通信的时候都用 key 进行加密解密

客户端如何将公钥发送给服务端需要通过 HTTPS 传输防止中间人攻击
Sylv
2019-08-10 16:49:20 +08:00
直接走 HTTPS + Certificate Pinning 就可以了,没必要自己造轮子。
ryd994
2019-08-10 16:50:59 +08:00
加密永远是持有公钥的发送,持有私钥的解密
签名永远是持有私钥的签名,持有公钥的解密

如果你要实现双向加密通信,你有两种选择:
1. 学普通 HTTPS 网站的做法,RSA 仅作签名用于验证服务器身份避免中间人攻击。双方协商一个对称密钥,实际通讯由对称密钥加密。然后用账号密码等方式再验证服务器身份。
1.5 稍高级的 HTTPS 网站可以使用客户端证书直接实现双向验证。网银插件就是这样。U 盾本质上也是,但是基于硬件智能卡,所以更安全。

2.学 PGP/GPG,想给谁发消息就先想办法取得接收方的加密公钥。至于怎么验证公钥避免中间人工具,就只能靠其他可信信道。反正假设你已经取得并验证过公钥。

@shansing 实际上不对等,因为公钥的其中一个因子一般是固定为 65537,因此只要知道私钥,就能简单推出公钥。
shansing
2019-08-10 16:53:08 +08:00
@ryd994 谢谢。

我刚也查了 https://www.v2ex.com/t/144641 等网页,发现现实中私钥是容易推导出公钥的。
AlvaIM
2019-08-10 17:18:45 +08:00
非对称加密的话, 均是 公钥加密, 私钥解密, 私钥签名, 公钥验签, 把握住这个 4x4 的四字箴言就不会搞错了
jaskle
2019-08-10 17:19:35 +08:00
私钥能够导出公钥,所以私钥加密私钥也是能解开的,这也是为什么要分为公开私有。
AlvaIM
2019-08-10 17:27:56 +08:00
SSL/TLS 现在推荐使用类似 secp256k1 这类基于椭圆曲线的非对称密钥对系统就是因为 EC 系统通过 ECDH 来实现零知识证明的密钥分发 是天然抵御中间人攻击的。简单的来说, 假设有 2 个人,Alice 和 Bob, 各持有一个密钥对,Alice 的公钥给 Bob,Bob 的公钥给 Alice, 现在互相要发消息给对方, 假设 Alice 要发给 Bob, 那么 Alice 只需要用自己的私钥和 Bob 的公钥就能计算出一个密钥, 用这个密钥通过对称加密比如 AES 加密数据后发给 Bob,Bob 获取后, 通过自己的私钥和 Alice 的公钥就能同样计算出和 Alice 一样的密钥, 就能解开密文得到原始数据了。

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

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

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

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

© 2021 V2EX