这是一个创建于 814 天前的主题,其中的信息可能已经有所发展或是发生改变。
最近在看安全方面的知识,为了防止重放攻击,我查阅了一些资料。
also24 的回复说得非常棒。
单向的 https 只能保证你请求的银行真的是银行,但银行无法确定你是你。
加了 token 才能让银行知道你是你,但是银行不知道你带的东西是你自己带的,还是别人塞进你包里的。
加上 nonce 和签名,才能让银行知道这些东西全都是你带的,别人没有夹带,但是银行不知道这个你,是否是用 1 年前的你克隆出来的。
加上时间戳,银行才能确定面前的你确实是当前时间点真实存在你,东西也是你带的东西。
最后,稀奇古怪的加密又是什么呢? 答:你带的东西是一个保险箱~
但是我有一个疑问,产生签名是需要密钥的,那怎么安全地在 web 前端存储私钥呢?
46 条回复 • 2021-07-04 22:38:40 +08:00
1 janus77 2021-07-03 23:20:02 +08:00浏览器的环境实现吧,浏览器这个软件本身是利用了操作系统的功能,和硬件做了交互。 |
3 xmumiffy 2021-07-03 23:36:03 +08:00 via Android这种都是服务端间的交互方式,密钥直接写在代码里的。 |
4 FaiChou 2021-07-03 23:38:29 +08:00 via iPhone 2你是想在网页端做 ssl pinning ? 前端私钥怎么来的?服务器给的?服务器给的时候就可能被窃取。 安全存储了私钥,你得用代码获取它吧,你的代码能获取,怎么保证其他代码不能获取? 前端的东西都是透明的,不像 app 客户端可以封在包里,不过封在包里也可以被越狱 /root 来篡改。楼主想要的绝对安全的地方,不存在的。 |
5 hahasong 2021-07-03 23:40:48 +08:00jwt 就行,已经标准化了 |
8 IvanLi127 2021-07-04 00:06:25 +08:00 via Android我觉得每次都输入密码,用密码签名所有参数和时间戳,就能保证收到的东西就是你现在发送的。这个密码存可信的地方才行,你相信浏览器,那就能安全存储了。如果不相信自己,每次输入密码都没用 |
9 walpurgis 2021-07-04 00:16:12 +08:00带签名的接口一般都是给服务端调用的,原帖没有任何地方提到前端 |
11 binux 2021-07-04 00:23:06 +08:00 via Android浏览器安全是由浏览器保证的,你作为前端无论做什么都是没用的 |
12 JasonLaw 2021-07-04 00:25:49 +08:00 via iPhone@walpurgis #9 是的,一般都是服务端请求服务端,原帖没有提到前端。但我的问题是关于浏览器端请求服务端。 |
13 SP00F 2021-07-04 00:29:14 +08:00前端是防小人,不防君子。 都不信任,那就只能走一律不信的态度了 |
14 3dwelcome 2021-07-04 00:41:59 +08:00"怎么安全地在 web 前端存储私钥?" 但是有两点额外要素,第一是解密后私钥只确保使用一次后就失效。第二是每次用代码生成不一样的加密算法,就是前端存的不是私钥的解密密码,而是生成的解密代码虚拟机本身,比如 WEBASM 。 |
15 also24 2021-07-04 00:50:07 +08:00 7感谢认可之前的回答,本身不是专门做安全的,可能还有很多纰漏。 具体到本帖的问题,我觉得不妨先定义一下『安全的存储』指的是什么。 首先,『安全的存储』可能是指:让这个私钥不出现在前端代码里。 按这个思路,为了复用这个私钥,需要将其存储在本地,可选 Cookie 或 localStorage 来存储。 考虑到 Cookie 会被自动发送,相对来说更建议使用 localStorage 来存储私钥。 但是有些机智的朋友就说了,我打开 DevTools,不就直接看光光了么? 那就要请出第三方存储了,例如 U 盾等专门存储密钥的东东就是专门干这个的。 那有些更机智的朋友肯定又想到了,那我直接破解你的 U 盾,导出你的私钥,不又看光光了么? 那有些搞催眠的朋友…………………… |
16 jadec0der 2021-07-04 02:12:58 +08:00银行? U 盾啊 |
17 unco020511 2021-07-04 02:27:26 +08:00--- 单向的 https 只能保证你请求的银行真的是银行,但银行无法确定你是你。 2. 只能保证你请求的是银行, 但银行无法确定你是你? |
18 unco020511 2021-07-04 02:33:40 +08:00如果你问的是 oath2, 那前端怎么会存储私钥呢 |
19 xuanbg 2021-07-04 04:57:30 +08:00 1所以银行会发你一个 usbKey 来存储证书啊。就是因为浏览器干不来这个事情,客户端任何常规存储方式都是不安全的。 |
20 JasonLaw 2021-07-04 07:27:18 +08:00 via iPhone |
23 mxT52CRuqR6o5 2021-07-04 09:23:14 +08:00 via Android私钥不私的话破坏了很多假设,安全性就无法保证 |
24 ZeawinL 2021-07-04 10:06:12 +08:00 via Android前端使用用户密码 hash 作为密钥? |
26 vibbow 2021-07-04 10:39:24 +08:00U 盾就是干这个事情的呀 |
27 unco020511 2021-07-04 10:43:31 +08:00@JasonLaw 非对称加密除了加密外, 还有一个应用叫做数字签名, 完整的非对称加密流程包括: 对原文非对称加密 + 签名, 也就是实际是将密文 (公钥加密的)+ 签名(实际为 hash 后用私钥进行一次非对称加密运算得到) 一起打包发送, 这样做既保证了数据不会被中间方窃听, 又保证了数据的完整性以及来源 |
28 JasonLaw 2021-07-04 10:43:36 +08:00 via iPhone@vibbow #26 前面已经有很多人说了这个了,如果没有其它想法的话,最好不要重复同样的东西。如果冒犯到你的话,我先说句抱歉,我只是不想让主题包含太多没意义的信息。 |
30 BoringBB 2021-07-04 10:50:21 +08:00 via Android使用客户端证书啊,在 ssl 握手的时候,服务器可以要求客户端提供证书来验证身份 |
31 geniussoft 2021-07-04 10:56:34 +08:00@also24 啥? U 蹲被破解? 以后开通网上银行,要求用户默背 2048 位密钥,并且熟练掌握口算非对称加密,绝对不能动笔😂 |
32 also24 2021-07-04 10:57:02 +08:00@unco020511 #17 『单向的 https 』 指的是 https 只有『单向加密』么? 那『加密』和『认证』有什么区别呢? 在最常见的『单向认证』的 https 使用形式中,只对服务器端进行了『认证』。 也就是,让你确认『你请求的是银行』。 但是此时,银行能通过这个 https 连接信息确认『你是你』么?当然不能,因为每个人都可以这样发起连接。 此时,如果引入『双向认证』,也就是客户端也持有一份证书,在 https 握手的时候发给服务端,服务端验证证书可信后才会放行。 最后小结: |
33 xylophone21 2021-07-04 11:19:44 +08:00 1说一下我的理解吧 |
34 JasonLaw 2021-07-04 11:57:56 +08:00@unco020511 #27 你说 “完整的非对称加密流程包括: 对原文非对称加密 + 签名”,但是我看了 https://en.wikipedia.org/wiki/Public-key_cryptography,里面所说的是: With public-key cryptography, robust authentication is also possible. A sender can combine a message with a private key to create a short digital signature on the message. Anyone with the sender's corresponding public key can combine that message with a claimed digital signature; if the signature matches the message, the origin of the message is verified (i.e., it must have been made by the owner of the corresponding private key). 按照它所说的,非对称加密是非对称加密,签名是签名,并不是 “包括” 的关系。 --- 还有你说 “签名是用私钥进行一次非对称加密运算得到”,我不同意加密这个说法,“签名是使用私钥产生的” 会更加准确。 --- 我对安全方面并不是特别了解,如果有错误的地方,希望你能够指出。 |
35 unco020511 2021-07-04 12:20:32 +08:00@JasonLaw #27 没错, 你说的更准确, 非对称加密不包括验签, 我想表达的是非对称加密与验签往往成套出现. 所以我用的是 "非对称加密流程", 而不是 "非对称加密" |
37 unco020511 2021-07-04 12:28:37 +08:00@also24 #32 抱歉, 我是没有看到你原贴后面楼层的内容, 只是看到楼主单独贴出的内容, 所以就进行了讨论, 误解了你的观点. 周末愉快 |
39 also24 2021-07-04 12:39:02 +08:00@JasonLaw #34 你们在讨论的『签名』,其实默认了在说『 RSA 签名』,是一种具体的签名机制。 原回复中的『签名』,其实是一个宽泛概念,只要能起到对内容验证的作用,就算签名,实际上,很多时候都在用更简单的方式来生成这种签名。 例如:md5(data + sk + nonce + ts) |
40 Lemeng 2021-07-04 14:42:17 +08:00u 盾,多少年前就可以。现在估计企业的银行业务都还是靠 u 盾,不过普通人用的少了 |
41 Quarter 2021-07-04 15:25:12 +08:00 via iPhone为啥私钥要在浏览器端存储啊,最多浏览器存存公钥就差不多了 |
42 Jooooooooo 2021-07-04 15:26:11 +08:00先用对称加密交换密钥, 这个交换过程公网公开可见 然后再用这个密钥干活 |
45 wooyuntest 2021-07-04 17:07:25 +08:00此处的签名 指的不是非对称加密算法(如 RSA 、ECC 等)算法中的签名、此处的签名指的只是对浏览器发出的 http 报文用前后端约定好的算法生成一个 sign 字段附在报文中,后段程序接到请求后,使用同样的算法再次计算 sign 并与你发送的报文中的 sign 字段比对,若 sign==sign 则认为报文没有经过篡改(在 App 没有被逆向得到加密算法的情况下),也就是你说的 “才能让银行知道这些东西全都是你带的,别人没有夹带”。 这种做法常常用在 App 中来防止用户抓包修改报文以实现一些爬虫、辅助功能或用来测试后段的安全性。(因为在拿不到签名算法的情况下,用户篡改的报文在 ckecksign 阶段就被拒绝了),在基于浏览器的 web 应用中不会有这种做法,如果在浏览器中使用这种做法,会直接将加密算法公开,使得这种验签来判断报文没有经过修改的方式失去意义。 // 但是这种做法银行还是没有办法确认你就是你,判断你访问的银行就是真正的银行,是基于 PKI 体系来实现的。所以目前银行用来判断你就是你,用的方法也类似。在硬件设备(也就是常说的 U 盾)中创建非对称密钥对,导出公钥并与你关联,私有永久保存在 u 盾中,认证的时候,有一个密码学常见的 challenge-response 过程来实现。(可以思考下 ssh 密钥对登陆的密码学原理) // 可以看下 webauthn 的介绍和文档,他实现了 passless,也是未来 web 认证的趋势。会有不少新的收获。 //ps 在配备有 Touch ID 的 Mac 上用 Safari 登陆 iCloud 的时候,只用验证指纹,思考下这个是如何实现的? |
46 Nyarime 2021-07-04 22:38:40 +08:00https://secure.quantumca.com.cn QuantumCA 的前端(下简称 “Secure Center”)颁发 SSL 证书平台采用了 WebCrypto + WebAssembly 的前端私钥方案 具体策略如下: 以上是我们采用的高性能的,解决信任问题的证书签发下发系统。 参考文献: |