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

为什么京东支付接口的签名算法是用私钥加密而不是用私钥签名?

  •  
  •   v4j7o9m7s2 · 2017-09-09 00:49:05 +08:00 · 6167 次点击
    这是一个创建于 2614 天前的主题,其中的信息可能已经有所发展或是发生改变。
    对接京东支付的时候,发现官方文档上写着 ‘私钥证书进行加密,并进行 base64 转码,得到签名字符串 sign ’。
    最开始的时候以为是笔误,想表达的是 ’私钥证书进行签名‘,但是测试之后发现真的是用私钥进行加密。
    看了一下 rfc2313,发现 rsa 的确是支持用私钥加密的,但是为什么要这样做呢?是有什么安全性上的考虑吗?求解。
    25 条回复    2018-04-10 01:00:17 +08:00
    billlee
        1
    billlee  
       2017-09-09 03:03:29 +08:00
    RSA 签名,就是用私钥做加密操作
    FanWall
        2
    FanWall  
       2017-09-09 03:12:23 +08:00 via Android
    1#正解,rsa 签名本质上就是私钥加密处理后的哈希值
    LxExExl
        3
    LxExExl  
       2017-09-09 03:48:10 +08:00 via iPhone
    私钥证书其实就是私钥签名
    msg7086
        4
    msg7086  
       2017-09-09 03:55:07 +08:00
    私钥签名 = 明文 + HASH(私钥加密)

    本质上差不多。
    msg7086
        5
    msg7086  
       2017-09-09 04:02:03 +08:00
    我上面说的好像有点问题。加密的话理论上应该用公钥做加密。但是公钥和私钥本身就是可以互换的。
    比如说你手里有 key1,京东有 key2,你用 key1 做运算的话其实是相当于用公钥加密,key2 才是私钥。
    这种时候 key1 可以公开,而 key2 必须保密。这种做法主要用于传输数据的保密而非认证。
    不知道你说的是不是这种情况。

    又如果 key1 和 key2 都是保密的,那这时候就可以同时做加密和认证了。
    Shura
        6
    Shura  
       2017-09-09 08:01:13 +08:00 via Android
    因为数字签名的原理就是私钥加密,公钥解密。
    leeg810312
        7
    leeg810312  
       2017-09-09 09:23:43 +08:00 via Android
    你的概念理解错了吧。公钥和私钥在数学上是相关的一对秘钥。公钥可以用私钥计算出来,但反过来极其困难,按现有技术相当于不可能或不实际,即所谓不对称算法,因此公钥当然是公开的,何来保密?只有私钥才要持有人保密。公钥加密明文,自然只能用私钥解开。反过来,用私钥加密,只能用公钥去验证是不是对应的私钥。
    v4j7o9m7s2
        8
    v4j7o9m7s2  
    OP
       2017-09-09 09:56:10 +08:00
    @billlee
    @FanWall
    @LxExExl
    @msg7086
    @Shura
    我知道 rsa 签名算法内部的实现有用到 私钥加密+ message digesting + data encoding。
    我的疑问是为什么京东选择只用私钥加密来签名,而把 rsa 签名算法里面的其它部分抛弃了?
    flowfire
        9
    flowfire  
       2017-09-09 10:05:28 +08:00 via Android
    @leeg810312 我觉得你理解错了吧,公钥和私钥都互相不能计算出来,公钥和私钥的唯一区别就是一个公开一个不公开。当然如果你说的不是 RSA 加密那当我没说………
    superbear
        10
    superbear  
       2017-09-09 10:17:33 +08:00 via iPhone
    看使用场景。
    1. 加密 公钥加密
    2. 签名 私钥加密

    公钥私钥是成对的,公钥加密的内容只能用对应的私钥解密;反之亦然。

    你这个是签名场景,签名的意思是表明这个信息是签发者发出的,而不是别人伪造的。京东拿到你的请求,用公钥解开了,一定是你的私钥加密的。私钥是保密的,支付过程中出了问题只可能是你这边私钥泄密了;而加密场景,举个例子,对方用你的公钥加密了一条消息,这条消息只有拿着私钥的人可以看到。

    总之,公钥是指公开的密钥,私钥是指保密的密钥,并没有限定只能用其中的一个加密,另一个解密。
    leeg810312
        11
    leeg810312  
       2017-09-09 10:22:13 +08:00 via Android
    @flowfire 只有没有深入理解非对称加密体系的人才会认为公钥和私钥是可以随意互换的。非对称的 2 个秘钥必须是数学上相关的,不仅是指 2 个密码不同,而且是互相推导的难度不对称,私钥可以推导公钥,反过来难度极高。所有非对称加密体系都是这样的模式。你要是理解这些概念,就不会说这么好笑的结论了。rsa 的数学模型估计你也没有了解一个大概,可能认为非对称就是随便写 2 个秘钥就可以了。
    keyfunc
        12
    keyfunc  
       2017-09-09 10:22:32 +08:00
    私钥是用来签名的,不能加密吧。公钥加密,私钥解密。私钥签名,公钥验签。
    leeg810312
        13
    leeg810312  
       2017-09-09 10:33:14 +08:00 via Android
    @flowfire 补充一点,实际使用中不能用私钥计算公钥的情况,是因为部分库和系统将私钥计算公钥的部分参数去掉了,可不是因为算法本身不能计算。
    alcarl
        14
    alcarl  
       2017-09-09 10:37:44 +08:00 via Android
    @v4j7o9m7s2 不用其他部分,可能是因为如果公钥不公开的话,私钥同样可以起到加密的作用吧。也可能数据中没有需要加密的内容也说不定,没有看接口,只能是猜的
    ETiV
        15
    ETiV  
       2017-09-09 10:45:20 +08:00 via iPhone
    没看过京东文档,但感觉它这里加密、签名在这里的区别:

    - 加密传输全密文(参数之类的也都加密在密文里),强制密文接收方解密后才能读到参数
    - 签名传输明文+签名,接收方可以忽略校验签名,直接读取参数
    ShareDuck
        16
    ShareDuck  
       2017-09-09 11:15:52 +08:00
    @leeg810312 我觉得 @flowfire 的理解才是对的,RSA 的加密体系,用 A 密钥加密的数据可以用 B 密钥解密,用 B 密钥加密的数据可以用 A 密钥解密,公、私钥本来是相对的。但主流的编程框架,实现 RSA 算法时,将 A、B 其中一个用为“公钥”,这里举例为 A 为公钥吧,但私钥他同时保存了 A 和 B,所以私钥是不能公开的,公开了就毫无意义了。私钥是同时保存了两个密钥,而不是用其中一个可以推出另外一个。密码学我也只知道皮毛,如有错误,欢迎指正。
    gamexg
        17
    gamexg  
       2017-09-09 11:27:23 +08:00   ❤️ 1
    @ShareDuck #16 千万别这么理解。
    公钥私钥加密的理论是大数分解,公钥是两个大素数乘积,私钥是两个大素数本身,通过私钥可以简单的计算出公钥。

    解读 RSA 公钥私钥储存格式
    http://www.10tiao.com/html/635/201707/2650105399/1.html


    三、分析公钥
    第三部分如下:
    前四字节是字符串 00 00 00 81 对应整数 129,然后后面有 129 个字节,对应素数积 n。

    RSA 密钥协议如下:
    第六部分是 0x0241 代表第一个素数,长度为 65 字节。
    第七部分是 0x0241 代表第二个素数,长度也是 65 字节。


    另外如果可以控制原文,那么可以降低通过密文暴力破解密钥的难度,所以靠谱的签名机制是私钥加密 hash(原文+盐)。
    ShareDuck
        18
    ShareDuck  
       2017-09-09 11:55:42 +08:00
    @gamexg 你的解析非常清楚明白,谢谢你。我的私钥和公钥理解概念有误。
    flowfire
        19
    flowfire  
       2017-09-09 12:23:01 +08:00 via Android
    @gamexg 我刚刚去维基查了一下 RSA 的原理,我觉得应该是这么理解。
    RSA 的数学理论中,根据两个大素数,计算出两个数 e 和 d 以及自己两个素数的乘积 N,最后得出 N,e 和 N,d 两个组,这两个组是完全对等的,可以互相加密解密,并且无法互相推导,但是在 RSA 标准里,为了明确区分私钥和公钥,因此将大素数本身编码进了私钥中。
    flowfire
        20
    flowfire  
       2017-09-09 12:34:57 +08:00
    @gamexg #17 可能我没说清楚= =,应该是这样的
    取两个大素数,p 和 q,其积为 N,然后经过运算,算出 d 和 e,那么组 [ N, d ] 和 组 [ N, e ],是完全对等的,除了分解 N 外没有其他方法互相推导,这两个组是完全可以互换的,
    但是在实际操作和标准中, 将 [其中一个组 + 大素数本身 + 其他信息] base64 编码后称之为私钥,将 [另一个组 + 其他信息 ] base64 编码后称之为公钥,因此按照标准编码过后的公私钥是不能互换的。
    因此公私钥不能互换是因为 [人为添加了额外信息] 而不是因为 [算法本身的问题]
    @ShareDuck #18
    Citrus
        21
    Citrus  
       2017-09-09 12:49:41 +08:00 via iPhone
    从 RSA 原理上来说,公私钥是对等的。但是从实际应用来说,为了加快计算速度,我们一般都取 e 为 65537。这样的话,如果你保密了 65537,别人直接就能猜出来了。。。
    GuuJiang
        22
    GuuJiang  
       2017-09-09 13:02:38 +08:00   ❤️ 1
    @gamexg
    #17 你的结论碰巧是正确的,然而论证是错误的
    首先“公钥是两个大素数乘积,私钥是两个大素数本身”这句话是错误的,你下面的例子里的那两个大素数并不是私钥本身,而是用于生成公私钥的元素,虽然现有的工程实践中在设计私钥文件格式时顺便保存了这两个大素数,然而在使用私钥进行加解密时并用不到他们,换句话说你完全可以自己设计一种密钥文件格式,公私钥中都不保存大素数,也完全不影响使用
    除了上面这个原因,还有另一个原因,为了下文简便先将 RSA 密钥的生成过程粗略地描述下,详细的过程在任何一篇 RSA 算法细节的文档中都能找到,生成两个大素数 p 和 q,乘积为 n,生成随机数 e,利用 n 和 e 计算出 d,注意这里已知 n 和 d 的话同样是可以计算出 e 的,二者地位等同,n 和 e 及 n 和 d 分别作为公私钥,然而现有的实现中 e 并不是用随机数,而是固定值 65537,于是只能 n 和 e 作为公钥,n 和 d 作为私钥,并且私钥文件中同时还保存了 pq 等其他信息
    综上所述,公私钥不能互换并不是算法本身决定的,而只是现有工程实践的特例,原始的 RSA 算法中二组密钥实际地位等同,谁是私钥谁是公钥完全取决于后续使用时谁公开谁保密
    GuuJiang
        23
    GuuJiang  
       2017-09-09 13:04:21 +08:00
    @flowfire @Citrus 呃,发出去以后才刷出二位的回复,你们基本把我想说的说完了
    pynix
        24
    pynix  
       2017-09-09 23:45:13 +08:00
    稍微了解点密码学理论基础也是好的。。。
    mrathena
        25
    mrathena  
       2018-04-10 01:00:17 +08:00 via iPhone
    通常认为,京东用私钥加密,那么持有京东公钥的客户都可以解密,这种情况下,默认京东只使用唯一一套公私钥,下发给客户的公钥都是相同的。
    如果京东为每个客户都生成一套新的公私钥,分配给客户的公钥都是不同的,一对一,那么用哪个来加密就无所谓了,反正别人都不知道,只有自己能够解密
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   981 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:49 · PVG 04:49 · LAX 12:49 · JFK 15:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.