上次gnupg签名写完后,雨苍跑过来问我gnupg里面的一些细节,讲,为什么不写清楚呢?我说不是写过一篇gnupg基础么?回去翻blog,居然没有!好吧,那就现场写一篇gnupg的基础概念。

非对称密钥

gnupg是一种签名/加密系统,通常而言,多数被用在mail和deb包签署上。普通加密程序的最大区别在于,gnupg是一种公钥/私钥结构。

我们简单点说,你可以用gpg --gen-key生成一个密钥对(是的,一次一对密钥),一个密钥对包含一个公钥和一个私钥。公钥是公布在网络上的,私钥自己持有,并且可以加一个密码,以防私钥泄漏。学过非对称密码体系的同学应该知道,公钥加密,私钥解密,私钥加密,公钥解密。因此,这个密钥对可以用于签署。方法是,对你的目标数据进行哈希,然后使用私钥加密这个哈希,得到签名数据。如果别人可以用你的公钥解密这个签名数据,然后和目标数据的哈希对比,那么这个数据就一定是私钥签署的。

附加资源

下面是最精彩的地方。一个密钥对里面,其实不仅包含一对密钥,而是包含多对。刚刚生成的公钥(pub)和私钥(sec)这对,被称为主密钥。而除去主密钥外,还可以加入三种资源,子密钥,uid,签名。

子密钥是另一个合法的对称或者非对称密钥。子密钥的常见用途是延长密钥的可用期,或者提供不同强度的加密(通常是减弱)。

密钥长期被用于加密数据后,可能会被已知明文攻击,因此一般密钥都有一个合理的使用周期。对于大量加密数据的人来说,这个合理使用周期可能比较短。看过上一篇互相签署的应当知道,对一个密钥每三四年乃至一年就签署一遍太麻烦了。因此,你可以使用子密钥。这个密钥的使用和吊销就比主密钥更加方便,生成一个,用六个月,然后废弃。而使用主密钥签署过的子密钥,同样可以认证该密钥属于某人。

uid则是认证这个人的合理名字,主要是姓名,昵称,邮箱。通过主密钥签署,别人可以认可这个网络身份真实的属于你。

签名则是别人对你的uid的认可。一般一个uid上可以有一个或者多个签名(至少需要自己主密钥的签名)。

常见参数选择

主密钥过期时间,建议选择5-10年,推荐10年。因为主密钥过期后需要重新签署,每三四年就重新签署一遍你的密钥实在是太麻烦了。

主密钥长度,我建议选择你能选择的最长长度。因为主密钥有相当长的过期时间,过短的密钥很快就不实用了。在2000年的时候,1024位还是比较安全的,但是2009年,RSA-768被成功破解,威胁到了1024位密钥的安全性。目前debian推荐密钥都是4096位长。至于对此造成的计算压力增加,你可以通过子密钥来解决。

主密钥一般是RSA的,gpg -k可以看到4096R之类的标示。

公钥的网络管理

上面说到,公钥需要公布在网络上。现在网络上就有一种专门的服务器,用于提供公钥的上传和管理。我用的是pgp.mit.edu,很有名(主要是比较短,好记)。你可以在上面放置一个你的公钥,里面附加各种uid和签名,吊销凭证,等等。

文件签名

密钥对可以对文件进行签署,生成分离的(.sig文件)或者内含的签名。签名方法是gpg -s,你可以用gpg --verify来验证。

FAQ:

Q: 有什么机构对gpg进行认证么?

A: 这个真没有,虽然你可以从公钥服务器上获得很多人的公钥,但你无法确认他们的身份。确认身份唯一可靠的办法就是线下交换fingerprint并且签署。作为替代,完全信任和勉强信任也部分的可靠。

Q: 签署和加密有什么区别?

A: 签署表示这个内容是被你确认过的(由你发出或者经你许可),所有人都能看到。加密表示这个内容只有你能看到,所有人都能发出。如果你打算给一个人发送一个内容,内容是经你确认的,并且只想被他看到。你可以同时签名和加密。

Q: 签名可以伪造么?

A: 这个应该不行,如果可以,你可以写个paper,全球奖金就数百万美元,更不提领域上的名声。

Q: 国家可以调动专用服务器来进行破解。

A: 目前已知破解的最长的密钥是RSA-768,长度768bit,因此1024位密钥有可能被政府机关破解。然而破解难度随着位数增加以几何级数增长,因此2048位的破解目前还遥遥无期。目前而言,2048以上长度的密钥还是无解的。

Q: 真的不行么?我知道各国军队都有保密的研究成果。

A: 如果你相信所谓的“秘密成果”,我也无话可说。仅公共领域流通的成果而言,离可接受的破解方法还差很远。目前已知最好的算法是普通数域筛选法,有希望成为可接受的破解方法的是基于量子计算机的Shor算法——不过量子计算机还没有制造出来。

Q: 既然2048位密钥不可破解,为什么还要选择4096位?

A: 一个不幸的事实是,虽然破解难度随着位数增加几何级数增长,然而破解速度随着时间流逝也在几何级数增长。如果你打算长期使用,还是使用4096位的比较保险。