V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
szandy6
V2EX  ›  问与答

客户端签名密钥如何存储才能保证安全?

  •  
  •   szandy6 · 249 天前 · 1387 次点击
    这是一个创建于 249 天前的主题,其中的信息可能已经有所发展或是发生改变。

    客户端请求 API 时,一般要带上签名信息,签名参数用的密钥( secret key)怎么存储才能保证安全,还是说有其他更好的方案,比如放在服务端,大家一般是怎么做的。

    第 1 条附言  ·  249 天前
    在网上也看到很多人说 https 环境下,没必要在对参数进行签名,国外很多大厂的 Open API 都是没有签名的,这种说法很有道理,我也挺赞同的。但在国内,没有几个大厂的 Open API 是不签名的。
    30 条回复    2023-08-23 15:46:42 +08:00
    dzdh
        1
    dzdh  
       249 天前
    webauthn ?
    EchoAI
        2
    EchoAI  
       249 天前 via Android
    我们目前是这么做的:Android 使用 so 文件,iOS 使用 a 文件,web 使用 wasm 文件。密钥和算法都在内部实现,同时做了很多防反编译的策略。
    szandy6
        3
    szandy6  
    OP
       249 天前
    @EchoAI 我们之前也是这么干的,不过安全部门说会被反编译出来。
    EchoAI
        4
    EchoAI  
       249 天前
    只要是密钥需要存储在客户端,就会被拿出来。只是时间的问题。绝对的安全是不存在的。
    szandy6
        5
    szandy6  
    OP
       249 天前
    @EchoAI 是的,能做的就是提高一点破解的复杂度,没有绝对安全。
    tool2d
        6
    tool2d  
       249 天前
    我看到过的版本是密钥和时间强相关,客户端 6 小时就会变动一次,用算法生成的。

    要破解密钥容易,要拿到算法还是有一点难度的。
    0o0O0o0O0o
        7
    0o0O0o0O0o  
       249 天前 via iPhone
    先说观点:放在客户端的全部都是能够被公开的东西。

    > 安全部门说会被反编译出来

    一些白盒密码方案大约就是为了应付这种情况,说是应付,因为它们和 #2 在一部分攻击者看来没有太多本质区别。
    xiangyuecn
        8
    xiangyuecn  
       249 天前
    http 时代的遗留产物。
    yinmin
        9
    yinmin  
       249 天前 via iPhone
    一了百了的方案是改成不对称加密。客户端保存 rsa 公钥(是公开的,没必要保密),客户端用 rsa 公钥加密数据后上传,服务器用 rsa 用私钥解密。

    直接从理论上解决问题。
    edwardhodges
        10
    edwardhodges  
       249 天前
    客户端不要直接请求这个 API 。客户端请求自己的业务服务器,然后服务器来请求这个 API ,密钥放在服务器就好了。
    tool2d
        11
    tool2d  
       249 天前
    @yinmin 不行哦,客户端能用 rsa 公钥加密,那么黑客也能用 rsa 公钥加密。

    服务器收到后,都能解密。分不清哪个是黑客签名,哪个是真客户端签名。
    mdn
        12
    mdn  
       249 天前
    @edwardhodges 业务服务器如何分辨是自己的客户端了
    hsfzxjy
        13
    hsfzxjy  
       249 天前
    放在系统原生的钥匙串应该安全吧?比如安卓的 https://developer.android.com/reference/android/security/KeyChain
    szandy6
        14
    szandy6  
    OP
       249 天前
    @yinmin HMAC 与加密需求不一样,如果是数据加密,现在非对称加密是比较成熟的方案。
    SteveRogers
        15
    SteveRogers  
       249 天前 via iPhone
    密钥本地二次加密、二加密后的密钥分开存储,然后放到多处。
    xiaoke
        16
    xiaoke  
       249 天前 via Android
    搭车请教,看到一些安卓 APP 直接把证书文件放在 assets 目录下,有风险吗?
    0o0O0o0O0o
        17
    0o0O0o0O0o  
       249 天前 via iPhone
    @tool2d #11 你说的这是客户端软件层面 **无解** 的事情(包括白盒),客户端的所有混淆都可以被分析所有逻辑都可以被模拟,只是难易度的区别。

    > 分不清哪个是黑客签名,哪个是真客户端签名

    这对应的应该是一个完整的风控系统,而不单纯是客户端该考虑的
    iX8NEGGn
        18
    iX8NEGGn  
       249 天前 via iPhone
    你没搞明白,国内大厂的 api 签名是为了防止重放攻击,参与签名的参数一般都包含时间,你这个属于 SSL Pinning ,为了提升绕过客户端请求的难度,破解是避免不了的,只是增加破解难度而已。
    rocmax
        19
    rocmax  
       249 天前 via Android   ❤️ 1
    一般应用加密只是为了防止篡改请求。如果你的应用真的需要用签名核实身份(例如比特币钱包类),请使用 HSM 。如果是手机应用的话内置加密模块有类似功能,可以保证密钥不离开硬件。
    edwardhodges
        20
    edwardhodges  
       248 天前
    @mdn 已经是业务服务器了,那就可以设置自己的登录等业务了。登录后获取 token ,用 token 来做校验不是常规操作?
    mdn
        21
    mdn  
       248 天前
    @edwardhodges #20 客户端加签名在没有被破解的情况下都是 信任的客户端,token 无法证明是客户端请求的 API
    edwardhodges
        22
    edwardhodges  
       248 天前
    @mdn 是不是想复杂了。这个跟客户端没有什么关系吧,举个例子,token 根据手机号登录验证后获取,然后根据当前用户的 token 来请求业务服务器。业务服务器根据这个 token 判断是哪个用户,然后业务服务器再来调用比如 openai 的接口。就是说使用 secret key 调用三方 api 的行为是发生在自己服务器的。 而客户端的验证方式就是传统的验证方式,所有 app 都是这么进行的。 客户端就是被破解了又怎么样,最多知道了 api 接口(客户端里面没有保存三方的 secret key 这些信息),那又怎么样。
    CodeCodeStudy
        23
    CodeCodeStudy  
       248 天前
    @yinmin #9 非对称加密太慢了,不应直接用非对称加密数据,而是用非对称加密对称加密的密钥,然后用对称加密数据
    mdn
        24
    mdn  
       248 天前
    @edwardhodges #22 客户端加签名,想要防止某些用户绕过客户端直接请求接口,比如签到等功能,token 用户自己也能看到,签名需要用户破解
    IvanLi127
        25
    IvanLi127  
       248 天前 via Android
    签名是防谁篡改负载?防非法用户篡改用登录凭据,防网络链路爱咋存咋存,防合法用户那得靠硬件了。
    msg7086
        26
    msg7086  
       248 天前
    @tool2d #11
    > 分不清哪个是黑客签名,哪个是真客户端签名。

    要不然呢?难道你还能分清你对面的是客户端还是黑客?
    EchoAI
        27
    EchoAI  
       248 天前 via Android
    @edwardhodges #22 客户端被破解了,不仅知道了 API ,用户的 token 也能被拿到,还省得去破解密钥了,直接使用 token 请求 API 就可以了。
    tool2d
        28
    tool2d  
       248 天前
    @msg7086 你普通 ssh 连接,服务器可以设置客户端指纹的白名单。就算黑客有密码和密钥,只要客户端指纹不对,服务器也是可以拒绝请求的。

    客户端被挟持发请求,和黑客第三方 IP 发起恶意请求,对服务器来说,还是有区别的。
    edwardhodges
        29
    edwardhodges  
       248 天前
    又看了下讨论,如果想把请求绝对限制在自己指定的客户端里,理论上只能增加难度,无法绝对的。不清楚大家的需求,感觉这个需求本身意义就不大吧。 使用加固混淆等方式,增加客户端 app 被破解的难度,所有请求必须使用信任机构颁发的证书的 https ,不在客户端存放重要的信息,验证流程通过服务器来校验。这些操作下来,理论上已经很安全了吧。
    msg7086
        30
    msg7086  
       248 天前
    @tool2d 客户端可以视作开源,黑客直接伪造指纹就行了。
    有些时候是不需要从头开始搞的,拿现成的代码来植入点东西跑可能会更方便。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   885 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 20:09 · PVG 04:09 · LAX 13:09 · JFK 16:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.