我正在努力更好地了解公钥/私钥是如何工作的。我知道发送方可以使用他/她的私钥向文档添加数字签名,从而实质上获得文档的哈希值,但我不理解的是如何使用公钥来验证该签名。

我的理解是公钥加密,私钥解密…有人能帮我理解一下吗?


当前回答

我认为误解中的最大问题是,当人们读到“不对称”这个词时,在他们的头脑中,他们认为“好吧,一个密钥加密,另一个密钥解密,因此它们是不对称的”。但如果你理解不对称实际上意味着“if密钥A加密了数据,那么它的“姐妹”密钥B可以解密数据。如果密钥B被用来加密数据,那么密钥A现在只能解密。”对称意味着用于加密数据的相同密钥可以用于解密数据。

其他回答

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

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

发件人发送:

的消息 用他们的私钥加密的消息的哈希值

接收方:

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

如果它们不相同,这意味着要么消息被篡改了,要么它是用其他密钥签名的,而不是我们认为的那个……

另一个例子是发送方使用接收方可能也知道使用的公共散列。例如:

发件人发送:

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

接收方:

解密(2)并获得一个哈希值 使用发送方使用的相同散列对消息(1)进行散列 比较两个散列以确保它们匹配

这再次确保消息没有被篡改,并且它来自预期的发送者。

我想为那些寻找更直观的东西的人提供一个补充解释。

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

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

希望能够阅读秘密消息的各方都拥有一把密钥 隐藏(即私钥) 希望能够发送秘密消息的各方都有能力获得一个未解锁的锁(即一个公共锁) 然后发送秘密信息就像用一把没有上锁的锁一样简单,但之后只能用其中一把隐藏的钥匙来解锁。

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

然而,对于发送数字签名,角色有点相反:

The party that wants to sign messages is the only one with access to the unlocked locks (i.e. a private lock) The parties that want to verify the signature all have the ability to obtain a key (i.e. a public key) Then what the signer does is create two identical messages: the one that anyone can read and one to accompany it, but which they lock with one of their private locks. Then when the receiver gets the message, they can read it, and then use the public key to unlock the locked message and compare the two messages. If the messages are the same, then they know that: The unlocked message wasn't tampered with during travel and, The message must have been from the person who has the matching lock to their public key. And finally, this entire system only works if anyone who wants to validate a signer's signature has an authoritative place to go to to get the matching key to the signer's locks. Otherwise, anyone can say "Hey, here's the key to so-and-so's private lock", send you a message pretending to be them but lock it with their private lock, you perform all the above steps and believe the message must actually be from the person you thought, but you're fooled because you were mislead as to the true owner of a public key.

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

键的作用是相反的:

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

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

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

openssl rsautl -sign -inkey private.pem       -in message.txt -out message.ssl
openssl rsautl       -inkey public.pem -pubin -in message.ssl -out message.txt

下面是一个使用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"

该脚本输出如下:

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

关于你的问题,我在看RSA的实现。并且更清楚地了解了使用公钥验证使用私钥的签名的方式。毫无疑问,私钥不会被暴露。以下是如何……

这里的技巧是将私钥隐藏在函数中。这里是(p-1)*(q-1)

假设p是私钥,e是公钥。P被封装在另一个函数中以使其隐藏。

E.g., `d = (p-1)(q-1); d * e = 1` (d is the inverse of e - public key)
Data sent = [encrypted(hash), message] = [m ^d, message];

留言在哪里 假设

'Data sent' = y

为了检验完整性,我们找到y^e得到m,因为m ^(d*e) = m ^1 = m。

希望这能有所帮助!:)

下面是一个使用Python验证公钥签名的示例

您需要安装pycryptodome。从这里开始

# pip install pycryptodome

from Crypto.PublicKey import RSA
from hashlib import sha512

# create RSA key-pair
keyPair = RSA.generate(bits=1024)
public_key = (keyPair.e, keyPair.n)
private_key = (keyPair.d, keyPair.n)

msg = b'A message for signing'
hash = int.from_bytes(sha512(msg).digest(), byteorder='big')

# RSA sign the message using private key
signature = pow(hash, private_key[0], private_key[1])

# RSA verify signature using public key
hashFromSignature = pow(signature, public_key[0], public_key[1])
print("Signature valid:", hash == hashFromSignature)