V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lihongming
V2EX  ›  程序员

有没有什么加密算法是一对多的?

  •  
  •   lihongming · 2020-08-07 06:58:59 +08:00 · 4223 次点击
    这是一个创建于 1603 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有个项目可能需要用到一对多的加密传输,但我对加密没研究,求大佬们帮忙推荐个加密算法。

    需求如下:

    客户端: 每个客户端有自己的 key,发往服务端的信息都要用 key 加密后传输

    服务端: 接收客户端发过来的加密信息,然后用自己的 key 解密,并且能验证客户端身份(比如客户端编号是 123,则其必须用 123 的 key,或者 key 本身带编号也可)

    管理端: 可以根据服务端的 key 和客户端的编号生成无数多个客户端的 key

    服务端、客户端、管理端都是脱机运行的,不联网。所以更新服务端名单的方法不能用,只能依靠加密算法。

    24 条回复    2020-08-08 08:09:56 +08:00
    singerll
        1
    singerll  
       2020-08-07 07:16:16 +08:00 via Android
    非对称加密。。。
    RecursiveG
        2
    RecursiveG  
       2020-08-07 07:19:42 +08:00
    标准证书系统。

    你在管理端生成一对 CA 密钥对,把公钥丢到服务端去。然后给每个客户端生成私钥证书对,用 CA 私钥给证书签名。客户端用自己的私钥给数据签名并连着有 CA 签名的证书一起发给服务端。最后服务端用 CA 公钥检查客户端传过来的证书的签名。

    至于数据加密具体怎么做看你需求。
    steven_yue
        3
    steven_yue  
       2020-08-07 07:33:51 +08:00
    kerberos
    nvkou
        4
    nvkou  
       2020-08-07 07:41:37 +08:00 via Android
    这不就是证书链吗。服务器做个 CA,然后给各个客户端签发证书就是
    xyjincan
        5
    xyjincan  
       2020-08-07 09:11:25 +08:00
    GPG keys 你弄一个,所有客户端都能给你发数据啦,只保存一个就行,客户端自己带个编号,检查一下就行
    phpfpm
        6
    phpfpm  
       2020-08-07 09:23:54 +08:00
    u1s1 服务端客户端管理端都不联网那么之间是怎么沟通的。。。。
    zealic
        7
    zealic  
       2020-08-07 09:34:36 +08:00
    可以看看 Bitcoin 的 HD 钱包是怎么设计的。
    最终的结果就是一个根密钥,对应到几乎无限的公钥。
    根密钥所有者可以推导处所有私钥,派生父公钥持有者只能推导自己的下级公钥。

    https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
    geelaw
        8
    geelaw  
       2020-08-07 10:20:53 +08:00 via iPhone
    你需要的是一种高级签名算法和一种普通加密算法,因为你的要求是“验证客户端身份”,发送者有无数个,但接收者只是服务器一个。搜索 identity-based signature 有惊喜。
    Vegetable
        9
    Vegetable  
       2020-08-07 10:25:23 +08:00
    这个没什么特别的,比如 jwt 的 token,每次登录返回的都可以不一样。你只要在生成的时候填入不重复的填充信息就好了。
    常见的非对称加密比如 RSA 加密,也是有加盐过程的,每次加密的结果也不一样。其实都是一回事儿,加入点会变的垃圾就完了。
    jimmyismagic
        10
    jimmyismagic  
       2020-08-07 10:26:26 +08:00
    反正我知道 HD 钱包可以,ECC 本身既可以用于签名也可以用来加解密
    diaryevil
        11
    diaryevil  
       2020-08-07 10:32:12 +08:00
    基于对称加密和非对称加密的证书+SSL 方式
    qwerthhusn
        12
    qwerthhusn  
       2020-08-07 10:34:28 +08:00
    这种场景挺适合用 CA 签发证书的,如果是在线的话,直接 TLS 客户端认证即可。如果是离线的话,实现类似的功能比较麻烦了。。

    其实可以用一个非常简单的方案。。全程都用 AES (不用什么非对称加密或者数字签名)
    因为非对称加密只能加密一些比较小的数据,比较大的数据加密非常慢(一般都是先生成个临时的对称加密的 key,然后数据用这个 key 加密,最后再把 key 用非对称的加密一下)

    如下:::
    服务器存一个 key 叫 sk

    新增客户端:生成一个 key 叫 ck
    然后将客户端标志和 ck 加密一下得到 cke (还可以附带一些其他信息,比如 失效时间等)
    将 ck 和 cke 发给客户端(假设发送数据的链路是安全的,就是不会被截获,不安全的话就可能要用 DH 这类算法了)

    客户端每次请求的时候,用 ck 把数据加密
    然后发送给服务器加密的数据和这个 cke ( ck 不能发)

    这时服务端拿着 cke 用 sk 解密获得 ck 和用户信息
    然后用获得的 ck 去解密数据
    这两步只要有一步解密失败说明数据不合法

    这个够简单吧。
    xiangyuecn
        13
    xiangyuecn  
       2020-08-07 10:50:06 +08:00
    哪有怎么复杂,还要上 CA 体系?

    看需求,生成一对 RSA 密钥就完全够了,服务端持有 RSA 私钥,客户端持有 RSA 公钥。

    客户端传输时( U 盘?),随机生成一个 key (或者固定的机器码),用 RSA 公钥加密这个 key 生成密文 A,用 key 加密实际的数据生成密文 B,把 A 、B 组合到一起(生成一个文件放到 U 盘)传输。

    服务端收到数据后,拆分出 A 、B 密文,用私钥解密得到客户端随机 key,用 key 解密数据 B,得到实际数据。

    全程脱机运行,只要 RSA 私钥不泄露,炒鸡安全。

    ----
    不需要:“管理端: 可以根据服务端的 key 和客户端的编号生成无数多个客户端的 key” ,这个需求在这个体系下几乎没有意义。
    shawndev
        14
    shawndev  
       2020-08-07 10:52:59 +08:00
    两种方式:
    shawndev
        15
    shawndev  
       2020-08-07 10:53:52 +08:00
    1. 非对称加密数字信封:缺点是每新增一个接收方都要更新密钥部分
    2. 代理重加密
    lihongming
        16
    lihongming  
    OP
       2020-08-07 10:56:41 +08:00 via iPhone
    @phpfpm 通过 NFC 通讯的
    no1xsyzy
        17
    no1xsyzy  
       2020-08-07 10:59:31 +08:00
    这不是多对一吗?
    littlewing
        18
    littlewing  
       2020-08-07 11:08:25 +08:00 via iPhone
    这不就是 ca 吗
    lihongming
        19
    lihongming  
    OP
       2020-08-07 11:11:53 +08:00 via iPhone
    @xiangyuecn 谢谢,但这个设计的问题是无法授权客户端,因为公钥是公开的,任何人都可以拿着公钥说自己是合法的客户端。

    但你的思路我懂了,只要改一下,让管理端来生成客户端的 key,再发给客户端,就可以实现授权了。但这样管理端用的 key 也不能公开了,也就不需要非对称算法了
    keepeye
        20
    keepeye  
       2020-08-07 11:15:43 +08:00
    每个用户生成一对密钥,服务端保存私钥即可
    lihongming
        21
    lihongming  
    OP
       2020-08-07 15:36:21 +08:00 via iPhone
    @keepeye 这样新增用户的时候,服务端就不认识了,因为服务端是脱机的,无法录入数据
    LLaMA2
        22
    LLaMA2  
       2020-08-07 15:55:30 +08:00
    @lihongming 看到你 19 楼的回复,我想提醒一下,加密是为了传递过程中不被第三方窃取,而不是为了防止有人伪造合法的客户端,假定,你的客户端要给到客户的手里,那么他总有办法研究你的加密流程,他就一定能按照合法的流程组合好数据发送给服务端。

    你的需求可能需要出厂的时候每个客户端都已经内置好了校验用的标识符,比如说每个设备都会生成一个 UUID 带上并且这个 UUID 在服务端上是独一份的,客户端所有的发送数据都会基于这个 UUID 做文章,你的服务端就知道这个数据是某个 UUID 发给你的,然后服务端保存了一份客户端-UUID 的映射表,每次新出一批设备就会在服务端添加上。

    但是话又说话来,客户还是有办法基于他手里已经有的设备来伪造这个设备,不过他要伪造他手里没有的设备,那就只能靠猜了,毕竟只要你的 UUID 完全没有规律。
    BIAOXYZ
        23
    BIAOXYZ  
       2020-08-07 22:50:13 +08:00
    hierarchical identity-based encryption 或 attribute-based encryption,然后有一个常规的证书系统就可以了。
    lihongming
        24
    lihongming  
    OP
       2020-08-08 08:09:56 +08:00 via iPhone
    @ye4tar 就这个项目而言,加密不只是为了满足传输安全的需求,也是为了验证客户端的合法性。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1058 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:13 · PVG 03:13 · LAX 11:13 · JFK 14:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.