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

为什么都是私钥签名公钥验签,而不是直接私钥加密公钥解密?

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

    为什么都是私钥签名公钥验签,而不是直接私钥加密公钥解密?

    是处于什么考虑这么做?性能考虑吗?

    第 1 条附言  ·  122 天前
    补充下:我的前提是同样都是为了防止受到的数据不被篡改下,不在乎发送的数据会不会被别人截获
    48 回复  |  直到 2018-12-24 15:16:20 +08:00
        1
    tony1016   122 天前
    所谓公钥,就是你有我有,大家都有,那还加个啥密??
        2
    tony1016   122 天前
    当然,原理上不是不可了,还有一个很重要的原因是非对称加解密的效率很低
        3
    augcat   122 天前
    签名不就是为了证明是你本人写的消息吗
        4
    tinybaby365   122 天前   ♥ 1
    是可以。但一般不这么做,https 协议中,浏览器用证书的公钥加密保护一个对称加密算法的 key,给服务端解密,以后都是对称加密通讯。https 的证书中,也只是用公钥验证签名。所以不少加密库没有类似于 RSA public decrypt 的方法。因为现实中几乎遇不到这种场景。
        5
    AlphaTr   122 天前 via iPhone
    签名和加密的作用不一样的,签名并不是为了保密;而公钥加密由于性能的原因,一般都换用密钥交换算法+对称加密
        6
    zoudm   122 天前   ♥ 2
    我猜楼主的意思是,现在的做法:text + privkey(hash(text)),为什么不用:privkey(text) 来证明是自己写的。

    可能是因为,明文 text 更方便别人阅读(不需要解密的步骤),当有需要验证来源时,再做额外的验证工作。
        7
    feather12315   122 天前
    私钥可以推导出公钥,反向不成立。
        8
    zarte   122 天前   ♥ 2
    主要是效率问题。
        9
    Aixtuz   122 天前
    知道加密不知道签名,然后去搜了一下,大概明白了。
    - A 要给 B 发信息要用 B 的公钥加密,B 用自己的私钥解密。
    - A 发布了一篇文章,说这是我发的,我用自己的私钥签名了。由于之前 A 已经发布了他的公钥,所以其它人可以用这个公钥去验证。因为知道 A 私钥的只可能是 A 自己。

    这样的话:加密是保护数据,签名是核对身份,解决的是不同需求。
    那么我的理解:不应该是需要解决什么问题就用什么吗?
    不希望第三方收到内容就加密,不希望第三方冒充发布就签名,或者同时使用。

    比如:
    在论坛以 ID 隐匿真名,发个帖子抽奖,显然奖品由当前这个 ID 提供,“证明他是他”也没什么必要,我就选不签名;
    若是代表某人 A 发布抽奖,我想确认他是否是 A 指定的发布者,自然就选择用 A 提供的公钥去验证发布者身份;
    然后,如果论坛没有私信功能,需要发帖通知中奖者领取某个序列号,自然不能被其他人知道,所以就跟中奖者索要一下公钥来加密。


    以上就是我搜完以后的理解,如果有错的地方,欢迎纠正。
        10
    crab   122 天前
    直接加密得考虑内容长度,签名只要加密内容的 hash,验证身份即可。
        11
    Yanni0507   122 天前
    题主你说的,直接私钥加密,公钥解密。可是公钥是公开的,可以认为能够随意获得,那你这个加密还有什么意义呢?
        12
    momocraft   122 天前
    签名和加密是两个不同的需求,虽然都在“密码学”
        13
    likuku   122 天前 via iPhone
    你非要质疑如今那些久经理论和实践考验的几个著名实现用的路子( pgp/gnupg/https/ssh-keys ),那真没人拦得住。
        14
    weifengzi2009   122 天前
    公钥私钥有两个用处。。

    1. 用私钥“加密”的信息,可以用公钥来判断来源是否是私钥持有人,也就是检查信息来源
    2. 用公钥加密私钥解密才是真加密,因为只有私钥持有人能解密,也就是确保信息去向
        15
    luwies   122 天前
    私钥加密公钥解密 这种情况就是验证签名的时候用的吧
        16
    c4f36e5766583218   122 天前
    “你只要想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。” --- https://www.zhihu.com/question/25912483/answer/46649199
        17
    gamexg   122 天前
    安全方面不知道,但是应该和性能有关系。
    记得看过私钥加密速度慢。
        18
    wd   122 天前 via iPhone
    @zoudm #6 因为 text 可能很大
        19
    tusj   122 天前
    如果私钥加密,公钥解密
    那岂不是向全天下公开你的信息,还加个啥密?
        20
    leavic   122 天前   ♥ 1
    如果这是一个 10GB 的视频文件,你准备加密这个视频,还是加密这个视频的 hash 值?
        21
    ruimz   122 天前 via Android
    考虑到签名的本质就是私钥加密公钥解密,则按楼主所说,能被 A 公钥解密的信息一定是 A 私钥发出的。
    理论上没问题,就是效率非对称不高。就是效率问题

    不过楼上为什么那么多人怀疑私钥加密公钥解密的做法呢?能用公钥解开的就是好签名,解不开的就是假签名,没毛病啊
        22
    Justin13   122 天前 via Android
    签名和加密的区别了解下。
        23
    mcfog   122 天前
    私钥“加密”,公钥“解密”的过程一般就叫做“签名”,“验签”,目的是证明信息是我发的
    “加密”一般是指保护信息不让别人看,应该是公钥加密,私钥解密

    题目里的说法,前后两半部分是一回事,后半部分一般不那么说

    至于性能问题,对于签名的场景,一般是用信息摘要(也就是哈希)作为签名的信息,而对于加密的场景,一般是用不对称算法(也就是公钥私钥)来保护对称算法的协商过程(也就是双方协商用什么对称算法,并随机生成临时的密钥,并定时轮换等),用对称算法保护实际内容
        24
    shm7   122 天前 via iPhone
    对称密码体系你可以用来加密,也可以用来做数字签名,就是反过来用密钥对。
    git 中用的代码提交就是用的这种,ssh 也是。
        25
    geelaw   122 天前 via iPhone   ♥ 6
    因为楼主和楼上很多人没搞清楚公钥、私钥的意思。

    在一个非对称加密方案中,公钥是用于加密的密钥,私钥是用于解密的密钥。在一个数字签名方案中,公钥是用于验证的密钥,私钥是用于签名的密钥。

    如果加上一点“类型”的感觉,四个密钥之间没有“隐式转换”,不存在“用私钥加密、用公钥解密”这种东西,无论你说的私钥 /公钥是指加密方案还是签名方案的一部分。

    至于某些加密、签名方案巧合地让此私钥和彼私钥有内容上的相似之处,那属于 private class member。
        26
    Paryace   122 天前   ♥ 1
    理论上公钥和私钥是可以反过来用的,哪边"加密",哪边"解密"都不影响。

    问题就在现行的库和协议默认私钥里面保存了原始信息,理论上有里面的数据可以硬算出公钥,相当于人为强行区分私钥和公钥,所以规定了流程:公钥加密,私钥解密,私钥签名,公钥验证。
        27
    reself   122 天前 via Android   ♥ 2
    非对称算法很慢的,因此签名和加密都不是直接在原文上操作。一般来说要用到私钥、公钥,密钥,hash 钥。分别对应非对称加密,对称加密,散列算法。
    加密时用的性能好的对称加密算法,而不是非对称算法。发送端用公钥加密密钥和 hash 钥,传输完成后,接收端用私钥解密出密钥和 hash 钥,再拿密钥来解密出明文,再用 hash 钥校验完整性。
    签名也是这样的。用首先 hash 起到了保证完整性的作用,签名 hash 就间接签名了原文,就没必要消耗大量的算力来直接签名原文了。
        28
    alcarl   122 天前 via Android
    私钥加密公钥解密的主要应用领域就是签名,是一码事好吧。。。。。直接加密数据,如果量很大,rsa 算法很慢的超级慢
        29
    reself   122 天前 via Android
    签名和验签的方法有很多种。私钥加密公钥解密只是实现方法的一种。如果只有两个人通信,那么用对称加密也可以,因为默认只有你们俩知道密钥,知道密钥本身代表了对方的身份。但是三个人就不行了,你收到了一份声明是没法区分是谁发的,因为对面两个人都知道密钥,他们可以互相冒充。
    而用非对称的话就能保证唯一性,能用谁的公钥解就能说明是谁发的。除非他们两个人共享私钥(这代表他们两个人绝对信任彼此,一方无条件赞成另一方的决定),或者私钥泄露(这属于私钥的管理问题了,很严重)。
        30
    zsj950618   122 天前 via Android
    那 rsa 来说,大质数运算太太太慢了。所以 rsa 直接加密的内容越少越好
        31
    yucao   122 天前
    主要还是你要的目标是什么?
    是验证数据是没有被修改的数字水印?
    还是给数据进行加密?
    后者就是你所说的情况啊
    确定自己的需求是第一要义啊...
        32
    timeg0   122 天前
    验签和加密解密是两种信息安全模型,验签了为解决不可否认问题,加解密是了解决保密性问题。一般验签用的是非对称算法,如 RSA,RSA 是基于大素数分解这个数学难题来开发的,效率一般比较低下。加解密一般是对称加密算法,如 DES,3DES 等,效率比较高。很多地方是对称算法和非对称算法结合起来使用。
        33
    Leigg   122 天前 via iPhone
    20 楼一针见血
        34
    CRVV   122 天前 via Android
    @geelaw
    你有没有意识到自己回复的内容是正确的废话?
    楼主问不混用的原因,你回答说这东西就这么规定的

    在 RSA 里面,公钥和私钥没有本质的区别,公开的那个叫公钥,不公开的叫私钥。用公钥做加密是加密,用私钥做加密是签名。
    至于怎么规定的,那是另外一件事。规定的那个方法当然是正确的方法,但楼主问的是为什么另一种不正确。

    楼主问的问题其实很简单
    如果用私钥加密得到密文,然后把密文改掉,再用公钥解密。这样也可以解出来一个结果,但是这个结果和原来不一样。签名的目的是确保收到的消息正确,所以这样做不可行

    这事和性能毫无关系。
    类似的情况在对称加密里也有,confidentiality 和 integrity 是两件事,要用完全不同的方法来做,看看 AEAD 的实现就懂了。
        35
    maomo   121 天前
    泻药

    题主的问题应该修正为:为什么消息签名用 E(Hash(m))而不直接用 E(m)?

    答案:后者不能满足签名的安全性要求。并不是因为性能或者其他原因。

    首先要明白为什么要签名?签名是主要为了提供消息的“完整性”和“认证性”,保证消息不被篡改和伪造。

    那么为什么不直接用 E(m)?答案是因为如果采用这种方案,攻击者可以利用选择密文攻击( CCA )伪造任意消息的签名,破坏了完整性和认证性。用 E(Hash(m))的原因是 Hash 函数提供了抵抗 CCA 的能力,因此可以保证完整性和认证性。

    以上
        36
    hoiyd   121 天前
    理论上没问题,实际是性能的问题。大段的文字,用非对称加解密比较慢。
    所以一般是用 对称加密算法 加解密大段文字,非对称加解密算法来加解密 对称加密算法的秘钥 和 签名。
        37
    williamx   121 天前
    楼主问了一个非常好的问题!
        38
    faemon   121 天前 via iPhone
    其实在实际使用过程中,对数据加密是使用对称加密的,然后用公钥加密对称加密的密钥,然后接收者用私钥解密得出密钥,再用密钥解密出数据,所以并不是直接使用公钥加密数据。

    公钥和私钥是一对的,其实签名也可以理解为一种加密,所以能理解为公钥加密只能私钥解密,私钥加密只能公钥解密,两者作用一样。所以区分两者就为了破解的难度问题(知道公钥算出私钥,知道私钥算出公钥,其实都是依赖那个大质数来算出对方),如果在不知道那个大质数,而在拥有破解能力(计算机运算能力)非常大的情况下,保证知道公钥情况下破解获得私钥的难度大于知道私钥破解公钥的难度,所以区分出公私钥,派发公钥出去,自己保留私钥。数学家应该知道两者破解的难度差异有多大吧
        39
    maristie   121 天前
    贴一段 wikipedia

    Used directly, this type of signature scheme is vulnerable to key-only existential forgery attack. To create a forgery, the attacker picks a random signature σ and uses the verification procedure to determine the message, m, corresponding to that signature.[25] In practice, however, this type of signature is not used directly, but rather, the message to be signed is first hashed to produce a short digest, that is then padded to larger width comparable to N, then signed with the reverse trapdoor function[26]. This forgery attack, then, only produces the padded hash function output that corresponds to σ, but not a message that leads to that value, which does not lead to an attack. In the random oracle model, hash-then-sign (an idealized version of that practice where hash and padding combined have close to N possible outputs), this form of signature is existentially unforgeable, even against a chosen-plaintext attack.[16][clarification needed]

    There are several reasons to sign such a hash (or message digest) instead of the whole document.

    For efficiency
    The signature will be much shorter and thus save time since hashing is generally much faster than signing in practice.
    For compatibility
    Messages are typically bit strings, but some signature schemes operate on other domains (such as, in the case of RSA, numbers modulo a composite number N). A hash function can be used to convert an arbitrary input into the proper format.
    For integrity
    Without the hash function, the text "to be signed" may have to be split (separated) in blocks small enough for the signature scheme to act on them directly. However, the receiver of the signed blocks is not able to recognize if all the blocks are present and in the appropriate order.
        40
    geelaw   121 天前
    @CRVV #34 你说的是一些错误的话,你需要阅读密码学的教材来明白词的含义,而不是依靠直觉理解。

    > 在 RSA 里面,公钥和私钥没有本质的区别,公开的那个叫公钥,不公开的叫私钥。用公钥做加密是加密,用私钥做加密是签名。

    首先你需要定义“本质”。RSA 这个名字既可以指代使用 RSA trapdoor 的加密方案,也可以指代使用 RSA trapdoor 的签名方案。混淆的根源是没有说明白到底是什么密码学方案。而目前流行的使用 RSA trapdoor 的加密、签名方案刚好都用到了 RSA trapdoor 的 inversion 的过程。在 RSA trapdoor 中,正 /反运算需要的额外输入(代码和陷门代码)可以具有类似的格式,也可以没有。

    > 至于怎么规定的,那是另外一件事。规定的那个方法当然是正确的方法,但楼主问的是为什么另一种不正确。

    这是错误的想法,名词的含义是根据其定义而来。如果使用某个东西签名,那么那个东西就是私钥。正确的问法是:“为什么不能把 RSA 加密的公钥、加密算法当作 RSA 签名私钥、签名算法,把 RSA 解密的私钥、解密算法当作 RSA 签名公钥、验证算法?”

    > 楼主问的问题其实很简单
    > 如果用私钥加密得到密文,然后把密文改掉,再用公钥解密。这样也可以解出来一个结果,但是这个结果和原来不一样。签名的目的是确保收到的消息正确,所以这样做不可行

    你想象中的攻击并不一定能够成功。
        41
    CRVV   121 天前   ♥ 1
    @geelaw
    > RSA 这个名字既可以指代使用 RSA trapdoor 的加密方案,也可以指代使用 RSA trapdoor 的签名方案。

    RSA 这个名字还可以指代 RSA 算法本身。或者说,这里列出来的几个基本操作 https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Operation

    > 首先你需要定义“本质”。

    我原本的意思是,可以任选一个密钥来加密,用另一个密钥来解密,在加解密的过程中不需要区分哪个密钥是哪个密钥。

    > 为什么不能把 RSA 加密的公钥、加密算法当作 RSA 签名私钥、签名算法,把 RSA 解密的私钥、解密算法当作 RSA 签名公钥、验证算法?

    这是四个问题,其中一个是,为什么不能把 RSA 加密的加密算法当作 RSA 签名算法。
    这就是楼主问的问题
    对于任何一个教科书上有答案的问题,你都可以回答说“教材上是这么写的”。所以我说你的回答是正确的废话。

    > 你想象中的攻击并不一定能够成功。

    你好像完成不懂密码学上的攻击是什么。一个攻击成功的概率高于暴力破解的概率,就算作一个攻击了。
    你可以自己写代码去试试这个方法的成功概率有多少,当然不写代码也应该知道这个方法成功的概率大约是什么水平。
    如果你认为这个方式能起到签名的作用,那你真的“需要阅读密码学的教材”了

    某个东西是 “ private class member ” 就不继续往下深究了,我不认可这样的学习方式。
        42
    geelaw   120 天前
    @CRVV #41

    > RSA 这个名字还可以指代 RSA 算法本身。

    我没有说 RSA 不能指代 RSA trapdoor function。

    > 我原本的意思是,可以任选一个密钥来加密,用另一个密钥来解密,在加解密的过程中不需要区分哪个密钥是哪个密钥。

    这仍然是定义的问题,用来加密和解密的那个输入叫做公钥、私钥,它们的名字是根据用法决定的,而不是这些字符串先有名字,后把它们安插到对应的参数位置。

    > 你对“为什么不能……?”的回复

    我在展示一个正确的提问方法。你不需要回答这个问题(当然,你的回答可能有助于楼主)。

    > 你好像完成不懂密码学上的攻击是什么……那你真的“需要阅读密码学的教材”了

    你在臆想我是否懂,我说的“成功”的意思是指该方法有 non-negligible advantage。首先你的“暴力破解”的说法很含糊,你是指目前人类知道的最好方法的成功概率呢,还是指字面上的枚举法的概率呢?如果是后者,一些密码学方案是缩减安全程度的,然而只要保障 adversary 的成功概率仍然是 negligible 就可以。

    至于为什么“你的攻击方法不一定能成功”,是因为这里很含糊,完全没有说具体的方案设计是怎么样,如果该方案其他地方有额外的验证机制,你的方法的成功概率不一定是 non-negligible。

    > 某个东西是 “ private class member ” 就不继续往下深究了,我不认可这样的学习方式。

    我并没有说不应该深入学习 private class member。我那句话意在表明先明白接口( public members ),明白术语的意思,然后正确地提出问题,才能获得正确的答案。
        43
    reself   120 天前 via Android
    @maomo THX,学习了!
    查找了一下资料,感觉选择密文攻击和完整性没关系,完整性本身仍然是保证了的(私钥确实签署了这份数据),选择密文攻击的风险应该是泄露明文:
    解密和签名、加密和验签的算子都是相同的,导致对已用公钥加密的密文再用私钥签名蕴含了解密,所以攻击者可以截获用公钥加密的密文,然后通过某种运算将密文隐藏,设法使私钥对这份隐藏有密文的数据直接签名,再对签名后得到的"准明文"进行逆运算就可以解出明文,最开始用公钥加密发送出去的明文就泄露了。
    hash 一下破坏了这条计算链,所以 hash 又有了抗选择密文攻击的作用。
        44
    geelaw   120 天前 via iPhone
    @reself #43 先无论前面的分析对错。最后的部分:是否抗那个攻击取决于 hash 函数的安全性质。
        45
    reself   120 天前 via Android
    @geelaw 就选择密文攻击的场合而言应该问题不大,因为是对公钥加密后的密文进行 hash,攻击无法达到解出明文的目的,构造 hash 碰撞来篡改倒是有可能,但貌似不属于选择密文攻击了。
    如果 hash 安全性也影响抗选择密文攻击的话,能否描述一下攻击的场景呢?网上搜了一下,大多是描述选择明文攻击的,讲选择密文攻击的太少了。
        46
    wolfie   119 天前
    加密的意义是什么?
    就是验证一个文件没有被篡改?
        47
    firefox12   119 天前
    这个问题 我还专门尝试过 对于 RSA 但是好像不可以



    Here is an example of RSA encryption and decryption. The parameters used here are artificially small, but one can also use OpenSSL to generate and examine a real keypair.

    Choose two distinct prime numbers, such as
    {\displaystyle p=61} p=61 and {\displaystyle q=53} q=53
    Compute n = pq giving
    {\displaystyle n=61\times 53=3233} n=61\times 53=3233
    Compute the Carmichael's totient function of the product as λ(n) = lcm(p − 1, q − 1) giving
    {\displaystyle \lambda (3233)=\operatorname {lcm} (60,52)=780} {\displaystyle \lambda (3233)=\operatorname {lcm} (60,52)=780}
    Choose any number 1 < e < 780 that is coprime to 780. Choosing a prime number for e leaves us only to check that e is not a divisor of 780.
    Let {\displaystyle e=17} e=17
    Compute d, the modular multiplicative inverse of e (mod λ(n)) yielding,
    {\displaystyle d=413} {\displaystyle d=413}
    Worked example for the modular multiplicative inverse:
    {\displaystyle d\times e{\bmod {\lambda }}(n)=1} {\displaystyle d\times e{\bmod {\lambda }}(n)=1}
    {\displaystyle 413\times 17{\bmod {7}}80=1} {\displaystyle 413\times 17{\bmod {7}}80=1}
    The public key is (n = 3233, e = 17). For a padded plaintext message m, the encryption function is

    {\displaystyle c(m)=m^{17}{\bmod {3}}233} {\displaystyle c(m)=m^{17}{\bmod {3}}233}
    The private key is (n = 3233, d = 413). For an encrypted ciphertext c, the decryption function is



    public 是 n 和 e
    private 是 n 和 d

    e 一般都是 65535, 而 n 是双方都知道的, 所以 priavte 加密 public key 基本就是公开的。当然 如果 n 不公开,还是可以认为有一点安全的。 如果只有双方知道 n 这个加密还是安全的。

    只是安照算法 直接把 e 替换成 d 然后加密,好像是不行的。
        48
    Evilk   118 天前
    这其实是,在两种不同的场景跟需求下的不同的叫法而已
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3859 人在线   最高记录 4385   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 21ms · UTC 06:00 · PVG 14:00 · LAX 23:00 · JFK 02:00
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1