安全与密码学
去年的这节课我们从计算机用户的角度探讨了增强隐私保护和安全的方法。 今年我们将关注比如散列函数、密钥生成函数、对称/非对称密码体系这些安全和密码学的概念是如何应用于前几节课所学到的工具(Git和SSH)中的。
本课程不能作为计算机系统安全 (6.858) 或者 密码学 (6.857以及6.875)的替代。 如果你不是密码学的专家,请不要试图创造或者修改加密算法。从事和计算机系统安全相关的工作同理。
这节课将对一些基本的概念进行简单(但实用)的说明。 虽然这些说明不足以让你学会如何设计安全系统或者加密协议,但我们希望你可以对现在使用的程序和协议有一个大概了解。
熵
熵(Entropy) 度量了不确定性并可以用来决定密码的强度。
正如上面的 XKCD 漫画 所描述的, “correcthorsebatterystaple” 这个密码比 “Tr0ub4dor&3” 更安全——可是熵是如何量化安全性的呢?
熵的单位是比特。对于一个均匀分布的随机离散变量,熵等于log_2(所有可能的个数,即n)
。 扔一次硬币的熵是1比特。掷一次(六面)骰子的熵大约为2.58比特。
一般我们认为攻击者了解密码的模型(最小长度,最大长度,可能包含的字符种类等),但是不了解某个密码是如何随机选择的—— 比如掷骰子。
使用多少比特的熵取决于应用的威胁模型。 上面的XKCD漫画告诉我们,大约40比特的熵足以对抗在线穷举攻击(受限于网络速度和应用认证机制)。 而对于离线穷举攻击(主要受限于计算速度), 一般需要更强的密码 (比如80比特或更多)。
散列函数
密码散列函数 (Cryptographic hash function) 可以将任意大小的数据映射为一个固定大小的输出。除此之外,还有一些其他特性。 一个散列函数的大概规范如下:
hash(value: array<byte>) -> vector<byte, N> (N对于该函数固定)
SHA-1是Git中使用的一种散列函数, 它可以将任意大小的输入映射为一个160比特(可被40位十六进制数表示)的输出。 下面我们用sha1sum
命令来测试SHA1对几个字符串的输出:
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'Hello' | sha1sum
f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0
抽象地讲,散列函数可以被认为是一个不可逆,且看上去随机(但具确定性)的函数 (这就是散列函数的理想模型)。 一个散列函数拥有以下特性:
- 确定性:对于不变的输入永远有相同的输出。
- 不可逆性:对于
hash(m) = h
,难以通过已知的输出h
来计算出原始输入m
。 - 目标碰撞抵抗性/弱无碰撞:对于一个给定输入
m_1
,难以找到m_2 != m_1
且hash(m_1) = hash(m_2)
。 - 碰撞抵抗性/强无碰撞:难以找到一组满足
hash(m_1) = hash(m_2)
的输入m_1, m_2
(该性质严格强于目标碰撞抵抗性)。
注:虽然SHA-1还可以用于特定用途,但它已经不再被认为是一个强密码散列函数。 你可参照密码散列函数的生命周期这个表格了解一些散列函数是何时被发现弱点及破解的。 请注意,针对应用推荐特定的散列函数超出了本课程内容的范畴。 如果选择散列函数对于你的工作非常重要,请先系统学习信息安全及密码学。
密码散列函数的应用
- Git中的内容寻址存储(Content-addressed storage):散列函数是一个宽泛的概念(存在非密码学的散列函数),那么Git为什么要特意使用密码散列函数?
- 文件的信息摘要(Message digest):像Linux ISO这样的软件可以从非官方的(有时不太可信的)镜像站下载,所以需要设法确认下载的软件和官方一致。 官方网站一般会在(指向镜像站的)下载链接旁边备注安装文件的哈希值。 用户从镜像站下载安装文件后可以对照公布的哈希值来确定安装文件没有被篡改。
- 承诺机制(Commitment scheme): 假设我希望承诺一个值,但之后再透露它—— 比如在没有一个可信的、双方可见的硬币的情况下在我的脑海中公平的“扔一次硬币”。 我可以选择一个值
r = random()
,并和你分享它的哈希值h = sha256(r)
。 这时你可以开始猜硬币的正反:我们一致同意偶数r
代表正面,奇数r
代表反面。 你猜完了以后,我告诉你值r
的内容,得出胜负。同时你可以使用sha256(r)
来检查我分享的哈希值h
以确认我没有作弊。
密钥生成函数
密钥生成函数 (Key Derivation Functions) 作为密码散列函数的相关概念,被应用于包括生成固定长度,可以使用在其他密码算法中的密钥等方面。 为了对抗穷举法攻击,密钥生成函数通常较慢。
密钥生成函数的应用
- 从密码生成可以在其他加密算法中使用的密钥,比如对称加密算法(见下)。
- 存储登录凭证时不可直接存储明文密码。
正确的方法是针对每个用户随机生成一个盐salt = random()
, 并存储盐,以及密钥生成函数对连接了盐的明文密码生成的哈希值KDF(password + salt)
。
在验证登录请求时,使用输入的密码连接存储的盐重新计算哈希值KDF(input + salt)
,并与存储的哈希值对比。
对称加密
说到加密,可能你会首先想到隐藏明文信息。对称加密使用以下几个方法来实现这个功能:
keygen() -> key (这是一个随机方法)
encrypt(plaintext: array<byte>, key) -> array<byte> (输出密文)
decrypt(ciphertext: array<byte>, key) -> array<byte> (输出明文)
加密方法encrypt()
输出的密文ciphertext
很难在不知道key
的情况下得出明文plaintext
。
解密方法decrypt()
有明显的正确性。因为功能要求给定密文及其密钥,解密方法必须输出明文:decrypt(encrypt(m, k), k) = m
。
AES 是现在常用的一种对称加密系统。
对称加密的应用
- 加密不信任的云服务上存储的文件。对称加密和密钥生成函数配合起来,就可以使用密码加密文件: 将密码输入密钥生成函数生成密钥
key = KDF(passphrase)
,然后存储encrypt(file, key)
。
openssl aes-256-cbc -salt -in test.txt -out text.enc.txt
enter AES-256-CBC encryption password:
Verifying - enter AES-256-CBC encryption password:
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
输出结果如下:
cat text.enc.txt
Salted__ Z ]PjKB1^5P'w~HX.<!ھ'e2ق3
非对称加密
非对称加密的“非对称”代表在其环境中,使用两个具有不同功能的密钥: 一个是私钥(private key),不向外公布;另一个是公钥(public key),公布公钥不像公布对称加密的共享密钥那样可能影响加密体系的安全性。
非对称加密使用以下几个方法来实现加密/解密(encrypt/decrypt),以及签名/验证(sign/verify):
keygen() -> (public key, private key) (这是一个随机方法)
encrypt(plaintext: array<byte>, public key) -> array<byte> (输出密文)
decrypt(ciphertext: array<byte>, private key) -> array<byte> (输出明文)
sign(message: array<byte>, private key) -> array<byte> (生成签名)
verify(message: array<byte>, signature: array<byte>, public key) -> bool (验证签名是否是由和这个公钥相关的私钥生成的)
非对称的加密/解密方法和对称的加密/解密方法有类似的特征。
信息在非对称加密中使用公钥加密, 且输出的密文很难在不知道私钥的情况下得出明文。
解密方法decrypt()
有明显的正确性。 给定密文及私钥,解密方法一定会输出明文: decrypt(encrypt(m, public key), private key) = m
。
对称加密和非对称加密可以类比为机械锁。 对称加密就好比一个防盗门:只要是有钥匙的人都可以开门或者锁门。 非对称加密好比一个可以拿下来的挂锁。你可以把打开状态的挂锁(公钥)给任何一个人并保留唯一的钥匙(私钥)。这样他们将给你的信息装进盒子里并用这个挂锁锁上以后,只有你可以用保留的钥匙开锁。
签名/验证方法具有和书面签名类似的特征。
在不知道私钥的情况下,不管需要签名的信息为何,很难计算出一个可以使 verify(message, signature, public key)
返回为真的签名。
对于使用私钥签名的信息,验证方法验证和私钥相对应的公钥时一定返回为真: verify(message, sign(message, private key), public key) = true
。
非对称加密的应用
- PGP电子邮件加密:用户可以将所使用的公钥在线发布,比如:PGP密钥服务器或 Keybase。任何人都可以向他们发送加密的电子邮件。
- 聊天加密:像 Signal 和 Keybase 使用非对称密钥来建立私密聊天。
- 软件签名:Git 支持用户对提交(commit)和标签(tag)进行GPG签名。任何人都可以使用软件开发者公布的签名公钥验证下载的已签名软件。
密钥分发
非对称加密面对的主要挑战是,如何分发公钥并对应现实世界中存在的人或组织。
Signal的信任模型是,信任用户第一次使用时给出的身份(trust on first use),同时支持用户线下(out-of-band)、面对面交换公钥(Signal里的safety number)。
PGP使用的是信任网络。简单来说,如果我想加入一个信任网络,则必须让已经在信任网络中的成员对我进行线下验证,比如对比证件。验证无误后,信任网络的成员使用私钥对我的公钥进行签名。这样我就成为了信任网络的一部分。只要我使用签名过的公钥所对应的私钥就可以证明“我是我”。
Keybase主要使用社交网络证明 (social proof),和一些别的精巧设计。
每个信任模型有它们各自的优点:我们(讲师)更倾向于 Keybase 使用的模型。
混合加密
比如用RSA来加密传输AES的秘钥,用AES来加密数据。
案例分析
密码管理器
每个人都应该尝试使用密码管理器,比如KeePassXC、pass 和 1Password)。
密码管理器会帮助你对每个网站生成随机且复杂(表现为高熵)的密码,并使用你指定的主密码配合密钥生成函数来对称加密它们。
你只需要记住一个复杂的主密码,密码管理器就可以生成很多复杂度高且不会重复使用的密码。密码管理器通过这种方式降低密码被猜出的可能,并减少网站信息泄露后对其他网站密码的威胁。
两步验证(双因子验证)
两步验证(2FA)要求用户同时使用密码(“你知道的信息”)和一个身份验证器(“你拥有的物品”,比如YubiKey)来消除密码泄露或者钓鱼攻击的威胁。
全盘加密
对笔记本电脑的硬盘进行全盘加密是防止因设备丢失而信息泄露的简单且有效方法。 Linux的cryptsetup + LUKS, Windows的BitLocker,或者macOS的FileVault都使用一个由密码保护的对称密钥来加密盘上的所有信息。
聊天加密
Signal和Keybase使用非对称加密对用户提供端到端(End-to-end)安全性。
获取联系人的公钥非常关键。为了保证安全性,应使用线下方式验证Signal或者Keybase的用户公钥,或者信任Keybase用户提供的社交网络证明。
SSH
我们在之前的一堂课讨论了SSH和SSH密钥的使用。那么我们今天从密码学的角度来分析一下它们。
当你运行ssh-keygen
命令,它会生成一个非对称密钥对:公钥和私钥(public_key, private_key)
。 生成过程中使用的随机数由系统提供的熵决定。这些熵可以来源于硬件事件(hardware events)等。 公钥最终会被分发,它可以直接明文存储。 但是为了防止泄露,私钥必须加密存储。ssh-keygen
命令会提示用户输入一个密码,并将它输入密钥生成函数 产生一个密钥。最终,ssh-keygen
使用对称加密算法和这个密钥加密私钥。
在实际运用中,当服务器已知用户的公钥(存储在.ssh/authorized_keys
文件中,一般在用户HOME目录下),尝试连接的客户端可以使用非对称签名来证明用户的身份——这便是挑战应答方式。 简单来说,服务器选择一个随机数字发送给客户端。客户端使用用户私钥对这个数字信息签名后返回服务器。 服务器随后使用.ssh/authorized_keys
文件中存储的用户公钥来验证返回的信息是否由所对应的私钥所签名。这种验证方式可以有效证明试图登录的用户持有所需的私钥。
资源
- 去年的讲稿: 更注重于计算机用户可以如何增强隐私保护和安全
- Cryptographic Right Answers: 解答了在一些应用环境下“应该使用什么加密?”的问题
课后练习
- 熵
- 假设一个密码是由四个小写的单词拼接组成,每个单词都是从一个含有10万单词的字典中随机选择,且每个单词选中的概率相同。 一个符合这样构造的例子是
correcthorsebatterystaple
。这个密码有多少比特的熵? - 假设另一个密码是用八个随机的大小写字母或数字组成。一个符合这样构造的例子是
rg8Ql34g
。这个密码又有多少比特的熵? - 哪一个密码更强?
- 假设一个攻击者每秒可以尝试1万个密码,这个攻击者需要多久可以分别破解上述两个密码?
- 假设一个密码是由四个小写的单词拼接组成,每个单词都是从一个含有10万单词的字典中随机选择,且每个单词选中的概率相同。 一个符合这样构造的例子是
- 密码散列函数 从Debian镜像站下载一个光盘映像(比如这个来自阿根廷镜像站的映像)。使用
sha256sum
命令对比下载映像的哈希值和官方Debian站公布的哈希值。如果你下载了上面的映像,官方公布的哈希值可以参考这个文件。 - 对称加密 使用 OpenSSL的AES模式加密一个文件:
openssl aes-256-cbc -salt -in {源文件名} -out {加密文件名}
。 使用cat
或者hexdump
对比源文件和加密的文件,再用openssl aes-256-cbc -d -in {加密文件名} -out {解密文件名}
命令解密刚刚加密的文件。最后使用cmp
命令确认源文件和解密后的文件内容相同。 - 非对称加密
Security and Privacy
The world is a scary place, and everyone’s out to get you.
Okay, maybe not, but that doesn’t mean you want to flaunt all your secrets. Security (and privacy) is generally all about raising the bar for attackers. Find out what your threat model is, and then design your security mechanisms around that! If the threat model is the NSA or Mossad, you’re probably going to have a bad time.
There are many ways to make your techn ical persona more secure. We’ll touch on a lot of high-level things here, but this is a process, and educating yourself is one of the best things you can do. So:
Follow the Right People
One of the best ways to improve your security know-how is to follow other people who are vocal about security. Some suggestions:
See also this list for more suggestions.
General Security Advice
Tech Solidarity has a pretty great list of do’s and don’ts for journalists that has a lot of sane advice, and is decently up-to-date. @thegrugq also has a good blog post on travel security advice that’s worth reading. We’ll repeat much of the advice from those sources here, plus some more. Also, get a USB data blocker, because USB is scary.
Authentication
The very first thing you should do, if you haven’t already, is download a password manager. Some good ones are:
If you’re particularly paranoid, use one that encrypts the passwords locally on your computer, as opposed to storing them in plain-text at the server. Use it to generate passwords for all the web sites you care about right now. Then, switch on two-factor authentication, ideally with a FIDO/U2F dongle (a YubiKey for example, which has 20% off for students). TOTP (like Google Authenticator or Duo) will also work in a pinch, but doesn’t protect against phishing. SMS is pretty much useless unless your threat model only includes random strangers picking up your password in transit.
Also, a note about paper keys. Often, services will give you a “backup key” that you can use as a second factor if you lose your real second factor (btw, always keep a backup dongle somewhere safe!). While you can stick those in your password managers, that means that should someone get access to your password manager, you’re totally hosed (but maybe you’re okay with that thread model). If you are truly paranoid, print out these paper keys, never store them digitally, and place them in a safe in the real world.
Private Communication
Use Signal (setup instructions. Wire is fine too; WhatsApp is okay; don’t use Telegram). Desktop messengers are pretty broken (partially due to usually relying on Electron, which is a huge trust stack).
E-mail is particularly problematic, even if PGP signed. It’s not generally forward-secure, and the key-distribution problem is pretty severe. keybase.io helps, and is useful for a number of other reasons. Also, PGP keys are generally handled on desktop computers, which is one of the least secure computing environments. Relatedly, consider getting a Chromebook, or just work on a tablet with a keyboard.
File Security
File security is hard, and operates on many level. What is it you’re trying to secure against?
- Offline attacks (someone steals your laptop while it’s off): turn on full disk encryption. (cryptsetup + LUKS on Linux, BitLocker on Windows, FileVault on macOS. Note that this won’t help if the attacker also has you and really wants your secrets.
- Online attacks (someone has your laptop and it’s on): use file encryption. There are two primary mechanisms for doing so
- Encrypted filesystems: stacked filesystem encryption software encrypts files individually rather than having encrypted block devices. You can “mount” these filesystems by providing the decryption key, and then browse the files inside it freely. When you unmount it, those files are all unavailable. Modern solutions include gocryptfs and eCryptFS. More detailed comparisons can be found here and here
- Encrypted files: encrypt individual files with symmetric encryption (see
gpg -c
) and a secret key. Or, likepass
, also encrypt the key with your public key so only you can read it back later with your private key. Exact encryption settings matter a lot!
- Plausible deniability (what seems to be the problem officer?): usually lower performance, and easier to lose data. Hard to actually prove that it provides deniable encryption! See the discussion here, and then consider whether you may want to try VeraCrypt (the maintained fork of good ol’ TrueCrypt).
- Encrypted backups: use Tarsnap or Borgbase
- Think about whether an attacker can delete your backups if they get a hold of your laptop!
Internet Security & Privacy
The internet is a very scary place. Open WiFi networks are scary. Make sure you delete them afterwards, otherwise your phone will happily announce and re-connect to something with the same name later!
If you’re ever on a network you don’t trust, a VPN may be worthwhile, but keep in mind that you’re trusting the VPN provider a lot. Do you really trust them more than your ISP? If you truly want a VPN, use a provider you’re sure you trust, and you should probably pay for it. Or set up WireGuard for yourself – it’s excellent!
There are also secure configuration settings for a lot of internet-enabled applications at cipherli.st. If you’re particularly privacy-oriented, privacytools.io is also a good resource.
Some of you may wonder about Tor. Keep in mind that Tor is not particularly resistant to powerful global attackers, and is weak against traffic analysis attacks. It may be useful for hiding traffic on a small scale, but won’t really buy you all that much in terms of privacy. You’re better off using more secure services in the first place (Signal, TLS + certificate pinning, etc.).
Web Security
So, you want to go on the Web too? Jeez, you’re really pushing your luck here.
Install HTTPS Everywhere. SSL/TLS is critical, and it’s not just about encryption, but also about being able to verify that you’re talking to the right service in the first place! If you run your own web server, test it and test it again. TLS configuration can get hairy. HTTPS Everywhere will do its very best to never navigate you to HTTP sites when there’s an alternative. That doesn’t save you, but it helps. If you’re truly paranoid, blacklist any SSL/TLS CAs that you don’t absolutely need.
Install uBlock Origin. It is a wide-spectrum blocker that doesn’t just stop ads, but all sorts of third-party communication a page may try to do. And inline scripts and such. If you’re willing to spend some time on configuration to make things work, go to medium mode or even hard mode. Those will make some sites not work until you’ve fiddled with the settings enough, but will also significantly improve your online security.
If you’re using Firefox, enable Multi-Account Containers. Create separate containers for social networks, banking, shopping, etc. Firefox will keep the cookies and other state for each of the containers totally separate, so sites you visit in one container can’t snoop on sensitive data from the others. In Google Chrome, you can use Chrome Profiles to achieve similar results.
Exercises
TODO
- Encrypt a file using PGP
- Use veracrypt to create a simple encrypted volume
- Enable 2FA for your most data sensitive accounts i.e. GMail, Dropbox, Github, &c
Solution-安全与密码学
1. 熵
假设一个密码是从四个小写的单词拼接组成,每个单词都是从一个含有10万单词的字典中随机选择,且每个单词选中的概率相同。 一个符合这样构造的例子是 correcthorsebatterystaple
。这个密码有多少比特的熵? 假设另一个密码是用八个随机的大小写字母或数字组成。一个符合这样构造的例子是 rg8Ql34g
。这个密码又有多少比特的熵?
Entropy = log_2(100000^4) = 66 #correcthorsebatterystaple
Entropy = log_2((26+26+10)^8) = 48 #rg8Ql34g
也可以使用下面两个网址进行计算
哪一个密码更强? 假设一个攻击者每秒可以尝试1万个密码,这个攻击者需要多久可以分别破解上述两个密码?
第一个更强。
因为每个密码的概率是相同,所以平均而言,需要的破解时间约为尝试所有可能密码所花时间的一半(概率论期望值的简单应用,记所有可能密码个数为x,每年尝试的密码数为y,破解所需的平均时间为:1x⋅y(1+2+⋯+x)=1x×(1+x)×x/2y=12×1+xy1�⋅�(1+2+⋯+�)=1�×(1+�)×�/2�=12×1+�� )
对于第一个密码:100,0004/104/(365×24×3600)/2=1.085亿年100,0004/104/(365×24×3600)/2=1.085亿年
对于第二个密码:628/104/(365×24×3600)/2=346年628/104/(365×24×3600)/2=346年
2.密码散列函数
从Debian镜像站下载一个光盘映像(比如这个来自阿根廷镜像站的映像)。使用sha256sum
命令对比下载映像的哈希值和官方Debian站公布的哈希值。如果你下载了上面的映像,官方公布的哈希值可以参考这个文件。
curl -O -L -C - http://debian.xfree.com.ar/debian-cd/current/amd64/iso-cd/debian-mac-10.9.0-amd64-netinst.iso
curl -O https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA256SUMS
注意这里 SHA256SUMS 包含的版本号,下载的 iso 文件也要是对应的版本号。原文中是 10.2.0版本,这里我们下载的是 10.9.0。当您看到此文时,可能版本又更新了,请到这里下载最新版本。
接下来进行哈希比对:
cat SHA256SUMS | grep debian-10.9.0-amd64-netinst.iso
8660593d10de0ce7577c9de4dab886ff540bc9843659c8879d8eea0ab224c109 debian-10.9.0-amd64-netinst.iso
shasum -a 256 debian-10.9.0-amd64-netinst.iso
8660593d10de0ce7577c9de4dab886ff540bc9843659c8879d8eea0ab224c109 debian-10.9.0-amd64-netinst.iso
可以看出来两个哈希是一样的。 也可以用diff
直接比较:
diff <(cat SHA256SUMS |grep debian-10.9.0-amd64-netinst.iso) <(shasum -a 256 debian-10.9.0-amd64-netinst.iso)
3. 对称加密
使用 OpenSSL的AES模式加密一个文件: openssl aes-256-cbc -salt -in {源文件名} -out {加密文件名}
。 使用cat
或者hexdump
对比源文件和加密的文件,再用 openssl aes-256-cbc -d -in {加密文件名} -out {解密文件名}
命令解密刚刚加密的文件。最后使用cmp
命令确认源文件和解密后的文件内容相同。
echo "hello world" > afile #创建一个文件
openssl aes-256-cbc -salt -in afile -out secfile #加密文件
enter aes-256-cbc encryption password:***
Verifying - enter aes-256-cbc encryption password:***
使用 hexdump
比较两个文件
diff <(hexdump afile) <(hexdump secfile)
1,2c1,3
< 0000000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a
< 000000c
---
> 0000000 53 61 6c 74 65 64 5f 5f cb 18 f1 7c 4f 09 b4 21
> 0000010 d2 f1 56 77 80 01 b1 2f ac 2d 32 35 52 23 2e c6
> 0000020
使用cat
比较两个文件
cat afile
# hello world
cat secfile
# Salted__|O !Vw/-25R#.%
对文件进行解密
openssl aes-256-cbc -d -in secfile -out notsafefile
cmp afile notsafefile
?
# 返回0,表示这两个文件内容相同
4.非对称加密
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/xxxxx/.ssh/id_ed25519): pw.txt
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in pw.txt
Your public key has been saved in pw.txt.pub
The key fingerprint is:
SHA256:k8Pzh2g5WYtgFJjpKRhXydIn5FGHsdpeFIjJMQIH+IM xxxxx@DESKTOP-TOR9E2L
The key's randomart image is:
+--[ED25519 256]--+
|+oo**X++o |
|o.oo%o++ . |
| * o.+o . |
|E + o+ o . |
| o. + S . |
| o o @ o |
| . B + . |
| . . . |
| |
+----[SHA256]-----+
passphrase: baozi
-
配置GPG。 Linux 系统可以直接按照上面的教程操作,MacOS 上的操作过程如下
<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">re</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mord mathnormal">in</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span></span></span></span> gpg --gen-key
-
给Anish发送一封加密的电子邮件(Anish的公钥)。
导入Anish发布的公钥,并完成验证
~ <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">c</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">h</span><span class="mord mathnormal">ttp</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">//</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal" style="margin-right:0.03588em;">ey</span><span class="mord mathnormal">ba</span><span class="mord mathnormal">se</span><span class="mord">.</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord">/</span><span class="mord mathnormal">ani</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span><span class="mord">/</span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal">eys</span><span class="mord">.</span><span class="mord mathnormal">a</span><span class="mord mathnormal">sc</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord">−</span><span class="mord mathnormal">im</span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.02778em;">or</span><span class="mord mathnormal">t</span><span class="mspace nobreak"> </span></span></span></span> gpg --list-keys # ~/.gnupg/pubring.kbx中除了刚才创建的自己的公钥,还存入了Anish的公钥 ~ gpg --edit-key "Anish Athalye" # 进入gpg控制台 gpg> fpr pub rsa4096/C3F6E4F5086B3B32 2014-10-30 Anish Athalye <me@anishathalye.com> 主密钥指纹: 72EE 4824 FA6E FF1F E750 A015 C3F6 E4F5 086B 3B32 # 将这个密钥指纹与Anish发布在网站上的做匹配,一致
接下来,使用Anish的公钥加密信息
~ touch message.txt ~ <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.791em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">ec</span><span class="mord mathnormal">h</span><span class="mord"><span class="mord mathnormal">o</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mathnormal">h</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.01968em;">ll</span><span class="mord"><span class="mord mathnormal">o</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">ess</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">e</span><span class="mord">.</span><span class="mord mathnormal">t</span><span class="mord mathnormal">x</span><span class="mord mathnormal">t</span><span class="mspace nobreak"> </span></span></span></span> gpg --encrypt --sign --armor -r me@anishathalye.com message.txt # 在本目录下会生成一个message.txt.asc的加密文件 # 这个文件,只有拥有私钥的Anish能解密 # 如果你也想查看这个加密文件,需要使用: ~ gpg --encrypt --sign --armor -r me@anishathalye.com -r usrname@example.com message.txt # 添加第二个 -r 接收人为你自己,你就能解密这个文件 ~ gpg message.txt.asc
接下来,你就可以尝试用邮件或其他方式,将这个使用Anish的公钥加密的文件发送给他(这里只是做说明,不推荐发送无意义的信息!)
-
使用
git commit -S
命令签名一个Git提交,并使用git show --show-signature
命令验证这个提交的签名。或者,使用git tag -s命令签名一个Git标签,并使用git tag -v
命令验证标签的签名。git commit -S -m "sign a commit"
可能会出现下面的错误
error: gpg failed to sign the data fatal: failed to write commit object
这个问题网上有一些解决方案可供参考:
如果遇到
echo "test" | gpg --clearsign gpg: [stdin]: clear-sign failed: Inappropriate ioctl for device
则执行
export GPG_TTY=<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">tt</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mord">‘‘‘</span><span class="mord cjk_fallback">此外要注意</span><span class="mord">‘</span><span class="mspace nobreak"> </span><span class="mord">/.</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal">co</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord">‘</span><span class="mord cjk_fallback">里面的</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span><span class="mord cjk_fallback">,</span><span class="mord mathnormal">e</span><span class="mord mathnormal">mai</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord cjk_fallback">要和生成秘钥时使用的一样,签名算法也是一样的:</span><span class="mord">‘‘‘</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">−</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal" style="margin-right:0.03588em;">ey</span><span class="mord mathnormal">i</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal" style="margin-right:0.02778em;">or</span><span class="mord mathnormal">ma</span><span class="mord mathnormal" style="margin-right:0.05764em;">tS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal" style="margin-right:0.13889em;">ORT</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mord mathnormal">sers</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">in</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord">/.</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">n</span><span class="mord mathnormal">u</span><span class="mord mathnormal">p</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord">/</span><span class="mord mathnormal">p</span><span class="mord mathnormal">u</span><span class="mord mathnormal">b</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">in</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord">.</span><span class="mord mathnormal">kb</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mord mathnormal">secrs</span><span class="mord mathnormal">a</span><span class="mord">2048/56</span><span class="mord mathnormal" style="margin-right:0.13889em;">EF</span><span class="mord">5</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord">32021</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">05</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">15</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord cjk_fallback">有效至:</span><span class="mord">2023</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">05</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">15</span><span class="mclose">]</span><span class="mord">35</span><span class="mord mathnormal">A</span><span class="mord">0</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord">790</span><span class="mord mathnormal" style="margin-right:0.05764em;">EBBFE</span><span class="mord">193422975097</span><span class="mord mathnormal" style="margin-right:0.07153em;">FC</span><span class="mord">49956</span><span class="mord mathnormal" style="margin-right:0.13889em;">EF</span><span class="mord">5</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord">3</span><span class="mord mathnormal">u</span><span class="mord mathnormal">i</span><span class="mord mathnormal">d</span><span class="mopen">[</span><span class="mord cjk_fallback">绝对</span><span class="mclose">]</span><span class="mord mathnormal">han</span><span class="mord mathnormal">x</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">o</span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">han</span><span class="mord mathnormal">x</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">o</span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mord">@</span><span class="mord mathnormal" style="margin-right:0.03588em;">qq</span><span class="mord">.</span><span class="mord mathnormal">co</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ss</span><span class="mord mathnormal">b</span><span class="mord mathnormal">rs</span><span class="mord mathnormal">a</span><span class="mord">2048/55</span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span><span class="mord">91952021</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">05</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">15</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord cjk_fallback">有效至:</span><span class="mord">2023</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">05</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">15</span><span class="mclose">]</span><span class="mord">‘‘‘</span><span class="mord cjk_fallback">对应的</span><span class="mord"> ‘.</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal">co</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord">‘</span><span class="mord cjk_fallback">为</span><span class="mord">‘‘‘</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">ser</span><span class="mclose">]</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">han</span><span class="mord mathnormal">x</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">o</span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">ce</span><span class="mord mathnormal">mai</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">han</span><span class="mord mathnormal">x</span><span class="mord mathnormal">ia</span><span class="mord mathnormal">o</span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mord">@</span><span class="mord mathnormal" style="margin-right:0.03588em;">qq</span><span class="mord">.</span><span class="mord mathnormal">co</span><span class="mord mathnormal">m</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">nin</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal" style="margin-right:0.03588em;">Key</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">55</span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span><span class="mord">9195‘‘‘</span><span class="mord cjk_fallback">所有问题都解决后,正常签名</span><span class="mord">‘‘‘</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal">co</span><span class="mord mathnormal">mmi</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mord">"</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">na</span><span class="mord mathnormal">co</span><span class="mord mathnormal">mmi</span><span class="mord mathnormal">t</span><span class="mord">"</span><span class="mopen">[</span><span class="mord mathnormal">main</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">c</span><span class="mord">8</span><span class="mord mathnormal">e</span><span class="mord">916</span><span class="mclose">]</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">na</span><span class="mord mathnormal">co</span><span class="mord mathnormal">mmi</span><span class="mord mathnormal">t</span><span class="mord">3</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">esc</span><span class="mord mathnormal">han</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">e</span><span class="mord mathnormal">d</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">3</span><span class="mord mathnormal">in</span><span class="mord mathnormal" style="margin-right:0.02778em;">ser</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">s</span><span class="mopen">(</span><span class="mord">+</span><span class="mclose">)</span><span class="mord mathnormal">cre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mord mathnormal">m</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord">100644</span><span class="mord mathnormal">sec</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">/</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">ecre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mord mathnormal">m</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord">100644</span><span class="mord mathnormal">sec</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">/</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mord mathnormal">t</span><span class="mord mathnormal">s</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">ecre</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">e</span><span class="mord mathnormal">m</span><span class="mord mathnormal">o</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord">100644</span><span class="mord mathnormal">sec</span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">/</span><span class="mord mathnormal">sec</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord">‘‘‘</span><span class="mclose">!</span><span class="mopen">[</span><span class="mord">1.</span><span class="mord mathnormal">p</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mclose">]</span><span class="mopen">(</span><span class="mord mathnormal">h</span><span class="mord mathnormal">ttp</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">//</span><span class="mord mathnormal">mi</span><span class="mord mathnormal">ss</span><span class="mord mathnormal">in</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6984em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">se</span><span class="mord mathnormal">m</span><span class="mord mathnormal">es</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.02778em;">er</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mord mathnormal">n</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mord mathnormal">h</span><span class="mord mathnormal">u</span><span class="mord mathnormal">b</span><span class="mord">.</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord">/</span><span class="mord mathnormal">mi</span><span class="mord mathnormal">ss</span><span class="mord mathnormal">in</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6984em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mord mathnormal">t</span><span class="mord mathnormal">es</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">an</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">so</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">u</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">s</span><span class="mord">/2020/</span><span class="mord mathnormal">so</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">u</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">o</span><span class="mord mathnormal">n</span><span class="mord mathnormal">s</span><span class="mord">/</span><span class="mord mathnormal">ima</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">es</span><span class="mord">/9/1.</span><span class="mord mathnormal">p</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mclose">)</span><span class="mord cjk_fallback">创建一个带签名的标签,并验证</span><span class="mord">‘‘‘</span><span class="mspace nobreak"> </span><span class="mord">/</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">i</span><span class="mord mathnormal">t</span><span class="mopen">(</span><span class="mord mathnormal">main</span><span class="mclose">)</span></span></span></span> git tag -s "v0.0.0" -m "Create a tag" ~/signgit (main) $ git tag -v v0.0.0 object 03fa307f9ced5d9717473a429d76122e46c7a70f type commit tag v0.0.0 tagger usrname <usrname@example.com> 1683883065 +0800 Create a tag gpg: Signature made Fri May 12 17:18:13 2023 CST gpg: using RSA key 07C700F1B0F8A6BFDA61571CA29FF423FCBD1279 gpg: issuer "usrname@example.com" gpg: Good signature from "usrname <usrname@example.com>" [ultimate]