安卓上一个奇怪的 rsa,每次加密结果都一样

2020-01-09 00:00:11 +08:00
 szvone

排版乱了,请看一楼

6005 次点击
所在节点    问与答
38 条回复
bagel
2020-01-09 08:52:12 +08:00
Padding 导致的。说白了就是没有真正理解 RSA 加密算法。

上面 geelaw 已经指出来了,还一堆人在那不懂装懂。另外,geelaw 你最后“可能的理解”是错的,Android 上的 API 是正确的,只是有些人不会用又不愿意读文档而已。
ThirdFlame
2020-01-09 08:53:35 +08:00
@geelaw
@baicheng10
在没有填充的情况下,明文 秘钥不变的情况下,密文不变。
在最优非对称加密填充(OAEP) 下 明文 秘钥不变的情况下,密文会变。根本原因是明文被填充了一些东西(每次还不一样),其实也就是明文变化了,所以导致了密文变化。
有些填充方式是固定的,不会导致每次填充后的明文变化,也就不会产生密文的变化。
CEBBCAT
2020-01-09 08:54:45 +08:00
@baicheng10 他这个还真没说错,你去搜索一下 语义安全 就明白了,或者去看这个链接: https://www.zhihu.com/question/305995210
mxT52CRuqR6o5
2020-01-09 09:01:31 +08:00
@geelaw 能说一下 [一个具有最基本安全性(具体来说是语义安全)的非对称加密算法必须满足,正常生成的密钥,加密同一消息两次,密文相同的概率必须非常小] 这个说法是从哪来的吗?查了半天没查到
KingPL
2020-01-09 09:09:53 +08:00
sm2 每次加密后不一样,但依旧可以重放攻击,正常后端解密后也需要验签,防重放攻击
baicheng10
2020-01-09 09:22:20 +08:00
@CEBBCAT #22 明白了,谢谢。
geelaw
2020-01-09 09:25:35 +08:00
@bagel #21 根据 #7 的说法,另一个 Java runtime 的实现是不同的,我猜另一个实现是 Sun 或者 Oracle 的,这个实现出现如此严重错误的可能感觉也不大。

@baicheng10 #19 如果你加密同一条消息多项式次,密文以极高的概率各不相同。
@ThirdFlame #20 确定性加密并不安全。
@mxT52CRuqR6o5 #24 你可以参考 #23 的链接。
ThirdFlame
2020-01-09 09:45:12 +08:00
@geelaw 安全不安全 不是我所说的那段话所要讨论的。 我只是想说明 为啥非对称加密 其实是不会变的。 而有些函数,为啥会变。

你的问题 其实就是要去看 那个函数实现里面有没有填充。 而不是问 “RSA 加密的话不是每次都会变动吗,为啥这个就不会变动呢?”
xiri
2020-01-09 10:11:11 +08:00
@geelaw
我姑且是学过密码学的。
根据我学到的原理,rsa 加密时所取的参数都是确定值,在明文不变的情况下计算出来的结果不可能会发生变化。
你说的“每次加密结果不同”貌似是同属于非对称密码体制下的椭圆曲线加密算法才有的性质。
椭圆曲线加密除了明文和一些必要参数,还用到了一个随机选取的 k 值。这个 k 值不需要让解密者知道,不会影响解密,但 k 值的变化会影响密文的结果。
xiri
2020-01-09 10:14:20 +08:00
@xiri 我这里只是从纯理论层面说明,不考虑实际应用时存在的填充之类的行为
geelaw
2020-01-09 10:23:25 +08:00
@ThirdFlame #28 楼主觉得自己选择了 RSA 加密算法,应该同一明文得到很多不同的密文,回复中问为什么非对称加密都要明文有不同的密文。一个不安全的非对称加密算法(仅符合语法和正确性)当然没有必要有随机化的加密算法。显然讨论不安全的加密算法是否非要随机并不是楼上一些回复的疑惑。

另外,那个问题不是“我的问题”。

@xiri #29

之前我一直是说结论,懒得提症结,觉得还是需要点明一下:很多回复混淆了 RSA 陷门函数和(安全的) RSA 加密。
szvone
2020-01-09 10:36:48 +08:00
@bagel
@geelaw
@xiri
@ThirdFlame
@CEBBCAT

感谢各位大佬的回复,我遇到的问题是,如果在电脑上面跑 main 函数,那么这个加密结果是会变动,如果在安卓上用按钮事件触发,这个加密结果始终不变,在无法改动安卓代码的情况下,服务端应该如何编写这个加密过程
Delon
2020-01-09 10:41:54 +08:00
楼上就 @geelaw 一个明白人,楼主要查问题也要从 padding 上面查
Delon
2020-01-09 10:44:07 +08:00
收回第一句,楼上还是挺多明白人的,我眼瞎
jacklin96
2020-01-09 10:51:10 +08:00
@geelaw 看你的头像好像很眼熟 然后去 fb 看了一眼 发现你躺在我的推荐好友列表里
3dwelcome
2020-01-09 11:04:57 +08:00
RSA 有两种填充。
第一种叫签名报文(PKCS#1 Type 01),保证每次签名后,结果都不变,好知道谁签名的(比如 TLS 里的 RSA)。
第二种才叫加密((PKCS#1 Type 02),保证每次加密后,结果都变化,增加安全性。
bagel
2020-01-09 11:30:33 +08:00
我再详细说下吧

@szvone #32 你在 Android 上面调用 init 方式没有指定 iv,这是为啥每次结果都一样的原因。安全的做法是像下面这样调用
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivBytes));

@geelaw #27 Android 和 Java 上面实现不同,Android 默认没有用随机 iv 填充。这是实现的差异,两者都是符合规范的。spec 里原文是
If this cipher requires any algorithm parameters that cannot be derived from the given key, the underlying cipher implementation is supposed to generate the required parameters itself (using provider-specific default or random values)

参考: https://stackoverflow.com/questions/31036780/android-cryptography-api-not-generating-safe-iv-for-aes#31037133
szvone
2020-01-09 15:33:18 +08:00
^_^已经完全理解,感谢各位大佬不吝赐教
@bagel
@3dwelcome

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

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

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

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

© 2021 V2EX