<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>ulyc</title>
        <link>https://paragraph.com/@ulyc</link>
        <description>undefined</description>
        <lastBuildDate>Wed, 15 Apr 2026 14:53:47 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>ulyc</title>
            <url>https://storage.googleapis.com/papyrus_images/dbacac9ba577b4b8f20493e1fc46782e513318be840ea7864afa5adbe75fa66d.jpg</url>
            <link>https://paragraph.com/@ulyc</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[2021年，用更现代的方法使用PGP（下）]]></title>
            <link>https://paragraph.com/@ulyc/2021-pgp-3</link>
            <guid>JBhUwSlWks6kXCkUIMLk</guid>
            <pubDate>Tue, 30 Nov 2021 00:53:41 GMT</pubDate>
            <description><![CDATA[世界上有两种密码:一种是防止你的小妹妹偷看你的文件;另一种是防止当局阅读你的文件.​ —— Bruce Schneier《应用密码学》2021年，用更现代的方法使用PGP（下）上篇链接:2021年，用更现代的方法使用PGP（上） 2021年，用更现代的方法使用PGP（中）PGP 公钥的 发布 与 交换讨论公钥安全交换的中文文章比较少，而这一环是整个加密体系的重中之重。 大部分的PGP教程最后一步就是让小白用户将公钥上传，这是非常过时，且不负责任的，所以这里来详细介绍下PGP 公钥的 发布 与 交换。原则首先明确一点： 上传公钥到 公钥服务器 不是必要的，甚至是危险的。 如果你是新手，请不要发布你的公钥到 公钥服务器。引子通过前文，你已经熟悉了gpg的本地使用， 并且生成了自己的PGP 密钥对。 想象一下， 如果你生活在1980年代， 想和远方的朋友加密通信，需要先交换彼此的公钥，又没有一个统一的可信的认证机构，这时会有什么问题？ 当面交换吗？当然是个办法，但是相信你不会想要将下列1609751914957这么长的公钥抄写到纸上，然后开车送到朋友那里，再让朋友照着这个输入他的电脑。...]]></description>
            <content:encoded><![CDATA[<blockquote><p>世界上有两种密码:一种是防止你的小妹妹偷看你的文件;另一种是防止当局阅读你的文件.​ —— Bruce Schneier《应用密码学》</p></blockquote><h1 id="h-2021pgp" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2021年，用更现代的方法使用PGP（下）</h1><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">上篇链接:</h4><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2021/01/13/2021%E5%B9%B4-%E7%94%A8%E6%9B%B4%E7%8E%B0%E4%BB%A3%E7%9A%84%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8PGP-%E4%B8%8A/">2021年，用更现代的方法使用PGP（上）</a> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2021/01/18/2021%E5%B9%B4-%E7%94%A8%E6%9B%B4%E7%8E%B0%E4%BB%A3%E7%9A%84%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8PGP-%E4%B8%AD/">2021年，用更现代的方法使用PGP（中）</a></p><h1 id="h-pgp" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">PGP 公钥的 发布 与 交换</h1><p>讨论公钥安全交换的中文文章比较少，而这一环是整个加密体系的重中之重。 大部分的PGP教程最后一步就是让小白用户将公钥上传，这是非常过时，且不负责任的，所以这里来详细介绍下PGP 公钥的 发布 与 交换。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">原则</h2><p>首先明确一点： 上传公钥到 公钥服务器 <strong>不是</strong>必要的，甚至是<strong>危险</strong>的。</p><p>如果你是新手，请不要发布你的公钥到 公钥服务器。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">引子</h2><p>通过前文，你已经熟悉了gpg的本地使用， 并且生成了自己的PGP 密钥对。</p><p>想象一下， 如果你生活在1980年代， 想和远方的朋友加密通信，需要先交换彼此的公钥，又没有一个统一的可信的认证机构，这时会有什么问题？</p><p>当面交换吗？当然是个办法，但是相信你不会想要将下列</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/97434e57c86394f7a7a8ff213ee79c6a30515ff88b51d208fc53a34b497cd9ec.png" alt="1609751914957" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1609751914957</figcaption></figure><p>这么长的公钥抄写到纸上，然后开车送到朋友那里，再让朋友照着这个输入他的电脑。如果中间有变动，需要重复以上过程n次。</p><p>那么还有其他办法吗？</p><p>那个时代还没有line、wechat这类即时通讯软件，而邮件提供商默认是不可靠的，不然也不会有PGP的诞生。 并且彼时https还未出现，用邮件交换PGP交换公钥显然不太安全。</p><p>你们双方都需要便捷地交换公玥， 并且确认彼此得到的公钥确实是未经篡改过的，真实有效的，就成了一个难题，这样，公钥服务器也就呼之欲出了。</p><h2 id="h-keyserver" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">公钥服务器 KeyServer</h2><p>公钥服务器使得人们只需要交换他们短短的key id 或者user id就可以方便地从公钥服务器下载公钥。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">历史与设计初衷</h3><p>第一个KeyServer 叫做 HKP（ web-based OpenPGP HTTP Keyserver Protocol） Keyserver ， 诞生在上世纪90年代，是Marc Horowitz在麻省理工学习时为了他的论文而搭建的。在此之前， 虽然不是那么安全， 但是大部分人依靠电子邮件来交换公钥。</p><p>虽然服务器有了， 但开发者们担心政府会试图强迫钥匙服务器运营商用政府选择的各种证书来替换证书。</p><p>所以他们做出了一个决定：公钥服务器永远不会删除信息。公钥服务器可以为现有的证书添加信息（比如可以revoke/sign或者调整expire时间），但永远永远永远不会删除证书或证书的信息。</p><p>为了达到这个目标，他们开始运行一个<strong>分布式</strong>的国际公钥服务器网络，这就是现在的KeyServer。世界各地的公钥服务器会定期相互通信，同步，比较目录。如果政府强迫公钥服务器运营商删除或修改证书，那么在比较步骤中就会被发现。残缺的公钥服务器会用完好钥匙服务器目录中的内容更新自己。</p><p>任何东西都不会被删除，听起来很美好，也是解决政府审查问题的一个简单而有效的办法，可是正是这个原则后来给KeyServer带来了无穷无尽的问题。</p><h3 id="h-web-of-trust" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">信任网络 (Web of Trust)</h3><p>好了，现在我们有了一个可以方便地上传和下载公钥的地方， 这样是不是就万事大吉了呢？</p><p>对于KeyServer 来说，任何人都可以上传公钥并声称自己是Linus, 是Zuckerberg,或是任何其他人，而KeyServer并不会去验证你是否是你所声称的人（因为KeyServer本来就没有一个中心化的运营者）。</p><p>如果你有一些密码学的基础， 那么就会知道， PGP协议依靠的非对称加密算法， 最脆弱的点就在于公钥的交换这一步。公钥交换时最容易收到中间人攻击，你一定要确定你接收到的公钥确实是你想交流的人的，由此TSL引入了CA证书认证体系，由一个可信的权威第三方来认证并颁发证书来解决身份的认证问题。 （具体可参见https系列<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2018/09/21/%E6%B2%A1%E9%82%A3%E4%B9%88%E6%B5%85%E5%9C%B0%E8%B0%88%E8%B0%88HTTP%E4%B8%8EHTTPS-%E4%BA%8C.html">没那么浅地谈谈HTTP与HTTPS</a>）。</p><p>“信任一个权威的第三方” 对于最初的极具有hack精神的开发者们来说， 显然是无法接受的。</p><p>当然，你可以说下载公钥后，通过电话等手段验证下公钥的指纹（fingerprint），就可以确认正确与否。 但是想象一下， 如果你在公钥服务器找到一个声称自己Linus Torvalds 的人, 你并没有他的其他联系方式，将永远无法确定这个公钥持有者到底是谁、这个公钥可信与否 ， 这样无疑是低效的，并且使整个系统沦为了熟人之间的小网络。</p><p>要知道，根据六度分隔理论（Six Degrees of Separation），世界上任何互不相识的两人，平均通过六个人就可以产生联系。 那么可以不可以这么思考， 假设我和小A见过面并检查过他的公钥，因而知道小A的公钥的的确确属于他本人，我选择信任小A。而小A同样验证了小B的证书并为小B的证书签名背书——小A的证书的持有人在此证明该证书是真实属于小B。那么我无须见亲见小B本人，也可以通过小A的背书而接受小B的证书。</p><p>如此循环下去，就形成了一张网， 这就是信任网络。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">主流公钥服务器</h3><h4 id="h-1-sks-keyserver-pool" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">1. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://sks-keyservers.net/">SKS Keyserver Pool</a></h4><p>当今世界最大的Key Server 池， 符合它的标准的世界各地的公钥服务器会定期相互通信，同步，比较目录，数据完全开放下载。 现在一般说起KeyServer说的就是这个。</p><p>KeyServer虽然一直是PGP的重要基础设置 ,但SKS Keyserver Pool 其实目前只有不到20台服务器，GnuPG默认用的服务器是其中的 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://hkps.pool.sks-keyservers.net">HKPS pool</a>,只有四台服务器。</p><h4 id="h-2-base-modern-software-keyserver" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">2. Base Modern Software KeyServer</h4><p>有一些KeyServer 没有用SKS的软件，运行的是更下现代和稳定的软件，比较有代表性的是 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://keyserver.ubuntu.com/"><strong>Ubuntu keyserver</strong></a>, 基于Hockeypuck ， 这些服务器仍然会和SKS pool保持同步。</p><h4 id="h-3-keyserver" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">3. 独立KeyServer</h4><p>这些服务器不与SKS pool同步数据，由中心化的运营者运行， 会对公钥上传者做一定的认证， 并且支持删除自己的公钥。</p><p>比较有代表性的有， <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://keys.openpgp.org/"><strong>keys.openpgp.org</strong></a> ，KeyBase等等。</p><h3 id="h-gpg" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">在gpg中使用</h3><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">发布</h4><pre data-type="codeBlock" text="gpg   --send-keys  {keyid/uid}
"><code>gpg   <span class="hljs-operator">-</span><span class="hljs-operator">-</span>send<span class="hljs-operator">-</span>keys  {keyid<span class="hljs-operator">/</span>uid}
</code></pre><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">下载</h4><pre data-type="codeBlock" text="gpg --recv-keys {keyid/uid}
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>recv<span class="hljs-operator">-</span>keys {keyid<span class="hljs-operator">/</span>uid}
</code></pre><p>此时有可能报错</p><pre data-type="codeBlock" text="gpg: &quot;xxxxxr&quot; not a key ID: skipping
"><code><span class="hljs-symbol">gpg:</span> <span class="hljs-string">"xxxxxr"</span> <span class="hljs-built_in">not</span> a <span class="hljs-keyword">key</span> ID: skipping
</code></pre><p>这时换个KeyServer就行：</p><pre data-type="codeBlock" text="gpg  --keyserver hkps://keyserver.ubuntu.com --recv-keys {keyid/uid}
"><code>gpg  --keyserver hkps:<span class="hljs-regexp">//</span>keyserver.ubuntu.com --<span class="hljs-keyword">recv</span>-<span class="hljs-keyword">keys</span> {keyid/uid}
</code></pre><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">签名和验证 他人公钥</h4><p>验证公钥真实性 依靠多渠道确认的 公钥指纹。</p><p>一般来说为别人的公钥签名后，需要发还给他，或者发到公钥服务器(最好经过本人同意)。</p><pre data-type="codeBlock" text="gpg --sign-key  {keyid/uid}   # 为已经导入的 他人钥签名， 你为他签名，意味着你将为他的身份真实性背书，请谨慎 
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>sign<span class="hljs-operator">-</span>key  {keyid<span class="hljs-operator">/</span>uid}   # 为已经导入的 他人钥签名， 你为他签名，意味着你将为他的身份真实性背书，请谨慎 
</code></pre><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">高级设置</h4><p>因为并不推荐大家使用KeyServer，所以这里只列举了基础操作。</p><p>如果你决定使用KeyServer的话，可以参考 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nova.moe/openpgp-best-practices-keyserver-and-configuration/">OpenPGP 最佳实践 - 密钥服务器</a>设置你的客户端与服务器通信使用 HKPS (HKP On SSL)协议， 并定期更新从服务器下载的公钥。</p><h3 id="h-keyserver" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">安全风险和争议， 被玩坏的KeyServer</h3><p>在20世纪90年代初，开发者们怀着对技术的信心和人性的希望，期望创建一个友善 、纯粹、没有审查的净土， 在当时背景下，KeyServer不能删除任何已上传的东西，听起来是美好的，设计似乎是合理的。</p><p>但是事实是，网络匿名环境中充满了不那么友好的， 甚至是恶意的使用者，在当今看来 ，KeyServer这个系统并不健壮，问题重重，许多问题已经被发现十多年，而且无望解决。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">滥用</h4><p>按照官方推荐， UID （User ID） 是用来存储用户信息的，应该在里面填上你的名字和邮箱，一个 GPG 帐号下可以有若干个 UID。</p><p>而其实这个UID是没有任何强制限制的，也就是说你可以在UID中放入任何东西，可以是小说片段，可以是磁力链接,可是以编码后的图像、音频或视频......</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/514ea3bbbfd43f3177d1bdbc7e013ac2d4eb1d43c80f41d05ce2f7dc879adf3a.png" alt="1609913349212" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1609913349212</figcaption></figure><p>当上传到KeyServer时, UID限制了2k的字符 . 以至于有人写了个用KeyServer<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/yakamok/keyserver-fs">存文件的项目keyserver-fs)</a>。</p><p>再次想象一下，你往网盘传了一个文件，共享给其他人，全世界的人都可以往这个网盘文件中添加文件，而且永远无法删除，情况会变得有多糟糕。</p><h4 id="h-keyid" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">脆弱的KeyID</h4><p>见过一些生成 PGP“靓号”的工具，就是指定你喜欢的ID规则，工具会暴力生成PGP密钥， 从中返回给你想要的密钥。</p><p>由此很容易想到，若攻击者知道了目标的KeyID， 完全可以通过工具来生成完全一样的KeyID（这就是碰撞）, 并上传到KeyServer，来冒充目标。</p><p>而伪造一个KeyID有多容易呢，有研究人员借助<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/lachesis/scallion">scallion</a>程序，使用了普通的GPU（<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://www.geforce.com/hardware">Nvidia GeForce GTX</a>）进行碰撞，花了4秒的时间就生成了一个指定的32 bit的 KeyID。</p><p>官方推荐公布自己的KeyID时，最少应该公布64 bit（也就是长16位16进制数啦 ），但是<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://thread.gmane.org/gmane.ietf.openpgp/7413">研究</a>表明64 bit的KeyID也是可以 被碰撞的。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">投毒</h4><p>公钥服务器任何人都可以上传公钥，甚至你可以上传别人的公钥，比如你可以将自己签名过的别人的公钥，再次上传到KeyServer。</p><h5 id="h-dos" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">签名Dos</h5><p>在WOT认证体系的设计中， 当客户端收到一份未知证书时，它应当从公钥服务器拉取所有为这张证书签过名的人的证书，逐层上溯，看看是否能够找到一张已经被用户信任的证书。如果能的话，就视信任这张为可信的。</p><p>2019年6月，有攻击者恶意向公钥服务器提交了对两个著名网友的签名背书。此事件中的受害者 Robert J. Hansen 的证书就被签名了 15000 次。因而任何人的 GPG 在尝试验证他的证书时，都会拉取 15000 个签名。而 GPG 在验证这么多签名的过程中会卡住很久。</p><p>由于被攻击的两个人在 GPG 社区中中地位很高，他们在 GPG 信任网络中处于相当核心的位置。这意味着——当你验证任意一份证书的时候，有不小的概率你会不小心拉取到他们俩的证书，然后你的 GPG 就会卡住。不但他们俩的证书没法用了，他们俩签名过的证书也都面临危险，乃至于他们俩签名过的证书所签名的证书……</p><p>而上传到KeyServer的所有东西都是不可删除的...为了解决这个问题， <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://lwn.net/Articles/793288/">GnuPG 2.2.17 LWN.net</a> 开始， 从KeyServer下载公钥时默认不再下载关联的公钥， 如果你想要感受证书DoS攻击的话，可以在设置中开启：</p><pre data-type="codeBlock" text="# ~/.gnupg/gpg.conf
keyserver-options no-self-sigs-only,no-import-clean
"><code># <span class="hljs-operator">~</span><span class="hljs-operator">/</span>.gnupg/gpg.conf
keyserver<span class="hljs-operator">-</span>options no<span class="hljs-operator">-</span><span class="hljs-built_in">self</span><span class="hljs-operator">-</span>sigs<span class="hljs-operator">-</span>only,no<span class="hljs-operator">-</span><span class="hljs-keyword">import</span><span class="hljs-operator">-</span><span class="hljs-title">clean</span>
</code></pre><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">爆破</h5><p>有个很厉害的程序媛Yegor Timoshenko（前面的SKS文件存储项目也是她的杰作），写了个工具<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/yegortimoshenko/sks-exploit">SKS-Exploit</a>，可以将任何人的PGP公钥<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://keyserver.2ndquadrant.com/pks/lookup?search=0x41259773973A612A&amp;op=vindex">损坏</a>，变得不可导入。</p><p>这个工具同时还可以给任意人的公钥 追加伪造的UID（不是KeyID），并骗过KeyServer。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/26c969b8a10de60a8f5b7d9f562eb7ef39080672697f11f9916716a74b46485a.png" alt="1609914787731" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1609914787731</figcaption></figure><p>另外能直接让KeyServer宕机。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/399973d978c977cfbd12cc6d7965a9204e9305cf9e0fc015905089d9ec78a705.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">隐私问题</h4><p>讽刺的是， 最初为了保护人们隐私而生的PGP , 却因为不能满足保护隐私的法规GDPR ，而使一个公开的 SKS 公钥服务器在欧洲处于违法状态（GDPR规定： 服务商必须提供删除个人信息的选项）。</p><p>许多新手按照教程提示的在创建PGP 密钥的时候填上了自己的真实姓名，并按照那些教程将公钥上传到了KeyServer，在人肉社工猖獗的今天，简直是个灾难。</p><p>我试着在KeyServer搜过一些博客作者留下的PGP Key， 不乏有些比较注重自身隐私的，可是他们大部分都将自己真实的名字（汉字或拼音）和邮箱一起发到了服务器上，要知道那里的数据是公开且永远不能删除的。 也有些人意识到问题之后revoke了带有真实姓名的公钥，可是仍然可以查到，并且变得更加显眼（revoke过的key会变红）。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">其他发布公钥的方法</h2><h3 id="h-1-wkdweb-key-directory" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">1. WKD（Web Key Directory）</h3><p>WKD 的工作过程是 ，通过邮箱客户端 在域名服务器检查一个&quot;well known&quot; 的URL， 如果匹配到了邮箱地址对应的公钥，会使用https下载，并且不需要用户进行其他操作。用户不需要gpg 命令行等等复杂操作，让PGP加密回归单纯的邮件加密本身，用起来有些像S/MIME,但其实不一样。</p><p>比如这样一个URL: <code>https://intevation.de/.well-known/openPGPkey/hu/g8td9rsyatrazsoiho37j9n3g5ypp34h</code> 就对应 &quot;<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="mailto:aheinecke@intevation.de">aheinecke@intevation.de</a>&quot;这个邮箱地址。</p><p>这是通过Gpg4win的使用的一个示例，</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f2de961204d71be8b28f0bb69a81bbfe50682c388148f14d828545948df4bb07.gif" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>这种方法不会泄露自己的邮箱，也不需要验证指纹， 但是需要你的邮件服务商提供支持。</p><p>proton邮箱是原生支持 WKD的， 但是它使用的是自己私钥，似乎没办法使用使用自己本地的公钥，其他也有支持。</p><p>如果你有自己的邮箱服务器，并且想折腾的话，可以参照<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://wiki.gnupg.org/WKDHosting">WKD Hosting</a>。</p><h3 id="h-2" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">2. 当面交换</h3><p>如果是和熟识的朋友，你可以约在任何合适地方，用你喜欢的方式交换密钥， 比如交换纸条，交换TF卡 或者usb设备，互相签名认证，互相得到公钥。</p><p>如果是想认识更多的人，并让自己的公钥被更多的人认证， 你可以参加「公钥签名派对（<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Key_signing_party">Key signing party</a>）」。参与派对的人们相互交换公钥的指纹（公钥一般是存在服务器或是一个别人可以下载到的地方，这里只交换指纹），甚至需要相互出示身份证、护照、驾照、出身证明，以验明正身。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ef73140aa7fbdc9d3caeb0f28c1b68dff7a39d6026ae59b63540ea7c47301cdd.jpg" alt="Key signing in front of FOSDEM 2008" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Key signing in front of FOSDEM 2008</figcaption></figure><h3 id="h-3-dns" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3. DNS</h3><p>有很多种方法将你的公钥通过DNS服务发布，但是有些一些方法只适用于老版本的GnuPG，有些方法只适用与新版本的GnuPG，兼容性不佳，而且搞起来比较繁琐，有兴趣的可以自行查找资料。在这里并不推荐使用。</p><h3 id="h-4" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4.个人网站 或 社交软件中</h3><p>现在中文世界， PGP的使用者中 有很多都是 独立的博客作者， 如果你拥有自己的博客或者个人网站，当然可以选择将自己的公钥发布在上面，最好给你的网站上一个Https 。</p><p>很多社交网站的个人展示页，可以自由编辑你的信息，你可以将PGP的 公钥发布在这里， 或者将 指纹 放在这， 这样通过其他渠道下载到公钥的人，也可以确认身份。</p><h3 id="h-5-gist" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">5. 代码仓库或Gist</h3><p>无论你是不是开发者， 都可以拥有一个Github账号， 你可以开一个仓库专门用来发布自己的公钥，或者将公钥发布到Gist。</p><h3 id="h-6" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">6. 共享笔记</h3><p>Notion或者印象笔记等可以共享笔记的地方，都可以贴出你的公钥。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">最后</h2><p>使用分散的、多渠道的、可能是线下的方式来交换和确认公钥 ，不要相信在放一处的 公钥 和指纹。</p><p>去验证紧跟在公钥后面的指纹 ， 就像你去问一个诈骗者，他是不是一个诈骗者一样无用。</p><p>如果不是当面，请至少从两个渠道进行验证，比如你从一个渠道（比如<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/pgp_keys.asc/">这里</a>）得到了我的公钥 , 你想和我安全通信的话，导入前一定要从另一处（比如我公布的其他账号的简介）得到我的指纹， 验证是否一致后再进行操作。</p><p>而且每次使用前，请重复以上步骤，确保你手上的公钥是最新的。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">参考链接</h2><p>[1]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linux.com/news/protecting-code-integrity-PGP-part-1-basic-PGP-concepts-and-tools/">用 PGP 保护代码完整性系列</a></p><p>[2]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://www.gnupg.org/gph/en/manual.html">The GNU Privacy Handbook</a></p><p>[3]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://jackqqcn.wordpress.com/2008/06/22/gnupg-%E7%94%A8%E5%A4%9A%E4%B8%AAsub-keys%E4%BF%9D%E6%8A%A4primary-key/">GnuPG: 用多个sub keys保护primary key | missing idea (wordpress.com)</a></p><p>[4]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.lancitou.net/PGP-tutorial/">PGP 自我扫盲</a></p><p>[5]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mogeko.me/2019/068/">GPG 的正确使用姿势</a></p><p>[6]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://emailselfdefense.fsf.org/zh-hans/windows.html">电子邮件加密指南</a></p><p>[7]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://www.asheesh.org/note/debian/short-key-ids-are-bad-news.html">Short key IDs are bad news (with OpenPGP and GNU Privacy Guard)</a></p><p>[8]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://blog.shell909090.org/blog/archives/1903/">gnupg密钥签署原理和过程 // Shell&apos;s Home (shell909090.org)</a></p><p>[9]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://roll.urown.net/server/PGP-keyserver.html#a-public-key-shelf">PGP Key Server| Roll Your Own Network</a></p><p>[10]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://medium.com/@mdrahony/are-sks-keyservers-safe-do-we-need-them-7056b495101c">Are SKS keyservers safe? Do we need them?</a></p><p>[11]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gist.github.com/rjhansen/67ab921ffb4084c865b3618d6955275f">SKS Keyserver Network Under Attack</a></p><p>[12]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nova.moe/openPGP-best-practices-keyserver-and-configuration/">OpenPGP 最佳实践 - 公钥服务器</a></p><p>[13]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.wangxuan.name/2019/11/30/gpg-sks-network-poisoned/">GPG SKS 同步网络被投毒事件及其影响</a></p><p>[14]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://superuser.com/questions/227991/where-to-upload-PGP-public-key-are-keyservers-still-surviving">where-to-upload-PGP-public-key-are-keyservers-still-surviving</a></p><p>[15]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zhuanlan.zhihu.com/p/137801979">GPG简明介绍</a></p>]]></content:encoded>
            <author>ulyc@newsletter.paragraph.com (ulyc)</author>
        </item>
        <item>
            <title><![CDATA[2021年，用更现代的方法使用PGP（中）]]></title>
            <link>https://paragraph.com/@ulyc/2021-pgp-2</link>
            <guid>0NdmQlysNS3Lzo3JIsBR</guid>
            <pubDate>Tue, 30 Nov 2021 00:42:01 GMT</pubDate>
            <description><![CDATA[世界上有两种密码:一种是防止你的小妹妹偷看你的文件;另一种是防止当局阅读你的文件. ​ —— Bruce Schneier《应用密码学》上篇链接:2021年，用更现代的方法使用PGP（上）三、安全使用和备份准备为了安全性，建议在一台断网的Linux或者BSD系统上生成你的密钥对。 特别推荐使用 Tails (boum.org)发行版，系统自带gpg和paperkey 等工具, 可以确保全程断网操作, 同时此系统重启会擦除所有内容，还免去了擦除密钥的麻烦。 需要工具：一台电脑一个装有Tails系统的U盘0 , 使用它生成密钥一个已经全盘加密的U盘/TF 卡 1（推荐），或者智能卡 , 用来存储主密钥一个智能卡 (推荐) ，或者已经全盘加密的U盘/TF 卡 2, 用来存放子密钥，日常使用备份策略我的备份策略：主密钥只保留一份，离线。子密钥可以复制多份，通过U盘导入各个设备，专密专用， 日常使用推荐用智能卡（比如Yubikey），还能免去每次输密码的麻烦撤销凭证可以和主密钥放在一起备份一份， 另外单独备份一份（这样丢失密钥，起码还可以撤销）主密钥备份建议备份在一个全盘加密的U盘中，然后...]]></description>
            <content:encoded><![CDATA[<blockquote><p>世界上有两种密码:一种是防止你的小妹妹偷看你的文件;另一种是防止当局阅读你的文件.</p><p>​ —— Bruce Schneier《应用密码学》</p></blockquote><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">上篇链接:</h4><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2021/01/13/2021%E5%B9%B4-%E7%94%A8%E6%9B%B4%E7%8E%B0%E4%BB%A3%E7%9A%84%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8PGP-%E4%B8%8A/">2021年，用更现代的方法使用PGP（上）</a></p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">三、安全使用和备份</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">准备</h3><p>为了安全性，建议在一台断网的Linux或者BSD系统上生成你的密钥对。</p><p>特别推荐使用 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tails.boum.org/">Tails (boum.org)</a>发行版，系统自带gpg和paperkey 等工具, 可以确保全程断网操作, 同时此系统重启会擦除所有内容，还免去了擦除密钥的麻烦。 需要工具：</p><ul><li><p>一台电脑</p></li><li><p>一个装有Tails系统的U盘0 , 使用它生成密钥</p></li><li><p>一个已经全盘加密的U盘/TF 卡 1（推荐），或者智能卡 , 用来存储主密钥</p></li><li><p>一个智能卡 (推荐) ，或者已经全盘加密的U盘/TF 卡 2, 用来存放子密钥，日常使用</p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">备份策略</h3><p>我的备份策略：</p><ul><li><p>主密钥只保留一份，离线。</p></li><li><p>子密钥可以复制多份，通过U盘导入各个设备，专密专用， 日常使用推荐用智能卡（比如Yubikey），还能免去每次输密码的麻烦</p></li><li><p>撤销凭证可以和主密钥放在一起备份一份， 另外单独备份一份（这样丢失密钥，起码还可以撤销）</p></li></ul><p>主密钥备份建议备份在一个全盘加密的U盘中，然后放在一个绝对安全的地方。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">备份介质：</h3><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">智能卡</h5><p>主密钥<strong>不建议</strong>导入智能卡设备，因为智能卡的使用场景是随身携带，随时取用，虽然智能卡中的密钥无法导出，但是随身携带增加了丢失的风险，主密钥一旦丢失，将会非常麻烦。</p><p>如果是土豪，当然导入智能卡中更好，因为智能卡中密钥无法导出，只不过这个智能卡不能再随身携带，而同样应该在一个安全的地方， 不到万不得已不再取用， 不过这样有些浪费，也是我不推荐的理由。</p><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">网盘存储</h5><p>你可以将主私钥加密后上传到网盘或其他线上服务。</p><h5 id="h-paperkey" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">PaperKey</h5><p>又是断网操作，又是非对称算法，还要好好保存一份私钥，这一套流程走下来你也发现了跟数字货币的相似性，很多备份方式都可以借鉴他们的思路，比如上面网盘存储就是数字货币热钱包的思路。</p><p>冷钱包很经典的一种方式，就是将私钥写/打印在纸上， 当然我们也可以借鉴，不过若你想将这一眼望不到头的私钥抄下来， 或者打印下来，将来需要恢复的时候再一个个输入进电脑，显然不现实。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6c14b92be44e40fe3fe46074453ec54e07aab78493dad6091ff12870ed29985c.png" alt="image-20210113111654636" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">image-20210113111654636</figcaption></figure><p>（示例私钥的一部分，用完即废，如果是你自己的私钥，打死也不要给别人看）</p><p>比如比特币， 私钥长这样：</p><pre data-type="codeBlock" text="5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss          # 这么短很容易抄写和输入
"><code>5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss          <span class="hljs-comment"># 这么短很容易抄写和输入</span>
</code></pre><p>同样是非对称算法,为什么PGP的私钥就长这么多呢？</p><p>因为他们用的算法不同，比特币默认使用的是ECDSA的 secp256k1算法， 该算法只是用来签名和认证，并不用来加密（很多科普文章会说这是加密算法，比特币的算法也可以用来加密，这是错的，比特币之所以有时被称作加密货币只是因为它依赖了密码学中的非对称算法，并不是它能加密…），PGP默认的是RSA算法，可以同时用来签名和加密，前面说过目前RSA密钥长度不小于2048 bit才安全，而且PGP导出的私钥中不止密钥信息，还包含了全部的公钥信息，UID，子密钥信息，以及设置密码时的混淆。</p><p>Linux下有一个工具叫做<code>paperkey</code>， 可以用来消去私钥中 冗余的公钥信息，极大减少私钥长度，然后可以将精简过的私钥(base 16格式)打印出来，或者将Raw格式转换成二维码，打印出来。</p><blockquote><p>注意：</p><ul><li><p>既然决定用PaperKey， 还是不要使用网络打印机了，</p></li><li><p>paperkey这个工具在Tails新版中是默认软件</p></li><li><p>paperkey 手册中推荐 恢复私钥时使用OCR扫描， 而大部分OCR服务都要联网， 请注意这点。</p></li></ul></blockquote><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">其他</h5><p>密钥只是一段信息，理论上可以放在其他任何可以存储信息的介质中，例如光盘，<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2019/03/15/%E7%9B%B2%E6%B0%B4%E5%8D%B0%E5%92%8C%E5%9B%BE%E7%89%87%E9%9A%90%E5%86%99%E6%9C%AF/">隐写在图片中</a>， <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2020/01/18/%E5%B8%B8%E8%A7%81RFID%E5%8D%A1%E7%89%87%E4%BB%8B%E7%BB%8D-%E7%A0%B4%E8%A7%A3%E6%80%9D%E8%B7%AF-%E5%8F%8A-Proxmark3%E7%AE%80%E4%BB%8B/">写入IC卡</a> ， <s>纹身，</s>， <s>X光片</s> ，<s>背下来</s> 等等等等，可以发挥你的想象力。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">安全使用</h3><p>请在你信任的电脑上使用子密钥，主密钥不到万不得已不要拿出来用，如果你将子密钥放在智能卡中使用，可以忽略这部分。</p><p>子密钥可以放在移动存储设备上直接使用，而无需拷贝/导入到电脑使用， 使用方法：</p><pre data-type="codeBlock" text="gpg --homedir [你的存储设备的路径]
"><code>gpg <span class="hljs-attr">--homedir</span> <span class="hljs-selector-attr">[你的存储设备的路径]</span>
</code></pre><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">四、进阶使用</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">使用其他算法</h3><p>在为什么安全？一节中 提到PGP支持很多算法，可是前面我们生成密钥时，只见到了很少的几种。</p><p>因为gpg还有一种隐藏模式—- 专家模式，生成密钥时可以使用</p><pre data-type="codeBlock" text="gpg --expert --full-gen-key
# 输出

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
  (14) Existing key from card
  
"><code>gpg <span class="hljs-comment">--expert --full-gen-key</span>
# 输出

Please <span class="hljs-keyword">select</span> what kind <span class="hljs-keyword">of</span> key you want:
   (<span class="hljs-number">1</span>) RSA <span class="hljs-keyword">and</span> RSA (<span class="hljs-keyword">default</span>)
   (<span class="hljs-number">2</span>) DSA <span class="hljs-keyword">and</span> Elgamal
   (<span class="hljs-number">3</span>) DSA (sign <span class="hljs-keyword">only</span>)
   (<span class="hljs-number">4</span>) RSA (sign <span class="hljs-keyword">only</span>)
   (<span class="hljs-number">7</span>) DSA (<span class="hljs-keyword">set</span> your own capabilities)
   (<span class="hljs-number">8</span>) RSA (<span class="hljs-keyword">set</span> your own capabilities)
   (<span class="hljs-number">9</span>) ECC <span class="hljs-keyword">and</span> ECC
  (<span class="hljs-number">10</span>) ECC (sign <span class="hljs-keyword">only</span>)
  (<span class="hljs-number">11</span>) ECC (<span class="hljs-keyword">set</span> your own capabilities)
  (<span class="hljs-number">13</span>) Existing key
  (<span class="hljs-number">14</span>) Existing key <span class="hljs-keyword">from</span> card
  
</code></pre><p>就可以看到多出来不少选项，其中ECC算法 全称Elliptic Curve Cryptography 椭圆曲线密码算法。</p><p>上面我选了 9 , 继续</p><pre data-type="codeBlock" text="  Please select which elliptic curve you want
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256   
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1            # 比特币使用的算法
"><code>  Please select which elliptic curve you want
   (<span class="hljs-number">1</span>) Curve <span class="hljs-number">25519</span>
   (<span class="hljs-number">3</span>) NIST <span class="hljs-selector-tag">P</span>-<span class="hljs-number">256</span>
   (<span class="hljs-number">4</span>) NIST <span class="hljs-selector-tag">P</span>-<span class="hljs-number">384</span>
   (<span class="hljs-number">5</span>) NIST <span class="hljs-selector-tag">P</span>-<span class="hljs-number">521</span>
   (<span class="hljs-number">6</span>) Brainpool <span class="hljs-selector-tag">P</span>-<span class="hljs-number">256</span>   
   (<span class="hljs-number">7</span>) Brainpool <span class="hljs-selector-tag">P</span>-<span class="hljs-number">384</span>
   (<span class="hljs-number">8</span>) Brainpool <span class="hljs-selector-tag">P</span>-<span class="hljs-number">512</span>
   (<span class="hljs-number">9</span>) secp256k1            # 比特币使用的算法
</code></pre><p>其中美国国家标准与技术研究院（NIST）系列椭圆曲线、Brainpool系列椭圆曲线、secp256k1都存在不同的安全风险，不建议使用。</p><p>可以发现这里少了（2）, 其实这里还有一些隐藏算法没有列出，可通过如下命令查看</p><pre data-type="codeBlock" text="gpg --list-config --with-colons curve

# 输出
cfg:curve:   cv25519;ed25519;nistp256;nistp384;nistp521;brainpoolP256r1;brainpoolP384r1;brainpoolP512r1;secp256k1
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>list<span class="hljs-operator">-</span>config <span class="hljs-operator">-</span><span class="hljs-operator">-</span>with<span class="hljs-operator">-</span>colons curve

# 输出
cfg:curve:   cv25519;ed25519;nistp256;nistp384;nistp521;brainpoolP256r1;brainpoolP384r1;brainpoolP512r1;secp256k1
</code></pre><p>上面缺少的(2)对应的就是ed25519 ，是一种签名算法，你选择 （1）时， 主密钥用来签发和签名 用的就是ed25519，自动生成的用来加密的子密钥 算法 是cv25519 。</p><h5 id="h-rsa-vs-ecc" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">RSA VS ECC</h5><p>ECC算法比RSA的优势在于，在<strong>同等强度</strong>下，ECC的密钥长度要小的多，性能也会好一些。 RSA算法的PGP私钥 通过paperkey精简过后一般还会有50+行HEX数据，如果使用的是ECC算法生成的话， 可以减到8行以内，手抄完全没问题。</p><p>RSA算法的优势在于大部分硬件设备的兼容性比较好，比如 YubiKey 5 支持 RSA 4096，但不支持 Curve 25519。而且多数设备都对RSA算法提供了硬件加速。</p><p><strong>PS</strong>:</p><p>查阅资料时发现 ，中文博客里被很多人抄来抄去的一句话：</p><blockquote><p>ed25519 加密解密很快，生成时间短而且安全性更高，rsa 则加密解密稍慢，生成时间长，安全性没有 ed25519 高，只是 rsa 基本都是默认，所以用的人更多，但是建议转换为 ed25519, 网站软件现在基本都支持了.</p></blockquote><p>这句话是 <strong>错的</strong>， ed25519是 EdDSA 算法的一种，只是一种签名算法， EdDSA 全称<strong>Edwards-curve Digital Signature Algorithm</strong>，爱德华椭圆曲线实现的数字签名算法。</p><p>上面的话多出现在替换SSH默认的RSA算法为ed25519的文章中出现。其实SSH协议中的非对称算法 并不是用来加解密信息的，而只是用来认证，正确的说法是ed25519签名和认证的速度很快。</p><p>再者， 不提密钥长度说安全性都是耍流氓 ，RSA 4096 的安全强度是要 好于 ed25519 的。</p><h3 id="h-uid" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">追加UID</h3><p>uid 即 user id ， 由三个部分组成：</p><ul><li><p>全名（现在的话网名即可）</p></li><li><p>注释（用 ( ) 包括）</p></li><li><p>邮箱地址（用 &lt; &gt; 包括）</p></li></ul><p>UID的性质：</p><ul><li><p>一个密钥可以有多个 uid，方便不同场合使用。</p></li><li><p>uid 与哪个子密钥无关，uid 是作用于整个密钥的。</p></li><li><p>uid 可以随时添加，但已有的 uid 不能修改，只能单独吊销。</p></li><li><p>uid 单独吊销后，只需要重新发布公钥即可。</p></li></ul><p>一般来说，操作UID只有主密钥有权限操作， 后面会提到UID可以是伪造，然后提交到服务器的。</p><pre data-type="codeBlock" text="gpg --edit-key {keyid/uid}    


gpg&gt; adduid     # 进入交互界面后 输入  help  可以查看支持的操作

# 输入你要追加的信息
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>edit<span class="hljs-operator">-</span>key {keyid<span class="hljs-operator">/</span>uid}    


gpg<span class="hljs-operator">></span> adduid     # 进入交互界面后 输入  help  可以查看支持的操作

# 输入你要追加的信息
</code></pre><p>使用UID的场景有哪些呢？ 如果你使用一个不常用的邮箱作为你的github/gitlab账号，你主要的邮箱生成的PGP 密钥就不能用来签名了。</p><p>这时候为了保护隐私 且 只要管理一个密钥，就可以 在 Github设置里把 Keep my email addresses private勾上，将为你生成的随机邮箱添加到 uid中， 这样就只需要管理一个PGP密钥，可以同时为你不同的Git账号签名。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">添加头像</h3><p>跟添加UID差不多， 在gpg交互 界面 输入 <code>addphoto </code>就可以， 想要查看的话 输入<code>showphoto</code>。</p><h3 id="h-pgpgit-commit" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">使用PGP为git commit 签名</h3><p>只要你PGP的uid包含 git config 中的邮箱， 使用</p><p><code>git commit -S -m your commit message</code></p><p>即可签名。</p><h3 id="h-pgp-ssh" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">使用PGP 进行SSH</h3><h4 id="h-a" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">生成 认证（A）用子密钥</h4><pre data-type="codeBlock" text="gpg --expert --edit-key {keyid/uid}                                   ## 使用专家模式, 不然没有认证的选项


gpg&gt; addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
Your selection? 8                                                   ## 选8, RSA, 自定义权限

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt                               ## 这里显示默认有Sign和Encrypt两种权限

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S                                                   ## 关闭Sign

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? E                                                   ## 关闭Encrypt

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions:

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? A                                                   ## 开启Authenticate

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q                                                    ## 退出
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      &lt;n&gt;  = key expires in n days
      &lt;n&gt;w = key expires in n weeks
      &lt;n&gt;m = key expires in n months
      &lt;n&gt;y = key expires in n years
Key is valid for? (0) 1y                                             ## 有效期
Key expires at Tue Jan  7 11:33:54 2020 CST
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  rsa2048/7DEFA5351BCE3C55
     created: 2019-01-07  expires: 2021-01-06  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa2048/2FCE923F8ECB63F6
     created: 2019-01-07  expires: 2021-01-06  usage: E
ssb  rsa4096/19D32A8839DCAA1F
     created: 2019-01-07  expires: 2020-01-07  usage: A
[ultimate] (1). hhhhh &lt;h@mail.com&gt;

gpg&gt; save                                                            ## 保存
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>expert <span class="hljs-operator">-</span><span class="hljs-operator">-</span>edit<span class="hljs-operator">-</span>key {keyid<span class="hljs-operator">/</span>uid}                                   ## 使用专家模式, 不然没有认证的选项


gpg<span class="hljs-operator">></span> addkey
Please select what kind of key you want:
   (<span class="hljs-number">3</span>) DSA (sign only)
   (<span class="hljs-number">4</span>) RSA (sign only)
   (<span class="hljs-number">5</span>) Elgamal (encrypt only)
   (<span class="hljs-number">6</span>) RSA (encrypt only)
   (<span class="hljs-number">7</span>) DSA (set your own capabilities)
   (<span class="hljs-number">8</span>) RSA (set your own capabilities)
  (<span class="hljs-number">10</span>) ECC (sign only)
  (<span class="hljs-number">11</span>) ECC (set your own capabilities)
  (<span class="hljs-number">12</span>) ECC (encrypt only)
  (<span class="hljs-number">13</span>) Existing key
Your selection? <span class="hljs-number">8</span>                                                   ## 选<span class="hljs-number">8</span>, RSA, 自定义权限

Possible actions <span class="hljs-keyword">for</span> a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt                               ## 这里显示默认有Sign和Encrypt两种权限

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S                                                   ## 关闭Sign

Possible actions <span class="hljs-keyword">for</span> a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? E                                                   ## 关闭Encrypt

Possible actions <span class="hljs-keyword">for</span> a RSA key: Sign Encrypt Authenticate
Current allowed actions:

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? A                                                   ## 开启Authenticate

Possible actions <span class="hljs-keyword">for</span> a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q                                                    ## 退出
RSA keys may be between <span class="hljs-number">1024</span> and <span class="hljs-number">4096</span> bits long.
What keysize do you want? (<span class="hljs-number">2048</span>) <span class="hljs-number">4096</span>
Requested keysize <span class="hljs-keyword">is</span> <span class="hljs-number">4096</span> bits
Please specify how long the key should be valid.
         0 <span class="hljs-operator">=</span> key does not expire
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>  <span class="hljs-operator">=</span> key expires in n <span class="hljs-literal">days</span>
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>w <span class="hljs-operator">=</span> key expires in n <span class="hljs-literal">weeks</span>
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>m <span class="hljs-operator">=</span> key expires in n months
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>y <span class="hljs-operator">=</span> key expires in n <span class="hljs-literal">years</span>
Key <span class="hljs-keyword">is</span> valid <span class="hljs-keyword">for</span>? (<span class="hljs-number">0</span>) 1y                                             ## 有效期
Key expires at Tue Jan  <span class="hljs-number">7</span> <span class="hljs-number">11</span>:<span class="hljs-number">33</span>:<span class="hljs-number">54</span> <span class="hljs-number">2020</span> CST
Is <span class="hljs-built_in">this</span> correct? (y<span class="hljs-operator">/</span>N) y
Really create? (y<span class="hljs-operator">/</span>N) y
We need to generate a lot of random <span class="hljs-built_in">bytes</span>. It <span class="hljs-keyword">is</span> a good idea to perform
some other action (<span class="hljs-keyword">type</span> on the keyboard, move the mouse, utilize the
disks) during the prime generation; <span class="hljs-built_in">this</span> gives the random number
generator a better chance to gain enough entropy.

sec  rsa2048<span class="hljs-operator">/</span>7DEFA5351BCE3C55
     created: <span class="hljs-number">2019</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07  expires: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>06  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa2048<span class="hljs-operator">/</span>2FCE923F8ECB63F6
     created: <span class="hljs-number">2019</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07  expires: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>06  usage: E
ssb  rsa4096<span class="hljs-operator">/</span>19D32A8839DCAA1F
     created: <span class="hljs-number">2019</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07  expires: <span class="hljs-number">2020</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07  usage: A
[ultimate] (<span class="hljs-number">1</span>). hhhhh <span class="hljs-operator">&#x3C;</span>h@mail.com>

gpg<span class="hljs-operator">></span> save                                                            ## 保存
</code></pre><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">配置文件</h4><p>编辑<code>bashrc</code> 文件， 将默认ssh 的agent替换为 gpg-agnet</p><pre data-type="codeBlock" text="#  ~/.bashrc

export GPG_TTY=$(tty)
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
echo UPDATESTARTUPTTY | gpg-connect-agent 1&gt; /dev/null
"><code>#  <span class="hljs-operator">~</span><span class="hljs-operator">/</span>.bashrc

export GPG_TTY<span class="hljs-operator">=</span>$(tty)
export SSH_AUTH_SOCK<span class="hljs-operator">=</span>$(gpgconf <span class="hljs-operator">-</span><span class="hljs-operator">-</span>list<span class="hljs-operator">-</span>dirs agent<span class="hljs-operator">-</span>ssh<span class="hljs-operator">-</span>socket)
echo UPDATESTARTUPTTY <span class="hljs-operator">|</span> gpg<span class="hljs-operator">-</span>connect<span class="hljs-operator">-</span>agent <span class="hljs-number">1</span><span class="hljs-operator">></span> <span class="hljs-operator">/</span>dev<span class="hljs-operator">/</span>null
</code></pre><p>编辑<code>~/.gnupg/gpg-agent.conf</code>文件,增加：</p><pre data-type="codeBlock" text="#  ~/.gnupg/gpg-agent.conf

enable-ssh-support
"><code>#  <span class="hljs-operator">~</span><span class="hljs-operator">/</span>.gnupg/gpg<span class="hljs-operator">-</span>agent.conf

enable<span class="hljs-operator">-</span>ssh<span class="hljs-operator">-</span>support
</code></pre><p>接着：</p><pre data-type="codeBlock" text="❯ gpg -k --with-keygrip    
/Users/root/.gnupg/pubring.kbx
-----------------------------
pub   rsa2048 2019-01-07 [SC] [expires: 2021-01-06]
      8A9FC025A44AA4824C1F4AE27DEFA5351BCE3C55
      Keygrip = BEFCCDFE36CC5442B888B8459265C68B60A4ABD2
uid           [ultimate] hhhhh &lt;h@mail.com&gt;
sub   rsa2048/0xF681DAEBBAB82124 2019-01-07 [E] [expires: 2021-01-06]
      Keygrip = 422922ACFD099E79863D93B93333528F225C90FC
sub   rsa2048/0x501DEDC36BD409C8 2019-01-07 [A] [expires: 2020-01-07]
      Keygrip = 999A87A51CFE82DAA494BEB42F585051307F9E33
"><code>❯ gpg <span class="hljs-operator">-</span>k <span class="hljs-operator">-</span><span class="hljs-operator">-</span>with<span class="hljs-operator">-</span>keygrip    
<span class="hljs-operator">/</span>Users<span class="hljs-operator">/</span>root<span class="hljs-operator">/</span>.gnupg/pubring.kbx
<span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span>
pub   rsa2048 <span class="hljs-number">2019</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07 [SC] [expires: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>06]
      8A9FC025A44AA4824C1F4AE27DEFA5351BCE3C55
      Keygrip <span class="hljs-operator">=</span> BEFCCDFE36CC5442B888B8459265C68B60A4ABD2
uid           [ultimate] hhhhh <span class="hljs-operator">&#x3C;</span>h@mail.com>
sub   rsa2048<span class="hljs-operator">/</span><span class="hljs-number">0xF681DAEBBAB82124</span> <span class="hljs-number">2019</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07 [E] [expires: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>06]
      Keygrip <span class="hljs-operator">=</span> 422922ACFD099E79863D93B93333528F225C90FC
sub   rsa2048<span class="hljs-operator">/</span><span class="hljs-number">0x501DEDC36BD409C8</span> <span class="hljs-number">2019</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07 [A] [expires: <span class="hljs-number">2020</span><span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>07]
      Keygrip <span class="hljs-operator">=</span> 999A87A51CFE82DAA494BEB42F585051307F9E33
</code></pre><p>选择你新加的带有[A]标志的那个新的子密钥的 keygrip , 即<code>999A87A51CFE82DAA494BEB42F585051307F9E33</code></p><p>加入到<code>~/.gnupg/sshcontrol</code>文件， 运行<code>ssh-add -l</code>, 查看是否已经加入。</p><p>然后</p><pre data-type="codeBlock" text="gpg --export-ssh-key   {keyid}! 
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>export<span class="hljs-operator">-</span>ssh<span class="hljs-operator">-</span>key   {keyid}<span class="hljs-operator">!</span> 
</code></pre><p>注意，这里不能用 uid ,不然会提示:</p><pre data-type="codeBlock" text="gpg: key &quot;uid&quot; not found: Unusable public key
gpg: export as ssh key failed: Unusable public key
"><code><span class="hljs-symbol">gpg:</span> <span class="hljs-keyword">key</span> <span class="hljs-string">"uid"</span> <span class="hljs-built_in">not</span> found: Unusable <span class="hljs-keyword">public</span> <span class="hljs-keyword">key</span>
<span class="hljs-symbol">gpg:</span> export <span class="hljs-keyword">as</span> ssh <span class="hljs-keyword">key</span> failed: Unusable <span class="hljs-keyword">public</span> <span class="hljs-keyword">key</span>
</code></pre><p>这里只能填子密钥的 key id,这个例子里就是 <code>0x501DEDC36BD409C8</code>。</p><p>输出的 ssh public key 放到你的服务器上的<code>~/.ssh/authorized_keys</code>中， 重启shell, 就可以连接了。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">未完待续</h2><hr>]]></content:encoded>
            <author>ulyc@newsletter.paragraph.com (ulyc)</author>
        </item>
        <item>
            <title><![CDATA[2021年，用更现代的方法使用PGP（上）]]></title>
            <link>https://paragraph.com/@ulyc/2021-pgp</link>
            <guid>BCGLgER6s096xTk3nJAm</guid>
            <pubDate>Tue, 30 Nov 2021 00:40:39 GMT</pubDate>
            <description><![CDATA[世界上有两种密码:一种是防止你的小妹妹偷看你的文件;另一种是防止当局阅读你的文件. ​ —— Bruce Schneier《应用密码学》一、PGP简介是什么？PGP 全称是 Pretty Good Privacy，是一个被设计用来加密信息，保护隐私的软件。现在提到“PGP”， 基本上是说 OpenPGP 标准。能干嘛？能用来加密和签名信息 并让你显得很Geek记录片《第四公民》中 Edward Snowden 就是使用 PGP 与女记者 Laura Poitras 之间收发邮件的，以下来自电影截图：image-20210113194002027image-20210113194014209PGP能保证 一条信息是你相信的人发的，除了你俩之外别人无法解密， 而且这条消息在传送时中间没有经过任何哪怕是一个标点一个字节的修改。能用来让你的Git Commit Log更加好看 验证Git Commiter身份1609409350928Github判定提交者只是依靠Git 客户端设置的user.name 和 user.email 来判定身份，而不会去验证真实性，也就是说你可以在你的仓库提交...]]></description>
            <content:encoded><![CDATA[<blockquote><p>世界上有两种密码:一种是防止你的小妹妹偷看你的文件;另一种是防止当局阅读你的文件.</p><p>​ —— Bruce Schneier《应用密码学》</p></blockquote><h2 id="h-pgp" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">一、PGP简介</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">是什么？</h3><p>PGP 全称是 Pretty Good Privacy，是一个被设计用来加密信息，保护隐私的<strong>软件</strong>。现在提到“PGP”， 基本上是说 OpenPGP 标准。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">能干嘛？</h3><h4 id="h-geek" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">能用来加密和签名信息 <s>并让你显得很Geek</s></h4><p>记录片《<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.imdb.com/title/tt4044364/">第四公民</a>》中 Edward Snowden 就是使用 PGP 与女记者 Laura Poitras 之间收发邮件的，以下来自电影截图：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/e5d00b6e3f2994cd353ad392ff14d906aeb9ba114bff11aadb80a72f10f1619f.png" alt="image-20210113194002027" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">image-20210113194002027</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fae071d4bc7e232679345e371c05b519cc10c24d2a91b5000f7c54a8b4922c9e.png" alt="image-20210113194014209" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">image-20210113194014209</figcaption></figure><p>PGP能保证 一条信息是你相信的人发的，除了你俩之外别人无法解密， 而且这条消息在传送时中间没有经过任何哪怕是一个标点一个字节的修改。</p><h4 id="h-git-commit-log-git-commiter" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">能用来<s>让你的Git Commit Log更加好看</s> 验证Git Commiter身份</h4><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3467e594e81cf1c9e08479dacc68e9e3a1ef8a2616d8b1fd130781c620042865.png" alt="1609409350928" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1609409350928</figcaption></figure><p>Github判定提交者只是依靠Git 客户端设置的user.name 和 user.email 来判定身份，而不会去验证真实性，也就是说你可以在你的仓库提交记录中伪造任何人的提交记录。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f87d65dcdc1350bcffa477e00dcc5bd558060dfa555380eeccf28cb00539c9e5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>具体危害可参见<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.spencerwoo.com/2020/08/wait-this-is-not-my-commit/">震惊！竟然有人在 GitHub 上冒充我的身份！</a></p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">能用来<s>放在博客简介里作为身份的象征</s> 增加联系你的安全方式</h4><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5f02f0010df9163721fa41fba3e64752872cc42b49cde4655ee07d81acf08c44.png" alt="1609410812279" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1609410812279</figcaption></figure><h4 id="h-ssh" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">用来代替SSH</h4><p>涌有了自己pgp key之后，就可以用 gpg-agent 来代替 OpenSSH Agent来进行 SSH操作了。不过替换了之后并不会增加SSH的安全性，额， 折腾精神不死嘛。</p><p>硬要说好处的话，大概就可以更方便地使用Yubikey(一种硬件加密智能卡)来SSH。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">用来…</h4><p>如果有其他好玩的用法，欢迎评论或邮件告诉我。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">为什么安全？</h3><p>PGP目前支持的算法</p><ul><li><p>非对称算法: RSA, ELG, DSA, ECDH, ECDSA, EDDSA</p></li><li><p>对称算法: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256</p></li><li><p>哈希算法: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224</p></li><li><p>压缩算法: Uncompressed, ZIP, ZLIB, BZIP2</p></li></ul><p>除非量子计算机落地，目前来说2048位的RSA加密是不可破解的。</p><h3 id="h-pgpopenpgpgnupg-gpg" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">PGP、OpenPGP、GnuPG 和 gpg</h3><p>我们需要知道PGP、OpenPGP、GnuPG 和 gpg 之间的不同：</p><ul><li><p>PGP （“Pretty Good Privacy”） 是最初商业软件的名字</p></li><li><p>OpenPGP 是与最初 PGP 工具兼容的 IETF 标准</p></li><li><p>GnuPG （“Gnu Privacy Guard”）是实现了 OpenPGP 标准的自由软件</p></li><li><p>GnuPG 的命令行工具称为 “gpg”</p></li></ul><p>OpenPGP 是在 PGP 基础上定义的开放标准，使得 PGP 技术可以由任何公司和个人实现，而不需要缴纳许可费用。<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2021/01/13/2021%E5%B9%B4-%E7%94%A8%E6%9B%B4%E7%8E%B0%E4%BB%A3%E7%9A%84%E6%96%B9%E6%B3%95%E4%BD%BF%E7%94%A8PGP-%E4%B8%8A/http%3A//www.ietf.org/rfc/rfc4880.txt">标准草案</a>指出 OpenPGP 提供的是数据完整性服务，赋予用户查看、检验、生成和写入加密信息、秘钥和签名的能力。 OpenPGP 通过加密、数字签名、压缩和 Radix-64 转换来实现这些功能。</p><p>GnuPG 是 OpenPGP 协议的一种完备的实现，除了按照 OpenPGP 协议提供数据加解密和签名服务之外，它还提供了完整的秘钥管理功能，并实现了协议中许多可选的加密或压缩算法。</p><p>今天，“PGP”这个词几乎被普遍用来表示开放的 OpenPGP 标准，而不是最初的商业软件，因此“PGP”和“OpenPGP”是可以互换的。</p><p>“GnuPG”和“gpg”这两个词应该仅在提及工具时使用，而不用于它们产生的输出或它们实现的 OpenPGP 功能。举例：</p><ul><li><p>PGP（而非 GnuPG 或 GPG）密钥</p></li><li><p>PGP（而非 GnuPG 或 GPG）签名</p></li><li><p>PGP（而非 GnuPG 或 GPG）公钥服务器</p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">历史</h3><p>以下来自wiki:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E8%8F%B2%E5%88%A9%E6%99%AE%C2%B7%E9%BD%8A%E9%BB%98%E6%9B%BC">菲利普·齐默曼</a>（Philip R. Zimmermann）在1991年创造了第一个版本的PGP，其名称“Pretty Good Privacy”的灵感来自于一个名为“Ralph’s Pretty Good Grocery”的杂货店——电台主播<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/w/index.php?title=Garrison_Keillor&amp;action=edit&amp;redlink=1">Garrison Keillor</a>虚构出来的一个名为<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/w/index.php?title=Lake_Wobegon&amp;action=edit&amp;redlink=1">Lake Wobegon</a>的城市的一个杂货店。</p><p>软件第一个版本包含一个齐默曼自己设计的<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E5%AF%B9%E7%A7%B0%E5%AF%86%E9%92%A5%E7%AE%97%E6%B3%95">对称密钥算法</a>，与<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E5%91%A8%E5%85%AD%E5%A4%9C%E7%8F%BE%E5%A0%B4">周六夜现场</a>的一个小品<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/w/index.php?title=BassOmatic&amp;action=edit&amp;redlink=1">BassOmatic</a>同名。作为一个老牌的<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/w/index.php?title=%E5%8F%8D%E6%A0%B8%E8%83%BD%E6%B4%BB%E8%B7%83%E5%88%86%E5%AD%90&amp;action=edit&amp;redlink=1">反核能活跃分子</a>，齐默曼为了让所有有相似倾向的人们可以安全的使用BBS并且安全存储消息和文件而创造了PGP加密。在非商业用途上是不需要授权的，无须任何费用，并且在所有的发行中附带了完整的<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E6%BA%90%E4%BB%A3%E7%A0%81">源代码</a>。</p><p>在2001年6月5号发表的一篇标题为”PGP 10周年” [<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/PGP#cite_note-2">2]</a>的文章中，齐默曼描述了他最初开发PGP时的情景：</p><blockquote><p>1991年的某天，我把PGP的第一版发给我几个朋友，以便上传到互联网。我最先发给Allan Hoeltje，他把这个程序发到了Peacenet，一个针对草根政治组织–特别是“和平运动”–的ISP。当时全球政治活跃分子都能访问到Peacenet。然后我又把它上传给了Kelly Goen，他接着就把源码转发到了一个专门分发源代码的Usenet新闻组。基于我的请求，他把该Usenet权限改为了“仅限美国”。Kelly还把PGP传到了（美国）国内很多BBS上面。我记不太清刚开始在网上贴是6月5号还是6号。 说出来吓人，1991年的时候，我对Usenet新闻组确是知之甚少。我并不知道那个“仅限美国”的标签只是个“建议”作用，基本上对贴子的传播（范围）毫无影响。当时，我以为这个标签会控制这个帖子的传播范围。当时我不知道如何在新闻组发贴，甚至不明白新闻组究竟是什么。</p></blockquote><p>PGP在<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E4%BA%92%E8%81%94%E7%BD%91">互联网</a>上传播开来，并且在这个世界上获得了非常多的拥护者。PGP用户和支持者也包括在极权主义国家持不同政见的人们（一些给齐默曼的感人信件被发表了，其中一些在美国国会之前被包括到证据中）。在世界其它地方的<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/w/index.php?title=%E5%85%AC%E6%B0%91%E8%87%AA%E7%94%B1%E6%84%8F%E5%BF%97%E4%B8%BB%E4%B9%89&amp;action=edit&amp;redlink=1">公民自由意志主义</a>支持者（参考齐默曼在各个听政会上发表的证据），以及“自由通讯”激进主义分子，他们称他们自己为<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/w/index.php?title=%E5%8A%A0%E5%AF%86%E7%88%B1%E5%A5%BD%E8%80%85&amp;action=edit&amp;redlink=1">加密爱好者</a>，进行宣传和分发。</p><h2 id="h-gpg" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">二、gpg快速开始</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">准备工作</h3><p>建议你先参照后面教程，在随便一台机器上练习。 等熟练操作之后，再阅读 安全使用 生成你真正主要使用的PGP密钥对 ：</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">安装</h3><h4 id="h-mac" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">🍎Mac:</h4><h4 id="h-linux" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">🐧Linux:</h4><p>各发行版一般都会默认安装GnuPG。</p><h4 id="h-windows" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">🏁Windows:</h4><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.gnupg.org/download/">下载地址</a></p><h4 id="h-openbsd" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">🌐OpenBSD:</h4><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">生成</h3><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">生成主密钥</h4><pre data-type="codeBlock" text="# step 0 
gpg --full-gen-key
# 这里不推荐使用的 `gpg --gen-key`


# step 1
gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection?
#  默认就可以


# step 2
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)

# 此处输入你希望的密钥长度， RSA的不应低于2048 bits，当然输入的数字越大越安全，相应的，加解密的速度也会更慢

# step 3
Please specify how long the key should be valid.
         0 = key does not expire
      &lt;n&gt;  = key expires in n days
      &lt;n&gt;w = key expires in n weeks
      &lt;n&gt;m = key expires in n months
      &lt;n&gt;y = key expires in n years
Key is valid for? (0)  2y

# 默认可以选0 ，即永不过期， 这里我选了2y，  因为到期之前随时可以更改你的过期时间，以确保你对此密钥仍拥有控制权

# step 4
Key expires at Wed 11 Jan 2023 05:50:53 PM CST
Is this correct? (y/N) y

#确定

# step 5

GnuPG needs to construct a user ID to identify your key.

Real name:  linus   # 这里名字可以是网名，可以是任意名字，如果你注重隐私就不要输入自己真名了 
Email address: linus@outlook.com  
Comment:     # 备注可以留空

# 注意了： 这里的邮箱， 如果你不打算使用PGP为你的Git记录认证， 这里其实是可以随便输入的，不需要是你的邮箱， 甚至不需要是一个真实存在的邮箱，只要接受你信息的人知道就行。隐私泄漏问题很严重，你一旦设置了，并且发布到公钥服务器，就永远删不掉了 😅


# step 6
You selected this USER-ID:
    &quot;linus &lt;linust@outlook.com&gt;&quot;

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

# 确认无误后输入 o

# step 7
┌──────────────────────────────────────────────────────┐
│ Please enter the passphrase to                       											  │
│ protect your new key                                                           │ 
│                                                      │
│ Passphrase: ________________________________________ 														 │
│                                                      │
│       &lt;OK&gt;                              &lt;Cancel&gt;     │
└──────────────────────────────────────────────────────┘

# 输入一个复杂的密码 并确认

# step 8
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

# 随机移动你的鼠标，越随机你的密钥越安全

# step 9 大功告成
                 
gpg: key 99F583599B7E31F1 marked as ultimately trusted
gpg: revocation certificate stored as &apos;/root/.gnupg/openpgp-revocs.d/705358AB85366CAB05C0220F99F583599B7E31F1.rev&apos;
public and secret key created and signed.

pub   rsa3072 2021-01-11 [SC]
      705358AB85366CAB05C0220F99F583599B7E31F1			 # 你的 key id
uid                      linus &lt;linus@outlook.com&gt;
sub   rsa3072 2021-01-11 [E] 		 # 这个是自动生成的用于加密的子密钥，E代表Encrypt 加密
"><code># step <span class="hljs-number">0</span> 
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>full<span class="hljs-operator">-</span>gen<span class="hljs-operator">-</span>key
# 这里不推荐使用的 `gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>gen<span class="hljs-operator">-</span>key`


# step <span class="hljs-number">1</span>
gpg (GnuPG) <span class="hljs-number">2.2</span><span class="hljs-number">.20</span>; Copyright (C) <span class="hljs-number">2020</span> Free Software Foundation, Inc.
This <span class="hljs-keyword">is</span> free software: you are free to change and redistribute it.
There <span class="hljs-keyword">is</span> NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (<span class="hljs-number">1</span>) RSA and RSA (default)
   (<span class="hljs-number">2</span>) DSA and Elgamal
   (<span class="hljs-number">3</span>) DSA (sign only)
   (<span class="hljs-number">4</span>) RSA (sign only)
  (<span class="hljs-number">14</span>) Existing key <span class="hljs-keyword">from</span> card
Your selection?
#  默认就可以


# step <span class="hljs-number">2</span>
RSA keys may be between <span class="hljs-number">1024</span> and <span class="hljs-number">4096</span> bits long.
What keysize do you want? (<span class="hljs-number">3072</span>)

# 此处输入你希望的密钥长度， RSA的不应低于<span class="hljs-number">2048</span> bits，当然输入的数字越大越安全，相应的，加解密的速度也会更慢

# step <span class="hljs-number">3</span>
Please specify how long the key should be valid.
         0 <span class="hljs-operator">=</span> key does not expire
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>  <span class="hljs-operator">=</span> key expires in n <span class="hljs-literal">days</span>
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>w <span class="hljs-operator">=</span> key expires in n <span class="hljs-literal">weeks</span>
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>m <span class="hljs-operator">=</span> key expires in n months
      <span class="hljs-operator">&#x3C;</span>n<span class="hljs-operator">></span>y <span class="hljs-operator">=</span> key expires in n <span class="hljs-literal">years</span>
Key <span class="hljs-keyword">is</span> valid <span class="hljs-keyword">for</span>? (<span class="hljs-number">0</span>)  2y

# 默认可以选<span class="hljs-number">0</span> ，即永不过期， 这里我选了2y，  因为到期之前随时可以更改你的过期时间，以确保你对此密钥仍拥有控制权

# step <span class="hljs-number">4</span>
Key expires at Wed <span class="hljs-number">11</span> Jan <span class="hljs-number">2023</span> 05:<span class="hljs-number">50</span>:<span class="hljs-number">53</span> PM CST
Is <span class="hljs-built_in">this</span> correct? (y<span class="hljs-operator">/</span>N) y

#确定

# step <span class="hljs-number">5</span>

GnuPG needs to construct a user ID to identify your key.

Real name:  linus   # 这里名字可以是网名，可以是任意名字，如果你注重隐私就不要输入自己真名了 
Email <span class="hljs-keyword">address</span>: linus@outlook.com  
Comment:     # 备注可以留空

# 注意了： 这里的邮箱， 如果你不打算使用PGP为你的Git记录认证， 这里其实是可以随便输入的，不需要是你的邮箱， 甚至不需要是一个真实存在的邮箱，只要接受你信息的人知道就行。隐私泄漏问题很严重，你一旦设置了，并且发布到公钥服务器，就永远删不掉了 😅


# step <span class="hljs-number">6</span>
You selected <span class="hljs-built_in">this</span> USER<span class="hljs-operator">-</span>ID:
    <span class="hljs-string">"linus &#x3C;linust@outlook.com>"</span>

Change (N)ame, (C)omment, (E)mail or (O)kay<span class="hljs-operator">/</span>(Q)uit? o

# 确认无误后输入 o

# step <span class="hljs-number">7</span>
┌──────────────────────────────────────────────────────┐
│ Please enter the passphrase to                       											  │
│ protect your <span class="hljs-keyword">new</span> key                                                           │ 
│                                                      │
│ Passphrase: ________________________________________ 														 │
│                                                      │
│       <span class="hljs-operator">&#x3C;</span>OK<span class="hljs-operator">></span>                              <span class="hljs-operator">&#x3C;</span>Cancel<span class="hljs-operator">></span>     │
└──────────────────────────────────────────────────────┘

# 输入一个复杂的密码 并确认

# step <span class="hljs-number">8</span>
We need to generate a lot of random <span class="hljs-built_in">bytes</span>. It <span class="hljs-keyword">is</span> a good idea to perform
some other action (<span class="hljs-keyword">type</span> on the keyboard, move the mouse, utilize the
disks) during the prime generation; <span class="hljs-built_in">this</span> gives the random number
generator a better chance to gain enough entropy.

# 随机移动你的鼠标，越随机你的密钥越安全

# step <span class="hljs-number">9</span> 大功告成
                 
gpg: key 99F583599B7E31F1 marked <span class="hljs-keyword">as</span> ultimately trusted
gpg: revocation certificate stored <span class="hljs-keyword">as</span> <span class="hljs-string">'/root/.gnupg/openpgp-revocs.d/705358AB85366CAB05C0220F99F583599B7E31F1.rev'</span>
<span class="hljs-keyword">public</span> and secret key created and signed.

pub   rsa3072 <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [SC]
      705358AB85366CAB05C0220F99F583599B7E31F1			 # 你的 key id
uid                      linus <span class="hljs-operator">&#x3C;</span>linus@outlook.com>
sub   rsa3072 <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [E] 		 # 这个是自动生成的用于加密的子密钥，E代表Encrypt 加密
</code></pre><p>以下是常见缩写释义：</p><pre data-type="codeBlock" text="A    =&gt;    Authentication
C    =&gt;    Certify
E    =&gt;    Encrypt
S    =&gt;    Sign
?    =&gt;    Unknown capability
sec  =&gt;    Secret Key
ssb  =&gt;    Secret SuBkey
pub  =&gt;    Public Key
sub  =&gt;    Public Subkey
"><code>A    <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Authentication
C    <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Certify
E    <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Encrypt
S    <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Sign
?    <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Unknown capability
sec  <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Secret Key
ssb  <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Secret SuBkey
pub  <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Public Key
sub  <span class="hljs-operator">=</span><span class="hljs-operator">></span>    Public Subkey
</code></pre><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">生成子密钥</h4><p>你日常使用应该使用子密钥，主密钥除了签发新的子密钥不要使用。</p><p>建议为不同环境，不同用途都单独生成子密钥，互不干扰。</p><pre data-type="codeBlock" text="# step 0
gpg --edit-key linus # 或者key id  

# step 1  进入gpg交互界面	
gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa3072/99F583599B7E31F1
     created: 2021-01-11  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE9C71CFED44076
     created: 2021-01-11  expires: never       usage: E
[ultimate] (1). linus &lt;linus@outlook.com&gt;C

# step 2  
gpg&gt;   addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
  (14) Existing key from card
Your selection? 4   
# 根据你的用途选择， 这里生成一个只用于签名的子密钥（sign only）

#  后面的选择和主密钥生成的大同小异，按提示操作即可

# 生成完毕后
sec  rsa3072/99F583599B7E31F1
     created: 2021-01-11  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE9C71CFED44076
     created: 2021-01-11  expires: never       usage: E
ssb  rsa3072/FDB960B857D397F6
     created: 2021-01-11  expires: never       usage: S
[ultimate] (1). linus &lt;linus@outlook.com&gt;

#  last step
gpg&gt;  save  #  记得save， 直接退出的话什么也没有
"><code># step <span class="hljs-number">0</span>
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>edit<span class="hljs-operator">-</span>key linus # 或者key id  

# step <span class="hljs-number">1</span>  进入gpg交互界面	
gpg (GnuPG) <span class="hljs-number">2.2</span><span class="hljs-number">.20</span>; Copyright (C) <span class="hljs-number">2020</span> Free Software Foundation, Inc.
This <span class="hljs-keyword">is</span> free software: you are free to change and redistribute it.
There <span class="hljs-keyword">is</span> NO WARRANTY, to the extent permitted by law.

Secret key <span class="hljs-keyword">is</span> available.

sec  rsa3072<span class="hljs-operator">/</span>99F583599B7E31F1
     created: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span>  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072<span class="hljs-operator">/</span>6FE9C71CFED44076
     created: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span>  expires: never       usage: E
[ultimate] (<span class="hljs-number">1</span>). linus <span class="hljs-operator">&#x3C;</span>linus@outlook.com>C

# step <span class="hljs-number">2</span>  
gpg<span class="hljs-operator">></span>   addkey
Please select what kind of key you want:
   (<span class="hljs-number">3</span>) DSA (sign only)
   (<span class="hljs-number">4</span>) RSA (sign only)
   (<span class="hljs-number">5</span>) Elgamal (encrypt only)
   (<span class="hljs-number">6</span>) RSA (encrypt only)
  (<span class="hljs-number">14</span>) Existing key <span class="hljs-keyword">from</span> card
Your selection? <span class="hljs-number">4</span>   
# 根据你的用途选择， 这里生成一个只用于签名的子密钥（sign only）

#  后面的选择和主密钥生成的大同小异，按提示操作即可

# 生成完毕后
sec  rsa3072<span class="hljs-operator">/</span>99F583599B7E31F1
     created: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span>  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072<span class="hljs-operator">/</span>6FE9C71CFED44076
     created: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span>  expires: never       usage: E
ssb  rsa3072<span class="hljs-operator">/</span>FDB960B857D397F6
     created: <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span>  expires: never       usage: S
[ultimate] (<span class="hljs-number">1</span>). linus <span class="hljs-operator">&#x3C;</span>linus@outlook.com>

#  last step
gpg<span class="hljs-operator">></span>  save  #  记得save， 直接退出的话什么也没有
</code></pre><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">生成撤销证书</h4><p>假如你忘了主密钥的密码，或者丢失了对主密钥的控制权（丢失，被夺取），如果没有撤销凭证的话， 除了一个个通知你的朋友们没有任何办法 证明你不再使用这个密钥，这简直是灾难。</p><pre data-type="codeBlock" text="# step 0
gpg --gen-revoke -ao   revoke.pgp   linus # uid 或者key id

# step 1
sec  rsa3072/99F583599B7E31F1 2021-01-11 linus &lt;linus@outlook.com&gt;

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here) 3

# 按提示走完流程就可以
"><code># step <span class="hljs-number">0</span>
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>gen<span class="hljs-operator">-</span>revoke <span class="hljs-operator">-</span>ao   revoke.pgp   linus # uid 或者key id

# step <span class="hljs-number">1</span>
sec  rsa3072<span class="hljs-operator">/</span>99F583599B7E31F1 <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> linus <span class="hljs-operator">&#x3C;</span>linus@outlook.com>

Create a revocation certificate <span class="hljs-keyword">for</span> <span class="hljs-built_in">this</span> key? (y<span class="hljs-operator">/</span>N) y
Please select the reason <span class="hljs-keyword">for</span> the revocation:
  <span class="hljs-number">0</span> <span class="hljs-operator">=</span> No reason specified
  <span class="hljs-number">1</span> <span class="hljs-operator">=</span> Key has been compromised
  <span class="hljs-number">2</span> <span class="hljs-operator">=</span> Key <span class="hljs-keyword">is</span> superseded
  <span class="hljs-number">3</span> <span class="hljs-operator">=</span> Key <span class="hljs-keyword">is</span> no longer used
  Q <span class="hljs-operator">=</span> Cancel
(Probably you want to select <span class="hljs-number">1</span> here) <span class="hljs-number">3</span>

# 按提示走完流程就可以
</code></pre><p>生成的<code>revoke.pgp</code>就是撤销凭证， 有了这个撤销凭证，你可以在没有密码的情况下使一个公钥失效，所以一定要妥善保存，而且最好比主密钥多一份。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">列出密钥</h3><pre data-type="codeBlock" text="# 列出所有公钥、子公钥
gpg --list-keys 
# 列出所有密钥、子密钥
gpg --list-secret-keys 

# 简化命令
gpg -k 
gpg -K  


# 输出 
sec   rsa3072 2021-01-11 [SC]
      705358AB85366CAB05C0220F99F583599B7E31F1
uid           [ultimate] linus &lt;linus@outlook.com&gt;
ssb   rsa3072 2021-01-11 [E]
ssb   rsa3072 2021-01-11 [S]
"><code># 列出所有公钥、子公钥
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>list<span class="hljs-operator">-</span>keys 
# 列出所有密钥、子密钥
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>list<span class="hljs-operator">-</span>secret<span class="hljs-operator">-</span>keys 

# 简化命令
gpg <span class="hljs-operator">-</span>k 
gpg <span class="hljs-operator">-</span>K  


# 输出 
sec   rsa3072 <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [SC]
      705358AB85366CAB05C0220F99F583599B7E31F1
uid           [ultimate] linus <span class="hljs-operator">&#x3C;</span>linus@outlook.com>
ssb   rsa3072 <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [E]
ssb   rsa3072 <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [S]
</code></pre><p>这样并没有列出子密钥的id, 而且没有打印出指纹信息， 是不安全的。所以在你查看密钥时应该</p><ul><li><p>加上 <code>--keyid-format long</code>输出长ID</p></li><li><p>加上 <code>--fingerprint</code> 输出指纹信息</p></li></ul><p>比如</p><pre data-type="codeBlock" text=" gpg --fingerprint -K --keyid-format long
 
 # 输出
sec   rsa3072/0x99F583599B7E31F1 2021-01-11 [SC]		# 长ID
      Key fingerprint = 7053 58AB 8536 6CAB 05C0  220F 99F5 8359 9B7E 31F1 #指纹信息
uid                   [ultimate] linus &lt;linus@outlook.com&gt;
ssb   rsa3072/0x6FE9C71CFED44076 2021-01-11 [E]            # 斜杠后面的就是子密钥ID
ssb   rsa3072/0xFDB960B857D397F6 2021-01-11 [S]
"><code> gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>fingerprint <span class="hljs-operator">-</span>K <span class="hljs-operator">-</span><span class="hljs-operator">-</span>keyid<span class="hljs-operator">-</span>format long
 
 # 输出
sec   rsa3072<span class="hljs-operator">/</span><span class="hljs-number">0x99F583599B7E31F1</span> <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [SC]		# 长ID
      Key fingerprint <span class="hljs-operator">=</span> <span class="hljs-number">7053</span> 58AB <span class="hljs-number">8536</span> 6CAB 05C0  220F 99F5 <span class="hljs-number">8359</span> 9B7E 31F1 #指纹信息
uid                   [ultimate] linus <span class="hljs-operator">&#x3C;</span>linus@outlook.com>
ssb   rsa3072<span class="hljs-operator">/</span><span class="hljs-number">0x6FE9C71CFED44076</span> <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [E]            # 斜杠后面的就是子密钥ID
ssb   rsa3072<span class="hljs-operator">/</span><span class="hljs-number">0xFDB960B857D397F6</span> <span class="hljs-number">2021</span><span class="hljs-operator">-</span>01<span class="hljs-number">-11</span> [S]
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">安全设置</h3><p>每次都打 <code>--keyid-format long</code>和<code>--fingerprint</code> 很烦对不对， 编辑配置gpg文件, <code>vim ~/.gnupg/gpg.conf</code></p><pre data-type="codeBlock" text="# ~/.gnupg/gpg.conf

keyid-format 0xlong
with-fingerprint
"><code># <span class="hljs-operator">~</span><span class="hljs-operator">/</span>.gnupg/gpg.conf

keyid<span class="hljs-operator">-</span>format 0xlong
with<span class="hljs-operator">-</span>fingerprint
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">备份</h3><pre data-type="codeBlock" text="gpg -ao public-key.txt --export linus   # 导出公钥

# 注意这里最后 要带上“!”， 不然会导出全部子密钥， 感谢@Dallas Lu 指正 
gpg  -ao secret-key --export-secret-key 99F583599B7E31F1! 			# 导出主私钥，建议secret-key 替换为你的加密设备备份文件的路径，直接导入到设备中
gpg  -ao sign-subkey --export-secret-subkeys FDB960B857D397F6!   	 #导出有[S]标识、签名用子私钥
gpg  -ao encrypt-subkey --export-secret-subkeys 6FE9C71CFED44076!    #导出有[E]标识、加密用子私钥 ,这里的ID替换为你的子密钥ID


# 别忘了同时将你刚刚生成的撤销凭证也备份起来
"><code>gpg <span class="hljs-operator">-</span>ao <span class="hljs-keyword">public</span><span class="hljs-operator">-</span>key.txt <span class="hljs-operator">-</span><span class="hljs-operator">-</span>export linus   # 导出公钥

# 注意这里最后 要带上“<span class="hljs-operator">!</span>”， 不然会导出全部子密钥， 感谢@Dallas Lu 指正 
gpg  <span class="hljs-operator">-</span>ao secret<span class="hljs-operator">-</span>key <span class="hljs-operator">-</span><span class="hljs-operator">-</span>export<span class="hljs-operator">-</span>secret<span class="hljs-operator">-</span>key 99F583599B7E31F1<span class="hljs-operator">!</span> 			# 导出主私钥，建议secret<span class="hljs-operator">-</span>key 替换为你的加密设备备份文件的路径，直接导入到设备中
gpg  <span class="hljs-operator">-</span>ao sign<span class="hljs-operator">-</span>subkey <span class="hljs-operator">-</span><span class="hljs-operator">-</span>export<span class="hljs-operator">-</span>secret<span class="hljs-operator">-</span>subkeys FDB960B857D397F6<span class="hljs-operator">!</span>   	 #导出有[S]标识、签名用子私钥
gpg  <span class="hljs-operator">-</span>ao encrypt<span class="hljs-operator">-</span>subkey <span class="hljs-operator">-</span><span class="hljs-operator">-</span>export<span class="hljs-operator">-</span>secret<span class="hljs-operator">-</span>subkeys 6FE9C71CFED44076<span class="hljs-operator">!</span>    #导出有[E]标识、加密用子私钥 ,这里的ID替换为你的子密钥ID


# 别忘了同时将你刚刚生成的撤销凭证也备份起来
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">删除</h3><p>备份完后，要将本机的密钥清除干净，首先删除：</p><pre data-type="codeBlock" text="
gpg --delete-secret-keys linus  # 删除私钥，  UID 也可以替换成子密钥ID, 主密钥Key ID
gpg --delete-keys linus		 # 删除公钥

# 如果想全部删除推荐直接删文件夹,即删除 $HOME/.gnupg
"><code>
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-keyword">delete</span><span class="hljs-operator">-</span>secret<span class="hljs-operator">-</span>keys linus  # 删除私钥，  UID 也可以替换成子密钥ID, 主密钥Key ID
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-keyword">delete</span><span class="hljs-operator">-</span>keys linus		 # 删除公钥

# 如果想全部删除推荐直接删文件夹,即删除 $HOME<span class="hljs-operator">/</span>.gnupg
</code></pre><p>由于gpg生成的私钥会在你的磁盘上使用明文储存，所以一个单独的 <code>rm</code> 或者右键删除 并不能彻底删除掉，可以使用 wipe 工具。如果你使用的是 SSD 且没有 启用全盘加密，是没法彻底删除的。</p><p>特别推荐使用 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tails.boum.org/">Tails (boum.org)</a>发行版来生成主要使用的密钥， 系统自带pgp和paper key 等工具, 可以确保全程断网操作, 同时此系统重启会擦除所有内容，还免去了擦除密钥的麻烦。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">导入</h3><pre data-type="codeBlock" text="#从文件导入
gpg --import [密钥文件]   # 刚刚备份的子密钥文件， 或者其他人的公钥

# 暂不推荐从公钥服务器导入，具体用法会在公钥服务器一章介绍
# 这里先推荐 练习导入自己的子密钥


 # 输出
sec#   rsa3072/0x99F583599B7E31F1 2021-01-11 [SC]		 # sec 后面带有 # 号说明主密钥未导入，是安全的
      Key fingerprint = 7053 58AB 8536 6CAB 05C0  220F 99F5 8359 9B7E 31F1 #指纹信息
uid                   [unknown] linus &lt;linus@outlook.com&gt;
ssb #    rsa3072/0x6FE9C71CFED44076 2021-01-11 [E]           # 带有 # 号说明该子密钥已导入
"><code><span class="hljs-comment">#从文件导入</span>
gpg --import <span class="hljs-section">[密钥文件]</span>   <span class="hljs-comment"># 刚刚备份的子密钥文件， 或者其他人的公钥</span>

<span class="hljs-comment"># 暂不推荐从公钥服务器导入，具体用法会在公钥服务器一章介绍</span>
<span class="hljs-comment"># 这里先推荐 练习导入自己的子密钥</span>


 <span class="hljs-comment"># 输出</span>
sec<span class="hljs-comment">#   rsa3072/0x99F583599B7E31F1 2021-01-11 [SC]		 # sec 后面带有 # 号说明主密钥未导入，是安全的</span>
      Key <span class="hljs-attr">fingerprint</span> = <span class="hljs-number">7053</span> <span class="hljs-number">58</span>AB <span class="hljs-number">8536</span> <span class="hljs-number">6</span>CAB <span class="hljs-number">05</span>C0  <span class="hljs-number">220</span>F <span class="hljs-number">99</span>F5 <span class="hljs-number">8359</span> <span class="hljs-number">9</span>B7E <span class="hljs-number">31</span>F1 <span class="hljs-comment">#指纹信息</span>
uid                   <span class="hljs-section">[unknown]</span> linus &#x3C;linus@outlook.com>
ssb <span class="hljs-comment">#    rsa3072/0x6FE9C71CFED44076 2021-01-11 [E]           # 带有 # 号说明该子密钥已导入</span>
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">签名和验证</h3><p>这里只讲 如何签名和验证 他人文件， 为他人公钥签名和验证 放在公钥的发布和交换一章讲解。</p><pre data-type="codeBlock" text="# 第一种方式，生成二进制签名文件

gpg --sign input.txt  # 当然也可以加上--output参数

# 第二种方式，生成ASCII格式签名
gpg --clearsign input.txt

# 第三种，签名和原文本分开（前两种的签名文件中包含了所有原文本，所以体积会比较大）
gpg --armor --detach-sign input.txt  #不加armor生成会二进制



#  验证签名文件
gpg --verify demo.txt.asc demo.txt
"><code># 第一种方式，生成二进制签名文件

gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>sign input.txt  # 当然也可以加上<span class="hljs-operator">-</span><span class="hljs-operator">-</span>output参数

# 第二种方式，生成ASCII格式签名
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>clearsign input.txt

# 第三种，签名和原文本分开（前两种的签名文件中包含了所有原文本，所以体积会比较大）
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>armor <span class="hljs-operator">-</span><span class="hljs-operator">-</span>detach<span class="hljs-operator">-</span>sign input.txt  #不加armor生成会二进制



#  验证签名文件
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>verify demo.txt.asc demo.txt
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">加解密</h3><pre data-type="codeBlock" text="# 加密：

# recipient指定接收者的公钥ID
gpg --recipient {keyid/uid} --output encrypt.txt --encrypt input.txt
# 也可以按喜好加上--armor选项等

# 我更喜欢用 
gpg  -se  -o  encrypt.txt  -r  {keyid/uid}   input.txt  
# s代表签名  e代表加密
# o是 将结果 输出到文件  encrypt.txt
# r后面跟 接收者的 uid或者 key id， 接收者的公钥必须已经导入过
# input.txt 是你要加密的文件


# 解密：
gpg --decrypt encrypt.txt --output decrypt.txt
# 也可以
gpg -d encrypt.txt   # 输出到终端 直接查看
"><code># 加密：

# recipient指定接收者的公钥ID
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>recipient {keyid<span class="hljs-operator">/</span>uid} <span class="hljs-operator">-</span><span class="hljs-operator">-</span>output encrypt.txt <span class="hljs-operator">-</span><span class="hljs-operator">-</span>encrypt input.txt
# 也可以按喜好加上<span class="hljs-operator">-</span><span class="hljs-operator">-</span>armor选项等

# 我更喜欢用 
gpg  <span class="hljs-operator">-</span>se  <span class="hljs-operator">-</span>o  encrypt.txt  <span class="hljs-operator">-</span>r  {keyid<span class="hljs-operator">/</span>uid}   input.txt  
# s代表签名  e代表加密
# o是 将结果 输出到文件  encrypt.txt
# r后面跟 接收者的 uid或者 key id， 接收者的公钥必须已经导入过
# input.txt 是你要加密的文件


# 解密：
gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>decrypt encrypt.txt <span class="hljs-operator">-</span><span class="hljs-operator">-</span>output decrypt.txt
# 也可以
gpg <span class="hljs-operator">-</span>d encrypt.txt   # 输出到终端 直接查看
</code></pre><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">发布 与 交换</h3><p>公钥的交换是所有非对称加密算法的脆弱点，所谓现代的使用方式，主要体现在密钥的交换和发布上面， 之后会单独来探讨。</p><p><strong>阅读并理解本系列之前请不要发布你的公钥到公钥服务器</strong>。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">撤销</h3><p>由于PGP没有提供任何将吊销信息通知其他用户的方式，他不能保证没人会使用撤销了的已经变得不安全的密钥。</p><p>你丢失的私钥仍然可以被攻击者使用，并用来解密那些没有更新你的公钥的人发送的加密消息。 revoke 子密钥并更新公钥后，若有人用老的公钥加密信息，虽然你仍然可以解密，但是攻击者同样可以，这时候是极度不安全的。</p><p>例如：如果A的私人密钥被盗，她将发出一个密钥撤销证书（key revocation certificate），但是由于这个密钥的分发是非正式的且将费大量的时间和口舌，故不能保证密钥环中每一个有A公开密钥的用户都能收到。由于A必须用她的私人密钥签名撤消的证书，所以如果A同时丢失了私人密钥，她就不能撤销密钥。密钥的撤销问题被认为是整个系统最薄弱的环节。</p><p>所以在你将密钥撤销后，请将撤销后的公钥发布到你一贯公布公钥的地方， 并尽可能通知其他人。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">撤销主密钥</h4><pre data-type="codeBlock" text="gpg --import gpg-linus.asc                                               # 在一台新的电脑上导入你的公钥
gpg: key 99F583599B7E31F1: &quot;linus &lt;linus@outlook.com&gt;&quot; not changed
gpg: Total number processed: 1
gpg:              unchanged: 1



gpg --import revoke                                                       # 导入你备份的撤销凭证，直接会导致密钥不可用



gpg: key 99F583599B7E31F1: &quot;linus &lt;linus@outlook.com&gt;&quot; revocation certificate imported
gpg: Total number processed: 1
gpg:    new key revocations: 1
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1  valid:   1  signed:   0  trust: 1-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2021-09-29



gpg -k																	# 查看密钥，已经revoke


pub   rsa3072 2021-01-11 [SC] [revoked: 2021-01-11]
      705358AB85366CAB05C0220F99F583599B7E31F1
uid           [ revoked] linus &lt;linus@outlook.com&gt;
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-keyword">import</span> <span class="hljs-title">gpg</span><span class="hljs-operator">-</span><span class="hljs-title">linus</span>.<span class="hljs-title">asc</span>                                               # 在一台新的电脑上导入你的公钥
<span class="hljs-title">gpg</span>: <span class="hljs-title">key</span> 99<span class="hljs-title">F583599B7E31F1</span>: <span class="hljs-string">"linus &#x3C;linus@outlook.com>"</span> <span class="hljs-title">not</span> <span class="hljs-title">changed</span>
<span class="hljs-title">gpg</span>: <span class="hljs-title">Total</span> <span class="hljs-title">number</span> <span class="hljs-title">processed</span>: 1
<span class="hljs-title">gpg</span>:              <span class="hljs-title">unchanged</span>: 1



<span class="hljs-title">gpg</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">revoke</span>                                                       # 导入你备份的撤销凭证，直接会导致密钥不可用



<span class="hljs-title">gpg</span>: <span class="hljs-title">key</span> 99<span class="hljs-title">F583599B7E31F1</span>: <span class="hljs-string">"linus &#x3C;linus@outlook.com>"</span> <span class="hljs-title">revocation</span> <span class="hljs-title">certificate</span> <span class="hljs-title">imported</span>
<span class="hljs-title">gpg</span>: <span class="hljs-title">Total</span> <span class="hljs-title">number</span> <span class="hljs-title">processed</span>: 1
<span class="hljs-title">gpg</span>:    <span class="hljs-title"><span class="hljs-keyword">new</span></span> <span class="hljs-title">key</span> <span class="hljs-title">revocations</span>: 1
<span class="hljs-title">gpg</span>: <span class="hljs-title">marginals</span> <span class="hljs-title">needed</span>: 3  <span class="hljs-title">completes</span> <span class="hljs-title">needed</span>: 1  <span class="hljs-title">trust</span> <span class="hljs-title">model</span>: <span class="hljs-title">pgp</span>
<span class="hljs-title">gpg</span>: <span class="hljs-title">depth</span>: 0  <span class="hljs-title">valid</span>:   1  <span class="hljs-title">signed</span>:   1  <span class="hljs-title">trust</span>: 0<span class="hljs-operator">-</span>, 0<span class="hljs-title">q</span>, 0<span class="hljs-title">n</span>, 0<span class="hljs-title">m</span>, 0<span class="hljs-title">f</span>, 1<span class="hljs-title">u</span>
<span class="hljs-title">gpg</span>: <span class="hljs-title">depth</span>: 1  <span class="hljs-title">valid</span>:   1  <span class="hljs-title">signed</span>:   0  <span class="hljs-title">trust</span>: 1<span class="hljs-operator">-</span>, 0<span class="hljs-title">q</span>, 0<span class="hljs-title">n</span>, 0<span class="hljs-title">m</span>, 0<span class="hljs-title">f</span>, 0<span class="hljs-title">u</span>
<span class="hljs-title">gpg</span>: <span class="hljs-title">next</span> <span class="hljs-title">trustdb</span> <span class="hljs-title">check</span> <span class="hljs-title">due</span> <span class="hljs-title">at</span> 2021<span class="hljs-operator">-</span>09<span class="hljs-operator">-</span>29



<span class="hljs-title">gpg</span> <span class="hljs-operator">-</span><span class="hljs-title">k</span>																	# 查看密钥，已经<span class="hljs-title">revoke</span>


<span class="hljs-title">pub</span>   <span class="hljs-title">rsa3072</span> 2021<span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>11 [<span class="hljs-title">SC</span>] [<span class="hljs-title">revoked</span>: 2021<span class="hljs-operator">-</span>01<span class="hljs-operator">-</span>11]
      705358<span class="hljs-title">AB85366CAB05C0220F99F583599B7E31F1</span>
<span class="hljs-title">uid</span>           [ <span class="hljs-title">revoked</span>] <span class="hljs-title">linus</span> <span class="hljs-operator">&#x3C;</span><span class="hljs-title">linus</span>@<span class="hljs-title">outlook</span>.<span class="hljs-title">com</span><span class="hljs-operator">></span>
</code></pre><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">撤销子密钥</h4><pre data-type="codeBlock" text="gpg --edit-key linus  
  
gpg &gt;   list  # 列出你所有的子密钥
gpg &gt;   key  {n}  # 选择你要销毁的子密钥的 序号
gpg &gt;   revkey
gpg &gt;   save    # 退出前一定要save, 不然所有更改不会生效
"><code>gpg <span class="hljs-operator">-</span><span class="hljs-operator">-</span>edit<span class="hljs-operator">-</span>key linus  
  
gpg <span class="hljs-operator">></span>   list  # 列出你所有的子密钥
gpg <span class="hljs-operator">></span>   key  {n}  # 选择你要销毁的子密钥的 序号
gpg <span class="hljs-operator">></span>   revkey
gpg <span class="hljs-operator">></span>   save    # 退出前一定要save, 不然所有更改不会生效
</code></pre><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">未完待续</h2><hr>]]></content:encoded>
            <author>ulyc@newsletter.paragraph.com (ulyc)</author>
        </item>
        <item>
            <title><![CDATA[盲水印和图片隐写术 ]]></title>
            <link>https://paragraph.com/@ulyc/sUNp7w8EOYKzehK7YoNV</link>
            <guid>sUNp7w8EOYKzehK7YoNV</guid>
            <pubDate>Tue, 30 Nov 2021 00:37:48 GMT</pubDate>
            <description><![CDATA[The shadow is within. ​ —— 劫 《 英雄联盟》盲水印和图片隐写术盲水印一、演示首先看 这是一张女朋友5cd152cce839e解码水印接下来我们输入一行神奇的命令: python bwm.py --action decode --origin Demo.jpg --im ../Gakki.jpg --result res.jpg 可以得到这样的一张图:res以后谁再跟你抢女朋友就可以这样声明版权了嘿嘿. (脚本和原图都在最后的附录里, 有兴趣的朋友只需要将上面的图片保存为Demo.jpg,附录里的原图保存为Gakki.jpg, 就可以解码出上面的信息)加密水印通过今天的方法你可以将信息放入任意图片,来达到加密信息的目的. 附录里的脚本, 加密用法: python bwm.py --action encode --origin Gakki.jpg --im wm1.png --result Demo.jpg --alpha 2二、用途上面 的水印就叫做盲水印，隐藏式的水印是以数字数据的方式加入音频、图片或影片中，但在一般的状况下无法被看见。隐藏式水印的重要...]]></description>
            <content:encoded><![CDATA[<blockquote><p>The shadow is within. ​ —— 劫 《 英雄联盟》</p></blockquote><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">盲水印和图片隐写术</h2><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">盲水印</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">一、演示</h3><p>首先看 这是一张女朋友</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/38ea9463f3ef9a372b9b50679d6b11a2ec6ec0c178184ffe434d8ec3508c66d6.jpg" alt="5cd152cce839e" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">5cd152cce839e</figcaption></figure><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">解码水印</h5><p>接下来我们输入一行神奇的命令:</p><p><code>python bwm.py --action decode --origin Demo.jpg --im ../Gakki.jpg --result res.jpg</code></p><p>可以得到这样的一张图:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a964940582a60878eefdb415624ee2c17ed3db756e529ecd1f3d000203205637.jpg" alt="res" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">res</figcaption></figure><p>以后谁再跟你抢女朋友就可以这样声明版权了嘿嘿.</p><p>(脚本和原图都在最后的附录里, 有兴趣的朋友只需要将上面的图片保存为<code>Demo.jpg</code>,附录里的原图保存为<code>Gakki.jpg</code>, 就可以解码出上面的信息)</p><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">加密水印</h5><p>通过今天的方法你可以将信息放入任意图片,来达到加密信息的目的.</p><p>附录里的脚本, 加密用法:</p><p><code>python bwm.py --action encode --origin Gakki.jpg --im wm1.png --result Demo.jpg --alpha 2</code></p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">二、用途</h3><p>上面 的水印就叫做<strong>盲水印</strong>，隐藏式的水印是以数字数据的方式加入音频、图片或影片中，但在一般的状况下无法被看见。隐藏式水印的重要应用之一是保护版权，期望能借此避免或阻止数字媒体未经授权的复制和拷贝。</p><h5 id="h-1" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">1.不同人加相同水印</h5><p>声明版权</p><p><strong>应用案例</strong>：</p><ul><li><p>某些画师、摄影师、设计师会在其作品中加入水印。</p></li></ul><pre data-type="codeBlock" text="13年左右有位自称是“超写实主义”的画家，声称自己纯手工画的画写实程度可以超过摄影机，并开办培训班敛财。

后被一位加了盲水印的摄影师戳穿，原来其“画作”都是直接将照片用ps处理成手绘质感的图。
"><code></code></pre><ul><li><p>淘宝防盗图功能</p></li></ul><pre data-type="codeBlock" text="淘宝卖家图会被淘宝自动打上水印，如果有别的卖家存图作为自己的图上传会被检测出。
"><code></code></pre><h5 id="h-2" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">2.不同人加不同水印</h5><p>将某份保密数字资料发送给不同人时，可加上不同标识，如果资料被复制、传播可根据解码出的唯一标识来追究责任人。</p><p><strong>应用案例</strong>：</p><ul><li><p>电影刚刚公映时，每个影院，影厅的 电影底片里都会加入不同的不可见水印， 如果电影流出，就可追究相关影院责任。</p></li><li><p>阿里，华为等公司内部论坛、平台会在HTML页面中加入足够数量 及不被发现的唯一标识。当有内部敏感信息通过截图等方式流出，也可追踪到个人。</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ec82ed6d34236b6a1c8316002b25e12b3b763af2835944f7dd1371c4695e81e7.png" alt="1551441624605" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1551441624605</figcaption></figure><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">三、原理</h3><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">原理图</h4><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/15be610f1c50f8549e70016bfab830a12d9b1e500d79855b1485484eb04cac3d.png" alt="v2-bbecf64a76b3dbfc4539e38e46ad8223_hd" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">v2-bbecf64a76b3dbfc4539e38e46ad8223_hd</figcaption></figure><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">傅里叶变换</h4><ul><li><p>简单复习下傅里叶变换</p></li></ul><p>傅里叶变换简单地说就是将信号在<strong>时域</strong>或<strong>空域</strong>的函数转变到<strong>频域</strong>表示，在和工程学中有许多应用。因其基本思想首先由法国学者约瑟夫·傅里叶系统地提出。</p><ul><li><p>再理解下时域和频域</p></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/30d3b1ad3eb3a412db11fa9e88b8bb128bc85ee8935176f848dd69f614fecc13.gif" alt="Fourier_transform_time_and_frequency_domains_(small)" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Fourier_transform_time_and_frequency_domains_(small)</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/77cb23b95df7c90dc1ea8652eb58619aa934e995abcca17d14f93048d2a180fb.jpg" alt="40cf849e55ed95732a60b52d4019d609_b" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">40cf849e55ed95732a60b52d4019d609_b</figcaption></figure><p>那么，傅里叶变换有什么用呢，</p><ul><li><p>先在纸上画一个sin（x），不一定标准，意思差不多就行。不是很难吧。</p></li><li><p>好，接下去画一个sin（3x）+sin（5x）的图形。这个就很难能画得出来。</p></li></ul><p>现在把sin（3x）+sin（5x）的曲线给你，只看图是看不出这整个曲线的方程式是怎样的，现在需要将把sin（5x）从图里拿出去，看看剩下的是什么。这基本是不可能做到的。</p><p>但是在频域呢？则简单的很，无非就是几条竖线而已。</p><p>这是最简单的一种用法，其他复杂用法不在此赘述。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">频谱图</h4><p>一维信号的变换理解之后，那么图像的频谱图长什么样呢。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/779ba7c7d6b5c818f960933a724ee7ad0b5b79effbbcb5b0e36cb97ea9fbee25.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ece5cc581d7bf5c56aad6472497a7048a9b6ac24f5186a3e3c70316fecc3ed86.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>图片中明亮的部分就是低频（平缓）部分，暗点的是高频（突变交界）部分。一般为了展示会把频谱图低频的部分移到中心。频谱图上的点跟原图不存在一一对应关系，频谱图的每一点都来自于全部的图像（类似于时域曲线的点，和频域图的点）。</p><p>这样可能还不够直观，接下来看这张图。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/118aa333be600dd32f726b335559995d72452c5dd89ac817e76e9a73f980030c.jpg" alt="img" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">img</figcaption></figure><p>这是一张400x400的图，共有16 万个像素点。</p><p>我们平时怎么来表示一张图片呢，首先是在笛卡尔坐标系中用x,y来定位某一确定的点。那么，我们怎么来描述这个点呢？</p><p>我们知道，所有的色彩都是由三原色组成。生活中经常说的红、黄、蓝（青），其实是一种消减型的三原色，光学中的三原色是红、绿、蓝，也就是R、G、B。</p><p>通常我们用来描述图像点的方法就是RGB的值，其实图像处理中用的是<strong>灰度</strong>（Gray scale）来表示图片，但是为了便于理解，下面用的是RGB演示 。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/282a9635d81fd65aa2938d68fd98450384ca777975fef28ec474b249bcc709b0.png" alt="CORB-RGB.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">CORB-RGB.png</figcaption></figure><p>上图是截取了某一行RGB的值做成的曲线图，可以看到，每条曲线都在不停的上下波动，且波动的频率是相同的。有些区域的波动比较小，有些区域突然出现了大幅波动。</p><p>对比一下图像就能发现，曲线波动较大的地方，也是图像出现突变的地方。</p><p><strong>图像的频谱可以理解为将一维的频谱绕着纵轴旋转一圈，形成一个3维的数学函数图（原图中心对称、镜像对称才可以这样干，其他类似），x、y轴代表两个方向的频率，z轴代表该频率的幅值，只不过频谱图像是一个2维图，所以用亮度来表示幅值了。</strong></p><p><strong>二维傅里叶变换的物理意义是将图像的灰度分布函数变换为图像的频率分布函数。</strong></p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">盲水印的特性</h4><p>鲁棒性一般要能抗（压缩 、裁剪、涂画，旋转）。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/86b79e4af39ceec9f5e562fe4fbbf0b24de5b8098f993c09f24e286ed00b26bc.png" alt="特性" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">特性</figcaption></figure><ol><li><p><strong>隐蔽性</strong></p><p>由于不希望被察觉、不希望干扰用户体验、不希望被模仿等等原因，我们的水印不可见，也就是隐匿性。</p></li><li><p><strong>不易移除性</strong></p><p>不易移除性跟鲁棒性有些相似， 不同的是：</p><p>鲁棒性更加强调的是数字资源在传播过程中不要被<strong>不自觉</strong>地干扰和破坏。</p><p>不易移除性是在别有用心者察觉了盲水印的存在后，不被他们<strong>自觉</strong>地移除或者破坏。</p></li><li><p><strong>强健性</strong></p><p>强健性通常也被称作鲁棒性，来自于其英文名称（Robustness）的音译。</p><p>简单地说就是耐操性。</p><p>需要说明的一点是，鲁棒性和隐蔽性通常不可兼得。</p></li><li><p><strong>明确性</strong></p><p>没什么可说的，就是盲水印需要表示出明确的信息。</p></li></ol><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">四、引申</h3><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">图种</h4><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5d02c6df3bcafeb966a011060096a0d98b526c046cd01d0fc9a88f022ce61b8c.jpg" alt="相貌平平" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">相貌平平</figcaption></figure><p>例如这是一张相貌平平的图片, 你可以保存下来,将后缀改为”rar”或者直接用解压工具打开,就可以看到神秘福利.</p><p>制作方法也很简单,在win下 入以下命令就可以做一张”图种”了.</p><p><code>copy /b A.jpg + B.zip C.jpg</code></p><p>大约十年以前，图种被广泛上传到论坛等地用来传播资源。后来由于许多网站在上传图片时会判断图片结尾标识，其之后的全部丢弃，慢慢不再有人使用。(<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://sm.ms/">https://sm.ms/</a>这个图床还是很给力的, 经测试还是可以解析种子)</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">隐藏文件</h4><p>图片可以跟种子文件结合，当然也可以和其他文件结合。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5688b328a2044ee91040323a919ff1396f78bd5f4e0909cd53d694c891c5d623.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>其实隐藏文件和盲水印都属于<strong>图片隐写术</strong>。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">图片隐写术</h2><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E9%9A%90%E5%86%99%E6%9C%AF">隐写术</a>（Steganography）也是数字水印的一种应用，双方可利用隐藏在数字信号中的信息进行沟通。</p><p>数字照片中的注释数据能记录照片拍摄的时间、使用的<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E5%85%89%E5%9C%88">光圈</a>和<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%96%80">快门</a>，甚至是相机的厂牌等信息，这也是数字水印的应用之一。</p><p>某些文件格式可以包含这些称为“metadata”的额外信息。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">用途</h3><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">规避敏感词过滤</h4><p>​ 所谓的“敏感词过滤”，常翻墙的同学，应该都很熟悉了。用图片来隐藏信息，可以规避GFW的敏感词过滤。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">规避肉眼审查</h4><p>​ 国内的很多网站，对于上传的图片，都会进行人工审查。如果能通过技术手段把信息隐藏在图片中，而图片本身又看不出什么异样，人工审核就看不出来。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">传递加密信息</h4><p>​ 不希望被别人看到的资料、信息等。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">常见方法</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/430726d8a0df17d76e350f81f322cf85b2663b36cc6db94ed7a849d511e12b3c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">原理</h3><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">内容覆盖法</h4><p>通常来说，图片文件都有包含2部分：文件头和数据区。</p><p>而“内容覆盖法”，就是把要隐藏的文件，直接【覆盖】到图片文件的【数据区】的【尾部】。</p><p>比方说，某图片有 100KB，其中文件头占 1KB，那么，数据区就是 99KB。也就是说，最多只能隐藏 99KB 的文件。</p><p>切记：<strong>覆盖的时候，千万不可破坏文件头</strong>。文件头一旦破坏，这个图片文件就不再是一个合法的图片文件了。</p><p>使用这种方法，对图片文件的格式，是有讲究的——最好用【24位色的 BMP 格式】。</p><ul><li><p>BMP 格式本身比较简单，数据区随便覆盖，问题不大；</p></li><li><p>24位色的 BMP 相对其它的格式 BMP，文件尺寸更大，可以隐藏更多内容。</p></li></ul><pre data-type="codeBlock" text="import sys

def embed(container_file, data_file, output_file) :
    &quot;&quot;&quot;代码没有严格计算 BMP 的文件头尺寸，只是大致预留了 1024 字节&quot;&quot;&quot;
    
    container = open(container_file, &quot;rb&quot;).read()
    data = open(data_file, &quot;rb&quot;).read()

    if len(data)+1024 &gt;= len(container) :
        print(&quot;Not enough space to save &quot; + data_file)
    else :
        f = open(output_file, &quot;wb&quot;)
        f.write(container[ : len(container)-len(data)])
        f.write(data)
        f.close()

if &quot;__main__&quot; == __name__ :
    try :
        if len(sys.argv) == 4 :
            embed(sys.argv[1], sys.argv[2], sys.argv[3])
        else :
            print(&quot;Usage:\n%s container data output&quot; % sys.argv[0])
    except Exception as err :
        print(err)
"><code><span class="hljs-keyword">import</span> sys

<span class="hljs-keyword">def</span> <span class="hljs-title function_">embed</span>(<span class="hljs-params">container_file, data_file, output_file</span>) :
    <span class="hljs-string">"""代码没有严格计算 BMP 的文件头尺寸，只是大致预留了 1024 字节"""</span>
    
    container = <span class="hljs-built_in">open</span>(container_file, <span class="hljs-string">"rb"</span>).read()
    data = <span class="hljs-built_in">open</span>(data_file, <span class="hljs-string">"rb"</span>).read()

    <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(data)+<span class="hljs-number">1024</span> >= <span class="hljs-built_in">len</span>(container) :
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Not enough space to save "</span> + data_file)
    <span class="hljs-keyword">else</span> :
        f = <span class="hljs-built_in">open</span>(output_file, <span class="hljs-string">"wb"</span>)
        f.write(container[ : <span class="hljs-built_in">len</span>(container)-<span class="hljs-built_in">len</span>(data)])
        f.write(data)
        f.close()

<span class="hljs-keyword">if</span> <span class="hljs-string">"__main__"</span> == __name__ :
    <span class="hljs-keyword">try</span> :
        <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(sys.argv) == <span class="hljs-number">4</span> :
            embed(sys.argv[<span class="hljs-number">1</span>], sys.argv[<span class="hljs-number">2</span>], sys.argv[<span class="hljs-number">3</span>])
        <span class="hljs-keyword">else</span> :
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"Usage:\n%s container data output"</span> % sys.argv[<span class="hljs-number">0</span>])
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> err :
        <span class="hljs-built_in">print</span>(err)
</code></pre><h4 id="h-lsb" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">LSB最低有效位</h4><p>很多商业软件使用的原理都是这个方法。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a83b3f32ecf8bb813f26af6882f6d64563ad544aba3aa39bc98e364e08d0fb88.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>例如在PNG图片的储存中，每个颜色会有8bit，LSB（<strong>Least Significant Bit</strong>）隐写就是修改了像数中的最低的1bit，在人眼看来是看不出来区别的，也把信息隐藏起来了。（每个像数可以携带3bit的信息。）</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6d1de92beb7e17c813ab21e34a014ff47e64a333e8be3a7fc90f1f2d96d857c9.png" alt="image-20210113193335303" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">image-20210113193335303</figcaption></figure><p>譬如我们想把’A’隐藏进来的话，如下图，就可以把A转成16进制的0x61再转成二进制的01100001，再修改为红色通道的最低位为这些二进制串。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/69b5d5b18b47e5ebc9dfbc671bd55a26ebf63761dddb1a636ac68346ccb19862.png" alt="image-20210113193350763" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">image-20210113193350763</figcaption></figure><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">最后</h3><ol><li><p>附上前面演示代码的实现:</p><p>(参考了几个git hub上的项目,不过鲁棒性都不太好)</p><pre data-type="codeBlock" text="# coding=utf-8
import cv2
import numpy as np
import random
import os
from argparse import ArgumentParser
   
ALPHA = 5
   
class BlindWaterMark():
    &quot;&quot;&quot;盲水印加解密，无频移简单版&quot;&quot;&quot;
    def __init__(self):
        self.parser = ArgumentParser()
        self.parser.add_argument(&apos;--action&apos;, dest=&apos;action&apos;, required=True)
        self.parser.add_argument(&apos;--origin&apos;, dest=&apos;ori&apos;, required=True)
        self.parser.add_argument(&apos;--img&apos;, dest=&apos;img&apos;, required=True)
        self.parser.add_argument(&apos;--result&apos;, dest=&apos;res&apos;, required=True)
        self.parser.add_argument(&apos;--alpha&apos;, dest=&apos;alpha&apos;, default=ALPHA)
   
    def encode(self, ori_path, wm_path, res_path, alpha):
        img = cv2.imread(ori_path)
        img_f = np.fft.fft2(img)  # 2维离散傅里叶变换
   
        height, width, channel = np.shape(img)
        watermark = cv2.imread(wm_path)
        wm_height, wm_width = watermark.shape[0], watermark.shape[1]
   
        # 水印随机编码
        x, y = range(height / 2), range(width)
        random.seed(height + width)   # 随机数解码时可控
        random.shuffle(x)
        random.shuffle(y)
           
        # 按目标图片大小 对水印图进行对称
        tmp = np.zeros(img.shape)  # 根据图片形状，生成0填充的矩阵
   
        for i in range(height / 2):
            for j in range(width):
                if x[i] &lt; wm_height and y[j] &lt; wm_width:
                    tmp[i][j] = watermark[x[i]][y[j]]
                    tmp[height - 1 - i][width - 1 - j] = tmp[i][j]
   
        res_f = img_f + alpha * tmp  # 原图频域值  +  水印频域值
        res = np.fft.ifft2(res_f)      # 傅里叶逆变换
        res = np.real(res)  # 转换为实数
   
        cv2.imwrite(res_path, res, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
   
   
    def decode(self, ori_path, img_path, res_path, alpha):
        ori = cv2.imread(ori_path)
        img = cv2.imread(img_path)
   
        ori_f = np.fft.fft2(ori)
        img_f = np.fft.fft2(img)
   
        height, width = ori.shape[0], ori.shape[1]
        watermark = (ori_f - img_f) / alpha
   
        watermark = np.real(watermark)
        res = np.zeros(watermark.shape)
   
        random.seed(height + width)
   
        x = range(height / 2)
        y = range(width)
        random.shuffle(x)
        random.shuffle(y)
   
        for i in range(height / 2):
            for j in range(width):
                res[x[i]][y[j]] = watermark[i][j]
                res[height - i - 1][width - j - 1] = res[i][j]
   
        cv2.imwrite(res_path, res, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
   
    def run(self):
        options = self.parser.parse_args()
        action = options.action
        ori = options.ori
        img = options.img
        res = options.res
        alpha = float(options.alpha)
   
        if not os.path.isfile(ori):
            parser.error(&quot;image %s does not exist.&quot; % ori)
        if not os.path.isfile(img):
            parser.error(&quot;watermark %s does not exist.&quot; % img)
   
        if action == &quot;encode&quot;:
            self.encode(ori, img, res, alpha)
        elif action == &quot;decode&quot;:
            self.decode(ori, img, res, alpha)
   
   
if __name__ == &apos;__main__&apos;:
    bwm = BlindWaterMark()
    bwm.run()
   
"><code><span class="hljs-comment"># coding=utf-8</span>
import cv2
import numpy as np
import random
import os
from argparse import ArgumentParser
   
<span class="hljs-attr">ALPHA</span> = <span class="hljs-number">5</span>
   
class BlindWaterMark():
    """盲水印加解密，无频移简单版"""
    def __init__(self):
        <span class="hljs-attr">self.parser</span> = ArgumentParser()
        self.parser.add_argument('--action', <span class="hljs-attr">dest</span>=<span class="hljs-string">'action'</span>, required=<span class="hljs-literal">True</span>)
        self.parser.add_argument('--origin', <span class="hljs-attr">dest</span>=<span class="hljs-string">'ori'</span>, required=<span class="hljs-literal">True</span>)
        self.parser.add_argument('--img', <span class="hljs-attr">dest</span>=<span class="hljs-string">'img'</span>, required=<span class="hljs-literal">True</span>)
        self.parser.add_argument('--result', <span class="hljs-attr">dest</span>=<span class="hljs-string">'res'</span>, required=<span class="hljs-literal">True</span>)
        self.parser.add_argument('--alpha', <span class="hljs-attr">dest</span>=<span class="hljs-string">'alpha'</span>, default=ALPHA)
   
    def encode(self, ori_path, wm_path, res_path, alpha):
        <span class="hljs-attr">img</span> = cv2.imread(ori_path)
        <span class="hljs-attr">img_f</span> = np.fft.fft2(img)  <span class="hljs-comment"># 2维离散傅里叶变换</span>
   
        height, width, <span class="hljs-attr">channel</span> = np.shape(img)
        <span class="hljs-attr">watermark</span> = cv2.imread(wm_path)
        wm_height, <span class="hljs-attr">wm_width</span> = watermark.shape[<span class="hljs-number">0</span>], watermark.shape[<span class="hljs-number">1</span>]
   
        <span class="hljs-comment"># 水印随机编码</span>
        x, <span class="hljs-attr">y</span> = range(height / <span class="hljs-number">2</span>), range(width)
        random.seed(height + width)   <span class="hljs-comment"># 随机数解码时可控</span>
        random.shuffle(x)
        random.shuffle(y)
           
        <span class="hljs-comment"># 按目标图片大小 对水印图进行对称</span>
        <span class="hljs-attr">tmp</span> = np.zeros(img.shape)  <span class="hljs-comment"># 根据图片形状，生成0填充的矩阵</span>
   
        for i in range(height / 2):
            for j in range(width):
                if x<span class="hljs-section">[i]</span> &#x3C; wm_height and y<span class="hljs-section">[j]</span> &#x3C; wm_width:
                    tmp<span class="hljs-section">[i]</span><span class="hljs-section">[j]</span> = watermark<span class="hljs-section">[x[i]]</span><span class="hljs-section">[y[j]]</span>
                    tmp<span class="hljs-section">[height - 1 - i]</span><span class="hljs-section">[width - 1 - j]</span> = tmp<span class="hljs-section">[i]</span><span class="hljs-section">[j]</span>
   
        <span class="hljs-attr">res_f</span> = img_f + alpha * tmp  <span class="hljs-comment"># 原图频域值  +  水印频域值</span>
        <span class="hljs-attr">res</span> = np.fft.ifft2(res_f)      <span class="hljs-comment"># 傅里叶逆变换</span>
        <span class="hljs-attr">res</span> = np.real(res)  <span class="hljs-comment"># 转换为实数</span>
   
        cv2.imwrite(res_path, res, <span class="hljs-section">[int(cv2.IMWRITE_JPEG_QUALITY), 100]</span>)
   
   
    def decode(self, ori_path, img_path, res_path, alpha):
        <span class="hljs-attr">ori</span> = cv2.imread(ori_path)
        <span class="hljs-attr">img</span> = cv2.imread(img_path)
   
        <span class="hljs-attr">ori_f</span> = np.fft.fft2(ori)
        <span class="hljs-attr">img_f</span> = np.fft.fft2(img)
   
        height, <span class="hljs-attr">width</span> = ori.shape[<span class="hljs-number">0</span>], ori.shape[<span class="hljs-number">1</span>]
        <span class="hljs-attr">watermark</span> = (ori_f - img_f) / alpha
   
        <span class="hljs-attr">watermark</span> = np.real(watermark)
        <span class="hljs-attr">res</span> = np.zeros(watermark.shape)
   
        random.seed(height + width)
   
        <span class="hljs-attr">x</span> = range(height / <span class="hljs-number">2</span>)
        <span class="hljs-attr">y</span> = range(width)
        random.shuffle(x)
        random.shuffle(y)
   
        for i in range(height / 2):
            for j in range(width):
                res<span class="hljs-section">[x[i]]</span><span class="hljs-section">[y[j]]</span> = watermark<span class="hljs-section">[i]</span><span class="hljs-section">[j]</span>
                res<span class="hljs-section">[height - i - 1]</span><span class="hljs-section">[width - j - 1]</span> = res<span class="hljs-section">[i]</span><span class="hljs-section">[j]</span>
   
        cv2.imwrite(res_path, res, <span class="hljs-section">[int(cv2.IMWRITE_JPEG_QUALITY), 100]</span>)
   
    def run(self):
        <span class="hljs-attr">options</span> = self.parser.parse_args()
        <span class="hljs-attr">action</span> = options.action
        <span class="hljs-attr">ori</span> = options.ori
        <span class="hljs-attr">img</span> = options.img
        <span class="hljs-attr">res</span> = options.res
        <span class="hljs-attr">alpha</span> = float(options.alpha)
   
        if not os.path.isfile(ori):
            parser.error("image %s does not exist." % ori)
        if not os.path.isfile(img):
            parser.error("watermark %s does not exist." % img)
   
        if <span class="hljs-attr">action</span> == <span class="hljs-string">"encode"</span>:
            self.encode(ori, img, res, alpha)
        elif <span class="hljs-attr">action</span> == <span class="hljs-string">"decode"</span>:
            self.decode(ori, img, res, alpha)
   
   
if <span class="hljs-attr">__name__</span> == <span class="hljs-string">'__main__'</span>:
    <span class="hljs-attr">bwm</span> = BlindWaterMark()
    bwm.run()
   
</code></pre></li></ol><p>2.隐写术是一门很深、应用很广泛的学问，这里讲的很泛，权当做抛砖引玉。图片隐写术只是其中一种，有兴趣的同学可以看下面这本书。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/de38a021a33ae6e9938b704c094bd94a465eb9e70fa179cb9058c93aedea98d2.png" alt="1551625636929" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1551625636929</figcaption></figure>]]></content:encoded>
            <author>ulyc@newsletter.paragraph.com (ulyc)</author>
        </item>
        <item>
            <title><![CDATA[常见RFID卡片介绍、破解思路 及 Proxmark3简介 ]]></title>
            <link>https://paragraph.com/@ulyc/rfid-proxmark3</link>
            <guid>Uvzl2k2fC0QaFcbU9Oqx</guid>
            <pubDate>Tue, 30 Nov 2021 00:26:13 GMT</pubDate>
            <description><![CDATA[我们大多数人至少都要工作三十年，这三十年里还会有很多东西要学。所以不用太在意之前学了什么，更重要的是看你还能学会什么。无论之前学过什么，将来都要再学新东西。无论之前学的是什么，将来也都会有用。艺无止境，功不唐捐。 ​ —— tombkeeperRFID卡片前言这篇只是最近学习RFID技术的一个笔记，请勿用于非法用途。简介射频识别（英语：Radio Frequency IDentification，缩写：RFID）是一种无线通信技术，可以通过无线电信号识别特定目标并读写相关数据，而无需识别系统与特定目标之间建立机械或者光学接触。 常用的ETC，门禁卡，手机的NFC功能，二代身份证，电子护照，动物识别标签等都是应用了RFID技术。常见卡片分类RFID卡.png介绍各种IC卡片的文章浩如烟海，不过大部分只介绍了低频的id卡以及符合ISO-14443A 标准的mifare系列卡。 因为搬家之后，坑爹物业只给一张门禁卡，于是Nerd之血熊熊燃烧, 花了几百大洋买了个Proxmark3，当然要好好研究下RFID技术啦，也不会仅止步于常见几种卡片的探索。 其实只看上面的脑图基本上就对RFID各...]]></description>
            <content:encoded><![CDATA[<blockquote><p>我们大多数人至少都要工作三十年，这三十年里还会有很多东西要学。所以不用太在意之前学了什么，更重要的是看你还能学会什么。无论之前学过什么，将来都要再学新东西。无论之前学的是什么，将来也都会有用。艺无止境，功不唐捐。</p><p>​ —— tombkeeper</p></blockquote><h2 id="h-rfid" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">RFID卡片</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">前言</h3><p>这篇只是最近学习RFID技术的一个笔记，请勿用于非法用途。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">简介</h3><p><strong>射频识别</strong>（英语：<strong>R</strong>adio <strong>F</strong>requency <strong>ID</strong>entification，<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E7%B8%AE%E5%AF%AB">缩写</a>：<strong>RFID</strong>）是一种<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E7%84%A1%E7%B7%9A">无线</a><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E9%80%9A%E4%BF%A1%E6%8A%80%E6%9C%AF">通信技术</a>，可以通过<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E6%97%A0%E7%BA%BF%E7%94%B5">无线电</a>信号识别特定目标并读写相关数据，而无需识别系统与特定目标之间建立<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E6%9C%BA%E6%A2%B0">机械</a>或者<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zh.wikipedia.org/wiki/%E5%85%89%E5%AD%A6">光学</a>接触。</p><p>常用的ETC，门禁卡，手机的NFC功能，二代身份证，电子护照，动物识别标签等都是应用了RFID技术。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">常见卡片分类</h3><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4989521f6ad612c520303858c5848b923433b1e8289916f50487e264be5ff536.png" alt="RFID卡.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">RFID卡.png</figcaption></figure><p>介绍各种IC卡片的文章浩如烟海，不过大部分只介绍了低频的id卡以及符合ISO-14443A 标准的mifare系列卡。</p><p>因为搬家之后，坑爹物业只给一张门禁卡，于是Nerd之血熊熊燃烧, 花了几百大洋买了个Proxmark3，当然要好好研究下RFID技术啦，也不会仅止步于常见几种卡片的探索。</p><p>其实只看上面的脑图基本上就对RFID各种卡有个大致印象了，下面是对一些好玩的卡的详细介绍，无耐心可跳过。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">低频</h4><h5 id="h-id" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">ID卡</h5><p>ID卡是我们的俗称，内部芯片的全名叫做EM4100或EM41XX ，频率是125kHz。每张卡出厂就有独一无二的ID号，不可改写。没有任何加密，只要知道卡号就可以模拟。</p><p>特殊的还有250K、375K、500K频率的ID卡，原版proxmark3不支持这种卡的读写，祖国魔改版有些支持。</p><h5 id="h-t5577" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">T5577卡</h5><p>T5577 卡是一种可以写入数据可以加密的低频卡。最特别之处是，写入ID号可以变身成为ID卡，写入HID号可以变身HID卡，写入Indala卡号，可以变身Indala卡。</p><p>T5577一共有8个块，每个块只能存8位数。第0块是用来设置卡片类型和调制方式的，决定了卡片是ID卡还是HID卡，如果随意修改会导致读不到卡。最后一个块，在没有加密时是数据区，加密后，其数据就变成了密码。</p><p>国内这卡主要是用来模拟ID卡用的。</p><h4 id="h-14443a" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">高频 -14443A</h4><h5 id="h-m1-s50" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">M1 S50卡</h5><p>目前最常见的高频卡，也是我们口中俗称的IC卡。M1卡科储存的数据大小为8k，分为16个扇区，每个扇区分4个块，每个块为16个字节，以块为存取单位。<strong>每个扇区都有独立的一组密码及访问控制</strong>，每张卡有唯一的一个32位的序列号。每个扇区的0,1,2块为数据块，用来存储数据，第3块为控制块，包括了密A、存取控制、密码B 每张卡的第0扇区的第0块用来春芳厂商代码，不可更改。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/389a80c0b243e45586af811072d92a582703b9dc22d1511a4d5eaab6196bbf0d.png" alt="M1卡数据结构.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">M1卡数据结构.png</figcaption></figure><p>中间4字节控制字是管理密码权限，用来设置A密码和B密码的功能。默认不修改的时候，可以用A密码读写所有数据。A密码不可读出，B密码可以用A密码读出。<strong>密码不一定可以读取，由控制字决定。</strong></p><p>这个卡又分 <strong>非加密卡</strong> 、<strong>半加密卡</strong> 和 <strong>全加密卡</strong>。</p><p>非加密卡中所有扇区的KEYA和KEYB数值都是默认值FFFFFFFFFFFF。</p><p>而加密卡中，其中有扇区的KEYA和KEYB不等于FFFFFFFFFFFF，部分扇区加密的卡称半加密卡，所有扇区都加密的卡称全加密卡。</p><h5 id="h-m1-uid" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">M1 UID卡</h5><p>全称l Mifare UID Chinese magic card（中国魔术卡），简称UID卡。</p><p>M1 UID卡是针对M1 S50卡特制的变种卡，用起来和M1 S50完全一样，只是多了一个功能，就是0扇区块的数据可以随意修改。因此UID号也可以随意修改，厂家信息也可以随意修改。UID卡修改0扇区0块数据是靠指令进入工厂模式，可以直接对全卡任何数据编辑，不需要密码即可读写卡，同时不怕写坏卡，即使写错0块，写坏扇区控制字，也可以随时修复回来，不影响后续使用。</p><h5 id="h-cuid" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">CUID卡</h5><p>CUID卡是针对UID卡做的优化。CUID卡可以重复修改0块，但是它和UID卡的区别是，UID卡是通过<strong>指令</strong>修改0块，CUID使用的是常规密码验证的方法写0块（写错了之后重写需要清卡），其他扇区和标准M1卡相同。缺点是，还是有可能会被检测出来，而且如果不小心写错了UID号的校验位导致无法读卡，没办法修复只能报废。</p><h5 id="h-fuid" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">FUID卡</h5><p>FUID卡是针对UID卡做的优化。新的读卡系统，通过检测卡片对特殊指令的回应，可以检测出UID卡，因此可以来拒绝UID卡的访问，来达到屏蔽复制卡的功能。<strong>FUID可以修改0块，但只可以修改一次</strong>，写错也没办法更改，也不能重复利用。修改后和M1卡完全一样，很难被屏蔽检测。</p><h5 id="h-cfuid" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">CFUID卡</h5><p>​ 鉴于FUID卡写错的成本太高，又发展出了这种卡。 CFUID卡 0扇区固化前可随意修改（相当于UID卡），固化（锁卡）后就跟M1卡完全一样。</p><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">侦测卡：</h5><p>可用122等设备写入id号然后用来读取并记录设备发出的密码信息，用于侦测密码，但其功能鸡肋，前有pm3离线侦测，后有变色龙模拟加侦测，现在基本淘汰。</p><h5 id="h-emv" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">EMV卡</h5><p>EMV规范是由Europay、Mastercard、Visa三大信用卡国际组织联合制定的IC（智能）卡金融支付应用标准，非接触传输协议方面也是遵循的14443A标注，是一种<strong>CPU芯片卡</strong>。</p><p>目前基于EMV卡的非接触式支付的实现有三个：VISA的payWave，MasterCard的PayPass以及银联的闪付QuickPass。目前从外观来看，银联发行的卡面有芯片的IC卡均支持闪付，部分银行支持VISA的payWave。</p><h4 id="h-14443b" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">高频 -14443B</h4><p>跟ISO 14443 -Type A 标准 的不同主要在于<strong>载波的调制深度及位的编码方式</strong>。TYPE A采用<strong>开关键控(On-Off keying)的</strong>Manchester编码，TYPE B采用<strong>NRZ-L</strong>的<strong>BPSK编码</strong>。</p><p>TYPE B与TYPE A相比，具有<strong>传输能量不中断、速率更高、抗干扰能力强</strong>的优点。RFID的核心是防冲突技术，这也是和接触式IC卡的主要区别。ISO14443-3规定了TYPEA和TYPE B的防冲突机制。二者防冲突机制的原理不同，前者是<strong>基于位冲突检测协议</strong>，而TYPE B<strong>通信系列命令序列完成防冲突。</strong></p><p>目前的二代身份证，社保卡，护照都是基于此标准，研究这个标准最初是为了能读出身份证信息或者护照，其中曲折下一篇文章再说。</p><p>Proxmark3的14b部分有对 ST Microelectronics 公司的 SRI512卡 和SRIX4K卡 的特别支持。</p><h4 id="h-nfc" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">NFC标签</h4><p>目前有五种，分别基于14a, 14b，Felica ，ISO/IEC 15693 标准, 详见上面脑图。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">高频卡 低频卡区分方法</h3><p>直接淘宝复制来的，比较直观：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3d37e48b8d0ebfa2a9e4abc3a7fd21d159cd4f097e6444b3d97f7e6036f577d7.png" alt="1.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">1.png</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4616682121e5f37e72170dbe46ea4aebbd5b305fdf6787bfaf829ed1b9ffbd08.png" alt="2.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">2.png</figcaption></figure><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">门禁卡破解思路</h3><p>ID卡使用手持机或者proxmark3等设备直接读出卡号即可模拟，最是无脑，CPU卡建议直接放弃。</p><p>所以这里的门禁卡单质 Mafira系列。</p><h4 id="h-ic" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">IC卡加密方式</h4><p>要知道怎么破解，先要知道他们是怎么加密。</p><p>目前常见的加密方式有这几种：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/36104d8f89b6991fce42e5968a6d88f772d95274761ce02898cce23cd885cf76.png" alt="IC卡加密方式.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">IC卡加密方式.png</figcaption></figure><h5 id="h-1" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">1.固定加密（校验码）：</h5><p>彼时来自东方的神秘技术 ：中国魔术卡 尚未降世，就算复制出来原卡数据，每张IC的ID也是不一样的，厂家只需要校验UID跟校验位匹配不匹配就可以防复制卡了。</p><p>这种只需要UID卡复制其UID以及校验位即可完美破解。</p><h5 id="h-2" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">2.一卡一密：</h5><p>这种加密方式只是把校验码，改成了密码。刷卡机读卡是根据卡号算出这张卡独一无二的密码，然后再用密码访问/修改金额 。</p><p>运用UID卡复制，也可简单解决。</p><h5 id="h-3" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">3.全加密：</h5><p>即IC卡16扇区均加入密码，一般是一个卡商用同一密码，密码破解可通过 侦测卡或pm3离线侦测，密码已知后，写入普通卡或UID卡，即可实现复制。</p><p>后来又出现了一种 一卡一密+ 全加密的卡，不过在PM3及UID卡面前不过是土鸡瓦狗而已。</p><h5 id="h-4" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">4.动态码加密：</h5><p>每次刷卡后，卡内数据都会变化。</p><p>这种比较麻烦，可以分几种情况：</p><ol><li><p>有些系统比较简单，每次刷新后某个数据加一，或者加固定数字，这种很容易<strong>发现规律</strong>和破解。</p></li><li><p>有些卡数据刷新后没有什么规律，明显用了某种算法，这种有能力的可以多刷几次，尝试<strong>逆向算法</strong>，不过难度比较大，</p></li><li><p>通过更改控制位或者修改卡内某些地方的数据来<strong>压制卡内数据的滚动</strong>，这是利用了早期某些厂家的读头不会校验计算后的数据是否写入成功的漏洞。</p></li><li><p>一些系统识别到卡里数据是从未滚动过的初始值后，就不会再做任何校验，认为这是张新卡。这种只要记录下初始数据，复制卡每次刷卡后 <strong>重置数据</strong>即可。 (刚了解到还有一种GTU卡（gtu、guid、gid、gpu，处女卡）, 可以锁定滚动码，让读卡器写卡失败卡)</p></li><li><p>一些系统识别到卡里数据是初始值后，还会进行校验，这时候我们可以使用同厂家同型号同版本的发卡器，通过修改发卡器发卡规则使得规则与物业的发卡规则相同来<strong>发卡</strong>。但是破解发卡规则同样很难，同时梯控厂家也不会向个人单独销售配套发卡器。</p></li><li><p>社工大法：通过保洁阿姨、保安大哥或者特别的技法获取 <strong>全通卡</strong>，就是给内部员工用的“万能钥匙”，这种卡一般不做加密，搞到之后复制一张基本就OK了。</p></li></ol><p><strong>注意事项</strong>：复制卡不确定是否是滚动码时， 复制后第一次刷卡原则上请刷原卡，不然数据滚动之后，原卡可能作废 。 卡与原卡仅一张有效</p><h5 id="h-5" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">5.防复制加密：</h5><p>用UID卡复制成功以后去现场刷卡没任何反应 或 就可以使用一次以后就给设备破环了拷贝卡的问题。</p><p>也存在几种情况，目前最常用的：</p><ol><li><p>校验magic指令，UID卡会响应magic指令，所以防火墙只要发现有magic指令的响应直接ban掉改卡，于是CUID卡应运而生。</p></li><li><p>防火墙尝试修改卡的0扇区，修改成功则说明是CUID卡，ban掉。 这种用FUID或者CFUID复制即可。</p></li></ol><h5 id="h-6" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">6.复合卡加密：</h5><p>利用ID或IC设备复制成功以后就可以开启其中一个地方，其他地方不可以同时开启。一般是IC+ID的结构，需要同时复制高频低频两个芯片。</p><h5 id="h-7cpu" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">7.CPU芯片加密：</h5><p>这种分析数据时全是零， 可能目标卡是CPU卡模拟的M1卡 或是 修改了控制位的数据把卡号隐藏起来。 这种可以最多可以做到复制UID，模拟刷个门禁啥的，涉及金额的就别想了。</p><h4 id="h-" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">一般流程</h4><p>流程图如下：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9d32673fb04976fe59d983a363d88e1faddb70b235977813f14ba3118c8c35e6.png" alt="image.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">image.png</figcaption></figure><h2 id="h-proxmark3" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Proxmark3</h2><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">前言</h3><p>之前想买个proxmark3 玩，但是发现淘宝卖家基本都是自吹自擂，对自己是PM3哪个版本都遮遮掩掩，语焉不详。 谷歌到的中文资料也比较少，大多是互相复制粘贴的资料，没人仔细介绍过PM3都有哪些版本，于是有了写这篇的动力，希望能使新手对proxmark3有个直观了解。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">简介</h3><p>Proxmark3是由<em>Jonathan Westhues</em>为了他的硕士论文设计开发的开源硬件，其主要用途是实现RFID卡片 的嗅探、读取破解以及克隆等等操作。</p><p>提到RFID， 就不得不提Proxmark3，PM3 属于这个领域的大杀器，基本相当于kali之于安全，node之于前端。它可以嗅探、模拟以及读取多种不同种类型的RFID，同时它还有一个<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://www.proxmark.org/forum/index.php">官方社区</a>，这里有不少同样的爱好者在里面学习交流。</p><p>Proxmark，确切来说是prox（接近的），mark（标签），翻译过来的意思就是“不用接触，靠近就能刷的卡片”。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">版本</h3><h4 id="h-proxmark2" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Proxmark2</h4><p>Proxmark是没有1的 ，Proxmark3 前身是Proxmark2。</p><p>Proxmark2版本是因为<em>Jonathan Wesrhues</em> 为了复制Verichip才应运而生的。 而Proxmark2的前身就是一个便携式的Verichips，该硬件可以读取并且重放Verichip的ID，如果利用天线去靠近Verichip，那样子设备就可以永远的保留ID在芯片里面，实际上Jonathan Westhues只是采用逆向工程把Verichip的频率和调制模式进行捕抓，从而进行回放操作。</p><h4 id="h-proxmark3" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Proxmark3 原版</h4><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><figcaption HTMLAttributes="[object Object]" class="">img</figcaption></figure><p>原型机，长这样，开源硬件，电路板github有，已经过时了，不是商业产品，不卖。</p><p>其他版本都是基于此版的原理做的改板。</p><h4 id="h-proxmark3-rdv2" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Proxmark3 RDV2</h4><p>这个版本算是Proxmark3第一次商业化的版本，研发团队是<em>Elechouse</em>（深圳一家硬件厂商） 。 RDV2 即是 Revision Two（重制版2 )。</p><p>Proxmark3 RDV2 修改和更新了Proxmark3所有主要的硬件组件，包括微控制器，FPGA和闪存。</p><p>但是，最重要的变化是天线的设计和实现。 Proxmark 3的笨重，笨拙和未调谐的天线已替换为紧凑的，预先调谐的HF和LF天线，使用标准的SMA接口代替以前使用的USB-Hirose电缆。</p><p>这个版本预装了可拆的低频和高频天线，也是首个“ALL-IN-ONE”的版本。但是天线性能存在已知问题，并且会被继电器故障影响。</p><p>有些论坛说的血贵的就是这个版本，之前貌似上千，现在五六百左右吧。</p><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">技术规格</h5><ul><li><p><strong>CPU</strong> AT91SAM7S512</p></li><li><p><strong>Storage</strong> 512Kb SPI flash</p></li><li><p><strong>Interface</strong> 4x mode LEDs, 1x button.</p></li><li><p><strong>Battery</strong> 独立外接电源</p></li><li><p><strong>天线</strong></p><ul><li><p><strong>LF</strong> 预装，可拆</p></li><li><p><strong>HF</strong> 预装，可拆</p></li></ul></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/08ce2948811d3c14337ac493d83c6a5982a97d3d5504b950eb90c68ebe984ec3.png" alt="rdv2.png" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">rdv2.png</figcaption></figure><h4 id="h-proxmark3-easy" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Proxmark3 EASY</h4><p>同样是 <em>Elechouse</em>团队的作品，是Proxmark3 RDV2 的阉割版，主要为了迎合中国市场在某宝卖的。</p><p>基本上某宝卖的都是基于这个版本或Proxmark3 RDV2 的魔改版。</p><p>比RDV2阉割了CPU、内存,还有外接电池。</p><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">技术规格</h5><ul><li><p><strong>CPU</strong> AT91SAM7S256</p></li><li><p><strong>Storage</strong> 256Kb SPI flash</p></li><li><p><strong>Interface</strong> 4x mode LEDs, 1x button.</p></li><li><p><strong>天线</strong></p><ul><li><p><strong>LF</strong> 需自行组装</p></li><li><p><strong>HF</strong> 一体，不可拆</p></li></ul></li></ul><p>长这样：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><figcaption HTMLAttributes="[object Object]" class="">Proxmark3 EASY</figcaption></figure><h4 id="h-proxmark-3-evo" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Proxmark 3 EVO</h4><p>Proxmark 3 EVO(Evolution，进化版)，是<strong>Elechouse</strong> 开发的最后一个Proxmark 3版本，更加的小型化，用了ABS 的材质，加了点灯，适配了安卓平台。</p><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">技术规格</h5><ul><li><p><strong>CPU</strong> AT91SAM7S512</p></li><li><p><strong>Storage</strong> External 2MBits / 512Kb SPI flash</p></li><li><p><strong>Interface</strong> 1x RGB LED, 1x button.</p></li><li><p><strong>电源</strong> 外接独立电池</p></li><li><p>天线</p><ul><li><p><strong>LF</strong> 预装，一体</p></li><li><p><strong>HF</strong> 预装，一体</p></li></ul></li></ul><p>这个版本国内见的不多，优化也有限，长这样：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><figcaption HTMLAttributes="[object Object]" class="">Proxmark 3 EVO</figcaption></figure><h4 id="h-proxmark3-rdv4" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Proxmark3 RDV4</h4><p>Proxmark3 RDV4是目前Proxmark3 平台 最新的版本，由 <em>RRG</em>团队开发，就是开官方论坛和固件很受欢迎的<em>iceman</em> 所在的团队 。 不过价格比较贵，基础版要一千五左右，所有外设买齐得好几千，需要海淘。</p><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">版本特色</h5><ul><li><p>更小的体积 54 x 87 x 10mm （EVO是60 x 90 x 12mm）</p></li><li><p>支持了 SIM/Smart 卡的嗅探和读取</p></li><li><p>可扩展框架：</p><ul><li><p>可热插拔的中长距离天线</p></li><li><p>增加了 蓝牙 和 wifi 模式</p></li></ul></li></ul><h5 id="h-" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">技术规格</h5><ul><li><p><strong>CPU</strong> SAM7S512</p></li><li><p><strong>Storage</strong> External 2MBits / 256Kb SPI flash</p></li><li><p><strong>Interface</strong> 4x power LEDs, 4x mode LEDs, 1x button.</p></li><li><p>天线</p><ul><li><p><strong>LF</strong> (125KHz): 70mm @ 65V</p></li><li><p><strong>HF</strong> (13.56MHz): 88mm @ 44V</p></li></ul></li></ul><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f003426d471aedfc8761a2b73f2edc94919f8f4766379ed204e1a08e594f4ffc.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h4 id="h-proxmark3" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Proxmark3 各种祖国版</h4><p>商家鼓吹什么3.0、4.0、5.0，终极 版本，其实各种版本基本都是Proxmark3 RDV2 或者easy 魔改的，选购时关注下cpu版本和内存 线圈和做工即可。</p><p>不过有时候会看到各种颜色，颜色只是印刷电路板用的阻焊剂（阻焊漆）不一样，油墨颜色不一样，不会影响实际功能和质量。</p><p>常见的电路板颜色有绿色、红色、蓝色、黑色。详细信息可以自行百度。原来的pm3是黑色的，看上去高端一些。现在新出了蓝色的，没别的原因，就是为了降低成本。虽然不影响质量，但是绿色、红色、蓝色的油墨用得比较多，量大价格就低。</p><p>不要听一些商家瞎吹做了什么升级，保证元器件没有任何改动。商家鼓吹蓝色是升级款，只是为了掩盖他的真实原因是为了降低成本，外加一波营销。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8b6978e4481daa83ff41ab62ae1835260baecdb5c77496f02d6d0418eb1171d3.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>说是最新自主研发5.0系统，其实就是RDV2的魔改版，他家利用隔板的空间，集成了变色龙，还在隔板上装了显示屏、按钮，类似手持机的功能，可以不开电脑复制ID卡。</p><p>特色是中文GUI客户端一直在优化，适合小白使用。</p><h4 id="h-mini-chameleonmini" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">变色龙 Mini ,ChameleonMini</h4><p>在网购PM3时，经常可以看到有PM3变色龙一体机卖，当时询问js ,他们也是语焉不详 。所以这里再单独介绍下变色龙是个啥。</p><p>变色龙 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/emsec/ChameleonMini">ChameleonMini</a> 是一款可编程的 NFC 安全分析工具的开源硬件项目，可模拟各种ic卡、侦测密码，可同时储存六组卡片数据随时可以手动切换，体积跟普通卡差不多方便携带。</p><p>ChameleonMini 常见的有两个版本 <strong>ChameleonMini Rev.E</strong> 与 <strong>ChameleonMini Rev.G</strong> 其中 Rev.G 是最新升级的版本，自带电池供电。</p><p>说白了，变色龙就是一张先进的侦测卡，不具备读写功能，需要配合其他读写设备使用。 PM3的现场嗅探功能其实比较弱，集成了变色龙之后就补齐了这个短板。</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">使用</h3><p>中文GUI主要是对43a的IC卡和 低频ID做的支持，对其他协议的卡片都没有支持。</p><p>熟悉基本操作之后，想要探索PM3的魅力还是推荐使用 命令行， 命令行教程汉化可以看RadioWar的wiki <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://wiki.radiowar.org/Proxmark3%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C">RadioWar:Proxmark3命令帮助</a>，其他教程也非常的多，可以自行查找。</p><p>打开方法是进入软件安装目录：</p><pre data-type="codeBlock" text="./prommark3.exe   com4   # com号会变，根据自己实际情况调整
"><code>./prommark3.exe   com4   # com号会变，根据自己实际情况调整
</code></pre><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">参考链接</h2><p>[1]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://proxmark.com/proxmark-3-hardware">Porxmark 官网</a></p><p>[2]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://4hou.win/wordpress/?paged=13&amp;cat=17">智能卡破解入门二三事</a></p><p>[3]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://lzy-wi.github.io/2018/07/26/proxmark3/">Proxmark3 Easy破解门禁卡学习过程</a></p><p>[4]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://cloud.tencent.com/developer/article/1043152">低成本安全硬件 RFID on PN532</a></p><p>[5]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ulyc.github.io/2020/01/18/%E5%B8%B8%E8%A7%81RFID%E5%8D%A1%E7%89%87%E4%BB%8B%E7%BB%8D-%E7%A0%B4%E8%A7%A3%E6%80%9D%E8%B7%AF-%E5%8F%8A-Proxmark3%E7%AE%80%E4%BB%8B/%5Bhttp://read.pudn.com/downloads121/ebook/513161/%E5%90%84%E4%BA%A7%E5%93%81.pdf%5D(http://read.pudn.com/downloads121/ebook/513161/%E5%90%84%E4%BA%A7%E5%93%81.pdf)">非接触IC卡主要产品简介</a></p><p>[6]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://www.card1688.com/smart_card/STMicroelectronics_chip_card.html">STMicroelectronics 芯片卡</a></p><p>[7]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://wenku.baidu.com/view/597156eee009581b6bd9eb3e.html">iCLASS说明文件</a></p><p>[8].<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://www.nfchome.org/nfc-forum-type1-type2-type3-type4.html">[NFC Forum标签平台四种标签类型详细介绍]</a></p><p>[9]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cnblogs.com/sky-heaven/p/4704895.html">初识CPU卡、SAM卡/CPU卡简介、SAM卡简介 【转】</a></p><p>[10]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zhuanlan.zhihu.com/p/81384126">手把手教 如何模拟IC加密卡</a></p><p>[11]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.guhei.net/post/jb1108">IC卡加密解密方式</a></p><p>[12].<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://rdcqii.hundsun.com/portal/article/642.mhtml">除了支付/刷卡还能干嘛？三分钟教你玩转RFID</a></p><p>[13].<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.freebuf.com/vuls/192356.html">使用HackCube-Special分析滚动码信号</a></p><p>[14]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.wasyoung.com/2019/11/30/337/">Proxmark3（PM3）硬件简单拆解与介绍</a></p><p>[15].<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.wasyoung.com/2019/11/30/337/">梯控、IC卡滚动码防复制原理和破解</a></p><p>[16]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://www.ickezhan.com/bbs/forum.php?mod=viewthread&amp;tid=41">简单讨论滚动码技术</a></p><p>[17]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://wiki.radiowar.org/Proxmark3%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C">RadioWar:Proxmark3命令帮助</a></p><p>[18]. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.cert.org.cn/upload/cncertcc06/0330/ct1/5.060330-YuYang-ThreatsFromAir.pdf">来自空中的威胁</a></p><p>[19]. 《非接触IC卡原理与应用》[电子工业出版社 2006-09-01]</p><hr>]]></content:encoded>
            <author>ulyc@newsletter.paragraph.com (ulyc)</author>
        </item>
    </channel>
</rss>