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

RSA 可以做私钥加密,公钥解密吗?解密的结果还是加密之前的明文吗?

  •  
  •   GuguguguDa · 2019-03-09 16:01:37 +08:00 · 14141 次点击
    这是一个创建于 2088 天前的主题,其中的信息可能已经有所发展或是发生改变。

    下面这个博客看的我很疑惑啊

    先不论私钥加密,公钥解密有没有意义

    私钥加密的结果,用公钥解密,还能解出来的吗?我试了下,居然还真可以?

    https://blog.csdn.net/wangqiuyun/article/details/42143957

    49 条回复    2019-03-11 08:52:07 +08:00
    sirgod
        1
    sirgod  
       2019-03-09 16:14:30 +08:00   ❤️ 1
    RSA 公钥跟私钥的作用是互逆的
    bzj
        2
    bzj  
       2019-03-09 16:25:35 +08:00
    先了解 RSA 的原理再来讨论有没有意义
    sadan9
        3
    sadan9  
       2019-03-09 16:32:35 +08:00
    数字签名了解一下
    LxExExl
        4
    LxExExl  
       2019-03-09 16:33:25 +08:00
    可不可以做? 可以做

    现实中有没有人这么做? 没有

    为啥呢? 因为加解密的对象不同。私钥持有者解密之后得到明文。公钥持有者解密之后得到摘要。不确切滴说,明文是肉眼看得懂的,摘要是肉眼看不懂的。
    3dwelcome
        5
    3dwelcome  
       2019-03-09 16:34:34 +08:00 via Android
    rsa 有两种应用,加密和签名,加密很有意义的,很多游戏数据加密就是用 RSA 配合 aes 来做的。
    lhx2008
        6
    lhx2008  
       2019-03-09 16:38:54 +08:00
    可以,有意义,可以验证是否是私钥加密的
    python35
        7
    python35  
       2019-03-09 16:40:59 +08:00   ❤️ 1
    rsa 算法秘钥有公钥和私钥,公钥是公开的,私钥是不公开的
    公钥加密的只有私钥持有者才能查看原文
    私钥加密的对应的公钥就能解开,但是公钥是公开的,所以所有持有公钥的人都能解开,这个严格意义上不算加密解密,而是私钥签名,公钥验签的过程
    GuguguguDa
        8
    GuguguguDa  
    OP
       2019-03-09 16:44:28 +08:00   ❤️ 1
    @LxExExl 诶?我试过,私钥加密,公钥解密,解密出来的是明文而不是摘要
    是加密的算法和签名的算法不一样导致的吧
    ThirdFlame
        9
    ThirdFlame  
       2019-03-09 16:49:20 +08:00   ❤️ 3
    当然可以。
    明文--公钥加密---密文--私钥解密---明文
    明文--私钥加密---密文--公钥解密---明文

    明文的哈希--私钥加密---签名---公钥解密----明文的哈希,若哈希值和明文的哈希值相同,则证明 明文的发送者,是私钥的持有者。

    不知道楼主看懂了没。 rsa 本身公钥 和 私钥 在加解密时,是可以互逆的。 根据加密的内容 和 方向不同,形成了 加密和 签名等用法。
    weyou
        10
    weyou  
       2019-03-09 16:49:30 +08:00 via Android   ❤️ 1
    @3dwelcome 签名其实也是加密,只是加密的对象是数字摘要。

    就 RSA 算法而言,私钥公钥是完全对等的,一个用作加密,另一个就可以解密。但实际应用中,为了性能考虑,对私钥公钥有不同的要求,比如 openssl 的公钥中的 e 就简单取了 65537,就是为了计算方便。这时候公钥私钥就最好不要互换。否者安全性得不到保证。
    3dwelcome
        11
    3dwelcome  
       2019-03-09 17:09:09 +08:00 via Android
    @weyou 据我了解,签名和加密是不太一样的。加密过程会填充随机 padding,以确保同一个数据,每次 RSA 加密的结果不同,提高破解难度。而签名刚好相反,需要每次结果都有一致性,已判断保护的数据块是否被篡改。
    GuguguguDa
        12
    GuguguguDa  
    OP
       2019-03-09 17:17:10 +08:00   ❤️ 1
    @3dwelcome 你可以试试 明文使用私钥进行加密,每次加密的结果是一样的,使用公钥加密,加密的结果是不一样的
    ThirdFlame
        13
    ThirdFlame  
       2019-03-09 17:28:19 +08:00
    @GuguguguDa openssl 使用私钥 加密时有填充选项。有的填充模式 就如,@3dwelcome 所说的那样。
    CEBBCAT
        14
    CEBBCAT  
       2019-03-09 17:44:05 +08:00   ❤️ 1
    在俺的理解里,公钥和私钥并没有本质上的不同,当你选择了其中一把作为私钥,另一把自动成为公钥,反之亦然
    dryadent
        15
    dryadent  
       2019-03-09 17:55:35 +08:00   ❤️ 1
    确实可以私钥加密,公钥解密。但是从 RSA 方案的设计角度来说,私钥加密,公钥解密这种方式安全性并无法得到保证,具体的你可以搜一下
    vinguo
        16
    vinguo  
       2019-03-09 17:56:50 +08:00
    楼主培训班出身?
    chinvo
        17
    chinvo  
       2019-03-09 18:03:50 +08:00 via iPhone
    搜一下可好?这个问题论坛里讨论不止一次了
    GuguguguDa
        18
    GuguguguDa  
    OP
       2019-03-09 18:03:51 +08:00
    @vinguo 虽然我不是 但我觉得培训班出身的人应该比你强
    CEBBCAT
        19
    CEBBCAT  
       2019-03-09 18:05:21 +08:00   ❤️ 1
    @CEBBCAT #14 好吧,我查了查( https://segmentfault.com/q/1010000002932436 ),本质上是一样的,但是 openssl 会把还多隐秘性的要素存进私钥的 pem,所以不能像我说的那样随意互换
    weyou
        20
    weyou  
       2019-03-09 21:46:53 +08:00 via Android
    @3dwelcome 并不是签名不可以加随机 padding,是没有必要。实际上加了 padding 也不应影响签名验证的结果,因为验证过程其实就是解密后比较 hash 值的过程,而 padding 并不会影响解密的结果。
    3dwelcome
        21
    3dwelcome  
       2019-03-09 22:19:37 +08:00
    @weyou 你说的没错,但是规范就是规范,对于符合 PKCS#1 V2.1 标准的 padding 类型有好多种,都是有严格限定,不能混用的。
    PADTYPE_SIGN 专用于签名报文,PADTYPE_ENCRYPT 专用于加密,PADTYPE_OAEP 结合 SHA256 算法,各司其职,各个 RSA 软件才能相互兼容。
    weyou
        22
    weyou  
       2019-03-09 22:58:47 +08:00 via Android
    @3dwelcome 是的,在实际应用中,公钥用来加密,私钥用来签名,不能互换,这是规范。但就楼主所问问题而言,RSA 算法在数学上公钥私钥其实没什么不同,任选一个作为公钥,另外一个就是私钥。任选一个用来加密另一个就可以用来解密。
    andyhuzhill
        23
    andyhuzhill  
       2019-03-09 23:32:28 +08:00
    @weyou #22 其实不是任选一个作公钥的 非对称加密还有一个特点就是 从私钥计算公钥很简单 从公钥计算私钥很困难 这也是保证公钥加密算法安全的一个因素
    bp0
        24
    bp0  
       2019-03-09 23:42:04 +08:00
    原理上没有问题。非对称密钥的本质就是用一个 key 加密,就能用另外一个 key 解密。

    不过一般都是,
    公钥加密,私钥签名。
    公钥加密,私钥签名。
    公钥加密,私钥签名。

    因为你公开了的就是公钥,没公开的就是私钥。


    @3dwelcome @weyou 签名是可以加上 padding 的,而且是有必要的。加了 padding 以后,保证每次生成的签名都不相同,但是都可以用同一个公钥进行验证。参考 PKCS#1 V2.2 RSASSA-PSS。

    @dryadent 私钥签名(加密)和公钥验证签名(解密)是数字签名的基础,必然是可以保证安全性的。如果真不能保证,那么我们现有的数字签名体系早就崩塌了。
    luckyuro
        25
    luckyuro  
       2019-03-10 00:05:03 +08:00 via iPhone
    @andyhuzhill 不是吧,一般来说 rsa 的公私钥,只有一个的话另一个是算不出来的吧
    andyhuzhill
        26
    andyhuzhill  
       2019-03-10 00:25:06 +08:00
    @luckyuro #25 由私钥是可以计算出公钥的,所以一般只需要好好保存私钥就可以了
    qwertyegg
        27
    qwertyegg  
       2019-03-10 05:10:53 +08:00
    这帖子一发出来就看到了,半天后回复除了 @sadan9 基本上都没抓住重点

    公钥加密系统两种用法

    op 提问的这个用法,叫数字签名,用私钥(加密)签名,公钥(解密)验证

    另外一个就是非对称加密,用公钥加密,用私钥解密
    ryd994
        28
    ryd994  
       2019-03-10 07:42:01 +08:00 via Android   ❤️ 2
    反过来这样加密就是签名算法的原理。但实际上不推荐用同一把。有可能存在如下攻击:通过观察签名数据的明文和密文之间的关系(公钥),即使不知道私钥,但也推测加密数据的明文和密文的关系(私钥),或者缩小可能的范围。目前没听说有可操作的攻击不代表以后没有。
    所以 gpg 就是建议加密、鉴权、签名三种密钥不同。

    @CEBBCAT 实现上是有不同的。n 和 d 组成私钥。n 和 e 组成公钥。e 可以随机选取,但一般都用 65537。也就是说,知道私钥就可以知道公钥。

    @luckyuro 实际上只要你用的是常见的软件生成,比如 OpenSSL,那就是默认 65537
    CEBBCAT
        29
    CEBBCAT  
       2019-03-10 08:22:57 +08:00 via Android
    @ryd994 太感谢了😊
    7DLNU56W
        30
    7DLNU56W  
       2019-03-10 09:27:24 +08:00
    其实我感觉私钥和公钥完全是可以互换的,生成一组之后,把哪个公开那个就是公钥,自己保留的那个就是私钥。
    私钥加密公钥解密通常都是签名的作用。通过公钥来验证一段内容是由私钥持有人发布的。不过现在通常签名都是用私钥加密哈希值而不是加密原文。但本质上你加密的是原文解密出来就是原文,加密的是哈希值,解密处理就是哈希值,解密结果与未加密的是一样的。
    aa6563679
        31
    aa6563679  
       2019-03-10 10:14:17 +08:00 via iPhone
    可以是可以,但公钥长度一般都不长,甚至本身是公开的。安全性不佳
    tangweihua163
        32
    tangweihua163  
       2019-03-10 12:30:46 +08:00   ❤️ 4
    楼上一堆瞎说的。。。。。。

    我在工作中经常使用这些东西,我来说说我的理解吧。

    # RSA 可以用于加解密,也可以用于消息签名。

    RSA 使用一对不同的密钥:公钥和私钥。公钥是公开的,你知道,别人也知道,别人也需要知道;私钥是只能持有者知道,不能泄露了,不然很麻烦。

    # 加解密

    A 和 B 通信,A 使用 B 的公钥和 RSA 加密算法对消息进行加密,得到密文,密文扔出去后,只有 B 使用自己的私钥才能解。
    B 回复 A,B 使用 A 的公钥和 RSA 加密算法对响应数据进行加密,加密后的密文只有 A 能够解。这就保证了,数据不会被第三方获取。

    当然这里面还有一些其他的问题,比如怎样获取对方的公钥,怎样确定获取到的公钥就是对方的公钥而不是中间人伪造的公钥。可以了解下 https 握手的过程,https 主要通过对称加密(比如 AES 等)方式通信,但是对称加密密钥是通过 RSA 加密传输的。

    # 签名验签

    RSA 可以用于消息签名,用于消息接收方确认消息发送方身份,防止伪造的消息。
    A 将原始数据使用 A 的私钥进行 RSA 签名得到 Sign,原始数据附带签名一起发送给消息接收方,消息接收方 B 使用 A 的公钥、原始数据、Sign 三个要素进行验签过程,也就是使用 A 的公钥和 RSA 算发对 Sign 进行处理,用处理的结果与原始数据进行对比,如果一致,说明是 A 发送的,而且只能是 A 发送的,除非 A 的私钥泄露了。

    由于 RSA 算法比较慢,而且原始数据的大小不确定,消息签名的计算和传输可能会造成很大的 cpu 和网络开销,消息签名一般是对原始数据的摘要进行签名,比如 MD5 消息摘要算法( MD5 长度固定,且不同消息 MD5 冲突的可能性很小),对应的,验签的时候对比的不不是原始数据,而是消息摘要。使用指定的消息摘要进行签名时,签名过程计算较快,而且签名结果长度也相对固定。



    总之,加解密和消息签名使用 RSA 时,目的不同,一个是为了防止明文消息被第三方获取(私密性),一个是为了方便消息接收方确认消息没有被篡改(完整性)。

    如有错误,烦请指出。
    tangweihua163
        33
    tangweihua163  
       2019-03-10 12:36:50 +08:00
    还有一点,消息签名可以防止抵赖,如果一段经过签名的消息使用 A 的公钥验签通过,那就可以确定是 A 发送的,A 不能抵赖(抗抵赖性)。
    tangweihua163
        34
    tangweihua163  
       2019-03-10 12:39:42 +08:00
    所以,加密是不用使用私钥的,公钥公开了,任何人只要获取到你的公钥就能解了。签名也不能使用公钥,没有人有办法验证,因为别人都不知道签名者的私钥。
    weyou
        35
    weyou  
       2019-03-10 14:27:29 +08:00 via Android
    @andyhuzhill 在数学意义上私钥( d,n )并不能很容易的计算出公钥( e,n ),或者说从私钥计算公钥和从公钥计算私钥的复杂度是完全一样的。之所以你实际操作中从私钥可以能计算出公钥是因为现有的 rsa 库(比如 openssl )都是选取 e 为 3 或者 65537 (为了效率考虑),私钥的 n 你知道了,e 只有两种可能,所以公钥自然就知道了。所以这不代表 rsa 算法中的公钥私钥不是对等的。

    打个比方,道路右行和左行其实没有区别,但是我国交通法规定必须右行,你在实际中硬要左行,那出事故的概率肯定要大大高于右行,但你得出个结论说因为左行事故发生率高所以我们必须右行,这就是本末倒置了。
    henglinli
        36
    henglinli  
       2019-03-10 14:42:14 +08:00 via iPhone
    非对称加密算法公私钥都可用来加解密。
    但是主流用法如 tls 是非对称算法签名,即私钥加密公钥解密,其对象是对称算法的密钥。
    然而高安全的应用会在 tls 链接之上再做一层认证和密钥交换,比如 tor 的 NTOR 握手。

    另外,rsa 是被怀疑有后门的——虽然没有人找出来,
    所以建议选择非对称算法时考虑下 curve25519,golang,erlang,openssl 等也都已支持。
    本人就毕设是做过 rsa,但是在看过 tor 的设计文档后感觉已经初入门道了,感兴趣的朋友强烈建议阅读参考。

    另外,公私钥是有区别的,私钥能轻易推导出公钥,但是公钥却几乎不可能“破解”出私钥,以至于某些实现的私钥数据结构中就包含公钥。
    msg7086
        37
    msg7086  
       2019-03-10 15:51:51 +08:00   ❤️ 3
    https://blog.x86.men/blog/rsa-faq

    专门写了一篇短文把知识点撸一下。

    这一楼里大家对名词的定义全是乱的,比如私钥和私钥文件不分清,导致各种上下矛盾但又都正确的帖子层出不穷。32 楼的 @tangweihua163 更是把私钥和事实私钥概念混在一起,写得完全正确,但是完全文不对题。
    tangweihua163
        38
    tangweihua163  
       2019-03-10 16:34:45 +08:00
    @msg7086 我只是指出楼主搞反了啊,加密不能用私钥,签名不能用公钥。另外,我说的公钥私钥是表层逻辑上的概念,并不包含底层算法原理和具体数据关系数据结构。我不知道到底是谁文不对题……我提到事实私钥这个概念了吗?😂
    msg7086
        39
    msg7086  
       2019-03-10 16:43:53 +08:00
    @tangweihua163 逻辑层上的私钥和公钥是事实私钥和事实公钥。
    底层算法原理中的公钥和私钥才是原始的公钥和私钥。

    算法原理中的公钥和私钥是对等的,而上层因为种种原因(例如实际代码实现,参数选择,存储方式等因素)才导致了你说的这些东西。这些不是“ RSA ”的限制,而是“某种 RSA 的实现”的限制。所以我才说,针对楼主说的“ RSA ”的疑问,你的回答,内容正确但是并不对题。你回答的并不是楼主问的。
    tangweihua163
        40
    tangweihua163  
       2019-03-10 17:03:45 +08:00
    @msg7086 你可能理解错了我的意思了,我已经说过了,签名是用私钥处理,公钥验证。公私钥在数学上对等的,只是个选择问题,但是,用私钥处理数据不能称为是加密,因为没有私密性,用公钥处理不能称为签名,可伪造。至于你说的什么事实私钥事实公钥,我觉得是多余的概念,一对密钥生成后,定下一个做公钥,一个做私钥,以后也不能改,那今后公就是公,私就是私,没有什么事实的说法,多余…
    pythonee
        41
    pythonee  
       2019-03-10 17:15:33 +08:00
    @tangweihua163 可以再谈谈公钥交换
    pythonee
        42
    pythonee  
       2019-03-10 17:16:28 +08:00
    @msg7086 感兴趣公钥交换
    msg7086
        43
    msg7086  
       2019-03-10 17:32:34 +08:00
    @pythonee 你说的是 Key Exchange 算法吗?
    pythonee
        44
    pythonee  
       2019-03-10 18:04:27 +08:00
    @msg7086 算法和交换过程
    crab
        45
    crab  
       2019-03-10 18:07:38 +08:00
    msg7086
        46
    msg7086  
       2019-03-10 18:13:09 +08:00
    @pythonee 维基百科上的 DHE 词条写得非常详细了,建议直接读那个。
    kangzai50136
        48
    kangzai50136  
       2019-03-11 01:19:25 +08:00 via Android
    小白弱弱地问下,如果公钥解不出私钥加密的数据,那服务器返回给客户端的数据要怎么得到……
    ryd994
        49
    ryd994  
       2019-03-11 08:52:07 +08:00 via Android
    @kangzai50136 RSA 不用与传输实际数据
    确认身份已经协商一个对称加密密钥,之后都是用对称
    原因是不对称加密太慢了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3167 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 13:46 · PVG 21:46 · LAX 05:46 · JFK 08:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.