V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
XuYijie
V2EX  ›  程序员

接口加密问题

  •  
  •   XuYijie ·
    BubblingXuYijie · 160 天前 via Android · 2769 次点击
    这是一个创建于 160 天前的主题,其中的信息可能已经有所发展或是发生改变。
    亲爱的同僚们,我目前在学习接口加密,就是请求参数和返回值加密,假如使用 rsa 的话:服务端生成一个密钥对,前端生成一个密钥对,互相交换公钥,就可以使用彼此的公钥和自己的私钥进行加密解密了,问题是前端的私钥存在哪里呢?放在代码里,本地存储里,cookie 里,都有被盗取的风险吧,难道是不存储密钥,每次调用接口都要临时生成秘钥吗?
    31 条回复    2024-06-21 16:35:58 +08:00
    FengMubai
        1
    FengMubai  
       160 天前
    是的, 一次一密. 客户端私钥只存在于内存里
    XuYijie
        2
    XuYijie  
    OP
       160 天前 via Android
    @FengMubai 好的,没做过要求加密的项目,不敢往那方面想,听说 rsa 密钥生成挺消耗性能的
    soar0712
        3
    soar0712  
       160 天前
    服务器生成 rsa 公私钥对,公钥是公开的,前端 js 生成 aes key ,用 aes 加密明文数据,用服务器的公钥加密 aeskey ,将加密后的数据和加密后的 aeskey 都传给服务器,服务器用私钥解数据拿到 aeskey ,再用 aeskey 解密密文,最后拿到明文数据
    soar0712
        4
    soar0712  
       160 天前
    @soar0712 这只是最基础的加密逻辑,还需要加上时间戳校验、哈希校验什么的,也就是防重放那一套逻辑
    ren2881971
        5
    ren2881971  
       160 天前
    不是这样的 如果加密数量量比较大的话,非对称加密的性能很差。
    一般都是通过密钥协商出来一个对称密钥对通信中的数据进行加密。比如:
    在客户端侧:客户端私钥+服务端公钥进行密钥协商
    在服务端侧:服务端私钥+客户端私钥进行密钥协商。
    协商出来的这两个密钥是一致的,你就可以当作是对称密钥来用。 在协商过程中。双方的私钥不见面,而且也不涉及到对称密钥传输的问题。
    HTTPS 或者说 TLS 就是大致这么做的。
    但听你的需求,你好像是想做信源加密。那你做数字信封就好。就是用服务端的公钥对数据加密密钥做加密,然后数据加密密钥对数据做加密,如果有防篡改的需求,也可以做个签名。
    ren2881971
        6
    ren2881971  
       160 天前
    一般单向 TLS/SSL 认证就够用啦,它来帮你做信道保护。
    你用数字信封做个信源加密就好。 客户端生成个随机数作为数据加密密钥就够了。
    XuYijie
        7
    XuYijie  
    OP
       160 天前 via Android
    @ren2881971 我纠结的是,客户端这边存放密钥的安全性问题,特别是 web 项目,协商出来的密钥一放到前端那不是 f12 就能找到
    Kathy1989
        8
    Kathy1989  
       160 天前
    放环境变量 env 里
    FengMubai
        9
    FengMubai  
       160 天前
    @XuYijie #2 所以一般用 aes 加密, 用服务端公钥把 aes 密钥加密后发出去
    ren2881971
        10
    ren2881971  
       160 天前
    @XuYijie 客户端不用私钥呀。 你每次通信的时候 都是客户端生成的随机数作为 对称加密密钥 A ,这个密钥是个临时的,只对本次会话负责。 对称加密密钥 A 加密数据,然后用服务器的公钥 B 加密 A 就好了。把加密好的 A 和加密数据 一同发给后端服务。
    ren2881971
        11
    ren2881971  
       160 天前
    服务端接收数据后,用服务端的私钥解密,获得密钥 A ,然后再用密钥 A 解密数据就好。
    XuYijie
        12
    XuYijie  
    OP
       160 天前 via Android
    @ren2881971 嗷嗷,也是每次请求重新生成,好的好的
    ren2881971
        13
    ren2881971  
       160 天前
    @XuYijie 其实就是生成个伪随机数而已。 对性能也没啥损耗,1 、起到了保护作用。2 、一次性密钥也不用费神研究密钥保护的事情。
    renoooo
        14
    renoooo  
       160 天前
    那服务端的公钥被盗取之后不是也一样可以走这套流程往服务端发数据吗
    @ren2881971
    hefish
        15
    hefish  
       160 天前
    参见 DH 密钥交换算法。
    XuYijie
        16
    XuYijie  
    OP
       160 天前
    @renoooo 能盗取服务端密钥的只能是顶级黑客,而客户端的密钥一般我就能盗取
    kuanat
        17
    kuanat  
       160 天前
    #3 @soar0712 说的就是标准做法。

    现在不明确的是为什么要加密,防的是谁。谁让你这么干就问他,这么干的目的是什么,只有这么一种实现方式么,这么做能抵御哪些攻击。

    提这个需求的大概率不懂,所以你也会跟着迷糊。你也可以试着思考一下,然后再过渡到为什么要存密钥,有没有必要存密钥,如果有必要存到哪里的问题。

    当然我个人的意见是前端针对请求参数和返回值“加密”是没什么意义的(除非这个网页应用就是提供 e2e 加密的),搞“签名”还可以防机器人。
    XuYijie
        18
    XuYijie  
    OP
       160 天前
    @kuanat 我也想不通有 https 为什么还需要对整个接口数据进行加密,但是确实存在这样的公司,例如国家医保的支付接口
    renoooo
        19
    renoooo  
       160 天前
    @XuYijie ren2881971 说的方法是防止信道不安全的问题,你的问题是服务器识别信源的问题,识别信源的问题就是要每次都要生成新的,soar0712 说的这种就是识别信源,你也可以了解一下 kerberos
    kuanat
        20
    kuanat  
       160 天前
    @XuYijie #18

    可能是比较机械地执行等保规定吧……既然这样的话,按照对面的要求执行就是了。

    如果直接用非对称加密,你只需要拉取公钥。如果用对称加密,你一样要拉取公钥,对称加密的密钥肯定是用非对称公钥加密保护一起传回去的。

    不论哪种情况你都不需要保存私钥。
    sampeng
        21
    sampeng  
       160 天前   ❤️ 1
    这个问题 v 里面讨论过很多次了。https 对链路的安全保证已经足够了。
    你要是考虑本地存储,cookie 被盗。首先,这两个东西被盗本身就是一个伪命题。1 ,成本巨大,只有电脑被黑中毒着一种情况。所以没人把密码存着里面。2.为啥要服务端返回什么你就存什么呢。你就不能自己再用 js 加密一次?你要是总是想着反编译就能看出逻辑来。。实话实说,99%的人做不到。

    第三,这种问题没必要自己猜和想,学习他人经验就好了。你的业务量再大有 aws 的业务量大?有他的安全性要求高? aws 的这些东西泄漏就是很多很多很多钱。。aws 的 client 都是现成开源的,分析 client 的请求签名逻辑就好了。aws 的接口内容都不需要加密。为啥你的接口需要?只需要保证 1 ,走的 https 。2 ,有签名确保是从可信 client 发出来的。接口安全到这个级别就够了。否则。。。拉 vpn 吧。。。。。
    ianisme
        22
    ianisme  
       160 天前
    加解密没有绝对的安全,只是为了做到相对安全,例如黑客他掌握了反编译、动态调试等技术,可以模拟出一个客户端的所有请求去和服务端交互,甚至对于 APP 来说直接 hook 相关代码把解析后的明文日志直接拿到都省略破解密钥这步了。
    ianisme
        23
    ianisme  
       160 天前
    @soar0712 和 @ren2881971 讲解的很清晰
    iOCZS
        24
    iOCZS  
       160 天前
    @XuYijie https 存在中间人攻击的问题,如果避免这种情况,他的确是安全的。中间人攻击就能看到明文了,如果明文是你说的接口加密,那仍然看不到解密后的东西,多了一层安全性。
    Sukuyedai
        25
    Sukuyedai  
       160 天前
    你需要的是这个: https://github.com/ti-dh

    流程上是 client 和 server 会通过交换公有信息后,各自分别在自己这里计算出一个用于对称加解密的 key ,这个 key 不会在网络上暴露。

    但是 DH 本质上只能提升一些成本且无法根治中间人劫持问题,但是,应该足够解决你的问题。
    NickX
        26
    NickX  
       160 天前
    难道上 HTTPS 还不够么,什么接口安全度需要用到参数的加密?除了密码不能明文外,没接触过还有什么场景要加密的。
    longlonglanguage
        27
    longlonglanguage  
       160 天前
    “问题是前端的私钥存在哪里呢?放在代码里,本地存储里,cookie 里,都有被盗取的风险吧,难道是不存储密钥,每次调用接口都要临时生成秘钥吗?”加密是为了防止传输过程中被人窃取,担心客户端的密钥泄露,纯属多余,他自己电脑存储的密钥都被获取了,估计客户端都被人下木马了。
    ren2881971
        28
    ren2881971  
       159 天前
    @renoooo 那你这是不可否认性的需求。 可以客户端本地生成密钥对,然后用私钥签名数据,公钥跟数据一起加密,作为数字信封一部分发给服务端。 服务端用他的服务器私钥先解开 数据密钥然后用数据密钥解出来数据和客户端公钥,客户端公钥验签通过后,再解密数据。 机密性、完整性、不可否认性的保护就都做了。
    别问我客户端私钥怎么保护。。。。 你可以临时生成。 或者你用个 usb key 保护下?
    密码保护这玩意 就是增加破解难度而已。
    soar0712
        29
    soar0712  
       159 天前
    @kuanat 貌似回复错楼层了吧
    horizon
        30
    horizon  
       159 天前
    @NickX #26
    防客户逆向
    NickX
        31
    NickX  
       159 天前
    @horizon 具体场景说说
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1764 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 16:36 · PVG 00:36 · LAX 08:36 · JFK 11:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.