公钥如何验证签名?

jca*_*782 141 pki digital-signature public-key-encryption public-key private-key

我正在努力更好地解决公钥/私钥的工作方式.我知道发件人可以使用他/她的私钥向文档添加数字签名,以基本上获取文档的哈希值,但我不明白的是如何使用公钥来验证签名.

我的理解是公钥加密,私钥解密......任何人都可以帮我理解吗?

Sha*_*man 178

您对"公钥加密,私钥解密"的理解是正确的......对于数据/消息ENCRYPTION.对于数字签名,情况恰恰相反.使用数字签名,您试图证明您签署的文档来自您.要做到这一点,你需要使用只有你拥有的东西:你的私钥.

最简单描述中的数字签名是数据(文件,消息等)的散列(SHA1,MD5等),随后用签名者的私钥加密.因为这只是签名者拥有(或应该拥有)信任来自的地方.每个人都有(或应该)访问签名者的公钥.

因此,要验证数字签名,收件人

  1. 计算相同数据的散列(文件,消息等),
  2. 使用发件人的PUBLIC密钥解密数字签名
  3. 比较2个哈希值.

如果匹配,则签名被认为是有效的.如果它们不匹配,则表示使用不同的密钥对其进行签名,或者数据已被更改(无论是有意还是无意).

希望有所帮助!

  • 这些键彼此相反.使用您的公钥加密某些内容?用你的私钥解密它.相反,如果您使用私钥加密某些内容,则需要向公众解密.这就是非对称密码术的本质. (51认同)
  • 对称只意味着使用相同的密钥来加密/解密.Assymetric意味着一个密钥加密和一个不同的密钥解密(反之亦然). (18认同)
  • 我的理解是密钥不是对称的......也就是说,用公钥加密的对象能够通过私钥解密,但是这种关系不能反向...更具体地说,我没有想到对象用私钥加密的密钥可以用公钥解密.如果确实如此,那肯定会回答我的问题. (10认同)
  • @Jodimoro,从技术上讲,如果用私钥加密,则消息不是"秘密".如果使用私钥加密,则任何具有公共可用"公共"密钥的人都可以解密该消息. (8认同)
  • @Jodimoro哈希用私钥加密到签名中的唯一原因是确保散列不被改变......不确保它是"秘密". (4认同)

Jaa*_*kko 58

正如atn的回答所指出的那样,这些关键是相反的.

公钥加密,私钥解密(加密):

openssl rsautl -encrypt -inkey public.pem -pubin -in message.txt -out message.ssl
openssl rsautl -decrypt -inkey private.pem       -in message.ssl -out message.txt
Run Code Online (Sandbox Code Playgroud)

私钥加密,公钥解密(签名):

openssl rsautl -sign -inkey private.pem       -in message.txt -out message.ssl
openssl rsautl       -inkey public.pem -pubin -in message.ssl -out message.txt
Run Code Online (Sandbox Code Playgroud)

下面是一个用于测试整个流程的示例脚本openssl.

#!/bin/sh
# Create message to be encrypted
echo "Creating message file"
echo "---------------------"
echo "My secret message" > message.txt
echo "done\n"

# Create asymmetric keypair
echo "Creating asymmetric key pair"
echo "----------------------------"
openssl genrsa -out private.pem 1024
openssl rsa -in private.pem -out public.pem -pubout
echo "done\n"

# Encrypt with public & decrypt with private
echo "Public key encrypts and private key decrypts"
echo "--------------------------------------------"
openssl rsautl -encrypt -inkey public.pem -pubin -in message.txt         -out message_enc_pub.ssl
openssl rsautl -decrypt -inkey private.pem       -in message_enc_pub.ssl -out message_pub.txt
xxd message_enc_pub.ssl # Print the binary contents of the encrypted message
cat message_pub.txt # Print the decrypted message
echo "done\n"

# Encrypt with private & decrypt with public
echo "Private key encrypts and public key decrypts"
echo "--------------------------------------------"
openssl rsautl -sign    -inkey private.pem -in message.txt          -out message_enc_priv.ssl
openssl rsautl -inkey public.pem -pubin    -in message_enc_priv.ssl -out message_priv.txt
xxd message_enc_priv.ssl
cat message_priv.txt
echo "done\n"
Run Code Online (Sandbox Code Playgroud)

此脚本输出以下内容:

Creating message file
---------------------
done

Creating asymmetric key pair
----------------------------
Generating RSA private key, 1024 bit long modulus
...........++++++
....++++++
e is 65537 (0x10001)
writing RSA key
done

Public key encrypts and private key decrypts
--------------------------------------------
00000000: 31c0 f70d 7ed2 088d 9675 801c fb9b 4f95  1...~....u....O.
00000010: c936 8cd0 0cc4 9159 33c4 9625 d752 5b77  .6.....Y3..%.R[w
00000020: 5bfc 988d 19fe d790 b633 191f 50cf 1bf7  [........3..P...
00000030: 34c0 7788 efa2 4967 848f 99e2 a442 91b9  4.w...Ig.....B..
00000040: 5fc7 6c79 40ea d0bc 6cd4 3c9a 488e 9913  _.ly@...l.<.H...
00000050: 387f f7d6 b8e6 5eba 0771 371c c4f0 8c7f  8.....^..q7.....
00000060: 8c87 39a9 0c4c 22ab 13ed c117 c718 92e6  ..9..L".........
00000070: 3d5b 8534 7187 cc2d 2f94 0743 1fcb d890  =[.4q..-/..C....
My secret message
done

Private key encrypts and public key decrypts
--------------------------------------------
00000000: 6955 cdd0 66e4 3696 76e1 a328 ac67 4ca3  iU..f.6.v..(.gL.
00000010: d6bb 5896 b6fe 68f1 55f1 437a 831c fee9  ..X...h.U.Cz....
00000020: 133a a7e9 005b 3fc5 88f7 5210 cdbb 2cba  .:...[?...R...,.
00000030: 29f1 d52d 3131 a88b 78e5 333e 90cf 3531  )..-11..x.3>..51
00000040: 08c3 3df8 b76e 41f2 a84a c7fb 0c5b c3b2  ..=..nA..J...[..
00000050: 9d3b ed4a b6ad 89bc 9ebc 9154 da48 6f2d  .;.J.......T.Ho-
00000060: 5d8e b686 635f b6a4 8774 a621 5558 7172  ]...c_...t.!UXqr
00000070: fbd3 0c35 df0f 6a16 aa84 f5da 5d5e 5336  ...5..j.....]^S6
My secret message
done
Run Code Online (Sandbox Code Playgroud)

  • 大!非常感谢!!!2天搜索这些简单的线条!感谢! (3认同)
  • 感谢您添加脚本-绝对有助于清除问题。 (2认同)

Zac*_*zer 27

如果我不得不根据我的理解重新表述你的问题,你会问以下问题:

如果公钥密码学确保可以从私钥导出公钥,但不能从公钥导出私钥,那么您可能想知道,公钥如何在没有发送方的情况下解密用私钥签名的消息将签名消息中的私钥暴露给收件人?(多读几遍,直到明白为止)

其他答案已经解释了非对称加密意味着你可以

  1. 用公钥加密,用匹配的私钥解密(下面是伪代码)
var msg = 'secret message';

var encryptedMessage = encrypt(pub_key, msg);

var decryptedMessage = decrypt(priv_key, encryptedMessage);

print(msg == decryptedMessage == 'secret message'); // True
Run Code Online (Sandbox Code Playgroud)
  1. 用私钥加密,用匹配的公钥解密(下面是伪代码)
var msg = 'secret message';

var encryptedMessage = encrypt(priv_key, msg);

var decryptedMessage = decrypt(pub_key, encryptedMessage); // HOW DOES THIS WORK???

print(msg == decryptedMessage == 'secret message'); // True
Run Code Online (Sandbox Code Playgroud)

我们知道示例 #1 和 #2 都有效。示例 #1 具有直观意义,而示例 #2 回避了原始问题

原来,椭圆曲线密码术(也称为“椭圆曲线乘法”)是原始问题的答案。椭圆曲线密码学是使以下条件成为可能的数学关系:

  1. 公钥可以从私钥生成数学
  2. 私钥不能用数学方法从公共密钥生成(即“陷门函数”)
  3. 私钥可以验证通过公钥

对大多数人来说,条件 #1 和 #2 是有意义的,但是 #3 呢?

您在这里有两个选择:

  1. 你可以钻进一个兔子洞,花几个小时来学习椭圆曲线密码学的工作原理(这是一个很好的起点)......或者......
  2. 您可以接受上述属性——就像您接受牛顿 3 运动定律而无需自己推导出它们一样。

总之,公钥/私钥对是使用椭圆曲线密码术创建的,它本质上创建了一个公钥和私钥,它们在两个方向上都在数学上相关联,但不是在两个方向上都从数学上推导出来的。这使您可以使用某人的公钥来验证他们是否签署了特定消息,而无需他们向您公开他们的私钥。

  • 这个答案就是我一直在寻找的。整个互联网上的其他任何地方实际上都没有对此进行解释。 (3认同)

wue*_*ueb 11

公钥加密,只有私钥可以解密,反之亦然。它们都加密为不同的哈希值,但是每个密钥都可以解密对方的加密。

有几种不同的方法可以验证消息是否来自某个预期的发件人。例如:

发件人发送:

  1. 讯息

  2. 使用其私钥加密的消息的哈希

收件人:

  1. 用公钥对签名(2)进行解密以获取一条消息,该消息应该与(1)相同,但我们尚不知道。现在,我们需要验证两条消息是否相同。因此,为此,我们将使用我们的公共密钥对它们进行加密,并比较两个哈希。所以我们会....
  2. 用公钥加密原始消息(1)以获取哈希
  3. 加密已解密的消息(3)以获取第二个哈希,然后与(4)比较以验证它们是否相同。

如果它们不相同,则意味着该消息已被篡改或已使用其他密钥签名,而不是我们认为的那个密钥...

另一个示例是发送方使用接收方可能也知道要使用的公用哈希。例如:

发件人发送:

  1. 一个消息
  2. 获取消息的已知哈希,然后使用私钥加密哈希

收件人:

  1. 解密(2)并获取哈希值
  2. 使用发件人使用的散列对消息(1)进行散列
  3. 比较两个散列以确保它们匹配

这再次确保了邮件没有被篡改,并且来自预期的发件人。


sho*_*hoe 8

以为我会为任何寻找更直观揭示的东西的人提供补充解释。

这种混淆的很大一部分来自于命名“公钥”和“私钥”,因为这些东西的实际工作方式与“密钥”的理解方式直接不一致。

以加密为例。它可以被认为是这样工作的:

  • 希望能够读取秘密消息的各方都隐藏了一个密钥(即私钥)
  • 希望能够发送秘密消息的各方都有能力获得解锁的锁定(即公共锁定)
  • 然后发送秘密消息就像用未锁定的锁锁定它一样简单,但之后解锁它只能使用其中一个隐藏的钥匙来完成。

这允许在各方之间发送秘密消息,但从这里的直观角度来看,“公共锁”是比“公共密钥”更合适的名称。

但是,对于发送数字签名,角色有些颠倒:

  • 想要签署消息的一方是唯一可以访问解锁的锁(即私人锁)的一方
  • 想要验证签名的各方都有获得密钥(即公钥)的能力
  • 然后签名者所做的是创建两个相同的消息:一个任何人都可以阅读,一个伴随它,但他们用他们的私人锁之一锁定。
  • 然后当接收者收到消息时,他们可以读取它,然后使用公钥解锁锁定的消息并比较两条消息。如果消息相同,则他们知道:

    1. 解锁的信息在旅行期间没有被篡改,并且,

    2. 该消息必须来自拥有与其公钥匹配的锁的人。

  • 最后,这个整个系统只有在任何想要验证签名者签名的人有一个权威的地方去获取签名者锁的匹配密钥时才能工作。否则,任何人都可以说“嘿,这是某某私人锁的钥匙”,向您发送假装是他们的消息但用他们的私人锁将其锁定,您执行上述所有步骤并相信该消息确实是来自你认为的那个人,但你被愚弄了,因为你被误导了公钥的真正所有者。

只要有一个值得信赖的来源来检索签名者的公钥,您就会知道谁是公钥的合法所有者,并且能够验证他们的签名。

  • 将“钥匙”更改为“解锁锁”只会增加混乱。 (5认同)