由快播的庭审说说加密解密的问题

今天是“快播”涉黄案开庭的日子,新浪网直播了庭审全过程,过程中充满了各种欢乐。我们来说说其中的一个:

且不说这位审判员对于法律是多么地无知,用户的文件无论有没有加密都属于个人隐私,能问出这样的问题显然是对隐私保护没有一丁点的认识。

接下来我们从技术的角度来说说,为什么不能解密。

加密解密实际上是纯数学的东西。如果把一个需要加密的文件看成是一串数字,比如一个文件由一串数字序列(A0, A1, A2, ..., An)构成,这个序列可以被人阅读和理解。加密的过程就是把上述 A 序列转换为(B0, B1, B2, ..., Bn),这个 B 序列是完全杂乱无章,看不懂的内容。然后解密就是加密的逆过程,把 B 序列再翻译回 A 序列。这两个转换过程中都需要大量的计算,而计算机的产生使用大规模加密解密成为可能。

加密解密的一个典型应用场景是寄信。比如小张要写一封信给小红,为了防止信件在寄送过程中被别人看到内容,小张可以把信的内容先加密,然后收小红收到信之后再解密,即可确保寄送过程中没有人可以看懂信件的内容。

加密解密的一个重要工具是密钥。密钥的本质也是一串数字序列(C0, C1, C1, ..., Cn),把它和 A 序列以某种方式混合,即可产生 B 序列。然后再把 C 序列和 B 序列以某种方式混合,即可产生 A 序列。这种方式称为对称密钥加密。常见的对称密钥加密方式是 AES,暴力破解 AES 加密需要千百万年的计算时间,因此被认为是安全的。

使用对称密钥加密的前提条件是,传递信息的双方事先要约定一个密钥,有了统一的密钥,才能顺利地加密和解密。我们在谍战剧里经常看到的,战争的一方截获对另一方的密码本,从而监听到了重要的信息。这个密码本,就是这里说的密钥。密钥需要定期更新,否则就有可能被对方暴力破解,或是以其它的方式窃取。

从谍战剧中我们可以看到,对称密钥加密的主要缺点就是,交换密钥不方便。虽然后续的通信都加密了,但是密钥的传输过程中却是公开的。密钥的传输过程成了加密解密中的薄弱环节。

那么有没有办法解决这个问题呢?当然是有的。这种方法称为非对称密钥加密

非对称密钥加密的密钥包含两部分:公钥和私钥,公钥可以公开,私钥需要保密。而非对称密钥加密是一个外人看来很玄乎的东西。先说说它的过程:小张手里有一对公钥 P 和私钥 X,小红手里有一对公钥 Q 和私钥 Y。小红先把自己的公钥 Q 告诉小张。小张使用 Q 和自己的私钥 X 把信件的内容 A 加密成 B,然后把 B 和小张自己的公钥 P 一起告诉小红。然后小红使用自己的私钥 Y 和小张的公钥 P 对加密内容 B 进行解密,即可还原出 A 来。相信看到这里多数人都已经晕了。

具体原理这是不多说,它和素数分解有关。它对于密钥的保护措施是加密的双方只需要交换公钥即可进行加密和解密,而即使公钥被第三个人知道,他也没有办法破解加密过的文本。常见的非对称密钥加密方式是 RSA,暴力破解 RSA 同样也需要千百万年。非对称密钥加密最常见的应用是 HTTPS。这下知道为什么 HTTPS 是安全的了吧。

于是这里就解答了那位审判员的疑惑,为什么不能对用户上传的文件进行解密,因为根本解不开。如果快播的用户在上传视频时使用了非对称加密,下载视频的用户在观看时解密,这个过程中快播是没有办法知道其中的内容的。聊天软件 Telegram 也使用了类似的方式进行端到端的加密,使用聊天内容就连 Telegram 自己也不知道。

和加密相关的另一个技术称为哈希(Hashing),哈希的作用是验证源文本的真实性。举个例子,小张立了一份遗嘱,他显然不需要对这份遗嘱加密,因为遗嘱最终是要公开的。而他要做的是,确保最终公布的那份遗嘱和他最初立下的是一样的。于是小张可以在立下遗嘱的时候对这份遗嘱做一个哈希,在遗嘱公开的时候,对公开的遗嘱再做一次哈希,如果两份哈希码一致,才说明遗嘱没有被改动过。当然这其中还涉及到一些哈希保密的步骤,这里不细说了,大家知道这个意思就可以了。

哈希和加密解密的一个重要区别是,哈希生成的哈希值,是没有办法解密的,就是还原不回去,只能把 A 哈希成 B,不能再从 B 推导出 A。哈希在计算机领域的一个常见用途是保存密码。比如你在某个网站上注册了一个帐号,这个帐号包含用户名和密码。而网站的管理员不希望除了你之外的其它人看到这个密码,于是网站上所保存的内容只是密码的哈希值,而不是密码本身。在你每次登录网站的时候,网站都会对你输入的密码做一次哈希,如果哈希值和网站数据库中存放的一致,则表示你输入的密码正确。而即使有人偷取了网站所保存的哈希值,也没办法还原出密码来,也就不能登录你的帐号。

现在主流的哈希算法是 SHA-2。一个常见的应用场景是两步验证

好了,说了这么多加密解密相关的东西,回过头来说说快播。我没有用过快播的软件,也不太清楚快播对色情视频的打击做到了什么程度。但从技术的角度来看,P2P 的加密内容分享是无法被解密的,这也加速了全球日益高涨的恐怖威胁。全世界的政府都在要求商业公司提供用户的解密数据,与之相对的是数学领域的加密理论已经远远把监控和破解甩在了身后。我不认为任何公司需要对技术的进步负责,科技的进步是大势所趋,而需要改进的,是那些仍处于落后状态的事物。

网易所谓的“EAL 3+”证书是个什么东西?

今天一早,乌云上曝出了网易邮箱的安全问题,过亿的用户信息被泄漏。而网易方面也是反应神速,一份宣传稿发到各大媒体,说是自己家的邮箱不仅没问题,而且安全性方面还是全国最牛X的。公告原文如下(摘自新浪):

文中提到了一个 EAL 3+ 的认证,而且号称是国内最高等级。这个到底是什么呢?我们来研究一下。

网易的企业邮箱网站在今年 8 月底发布了一则新闻,说是企业邮箱系统获得了 EAL 3+ 认证,还有一个像模像样的证书。图片就不贴了,大家点链接进去看吧。证书大意是“网易企业级邮箱系统”获得 中国信息安全评测中心信息安全实验室 颁发的 EAL 3+ 证书。

首先,这个系统的名字有歧义,企业级的邮箱系统,不一定只是给企业用的。网易可以说自家的免费邮箱也做到了企业级的安全性。当然网易算是心虚,没有在自己的首页发表这么个新闻,只是在企业邮箱的网站上发了。那我们只能认为只有网易的企业邮箱获得了这个证书,而大众所使用的免费邮箱却没有。而乌云提到的过亿的用户信息,显然不是从企业邮箱来的。网易在公告中宣称的“国内最安全”,只不过是偷换概念罢了。

当然,不能排除网易内部实际上使用的是同一套系统,即企业邮箱和免费邮箱的后台是一样的,只是页面看上去不一样。那么企业邮箱获得了安全认证,免费邮箱也就同样安全。好吧,然后我又去看了一下 EAL 3+ 的实际内容。

EAL(Evaluation Assurance Level)是某个国际组织设立的标准,按它的实际操作来看,每个国家都可以设立自己的评测实验室,对本国的软件进行评测。中国、美国、英国、法国、西班牙等国都有自己的评测实验室。中国的评测由上面提到的 中国信息安全评测中心信息安全实验室 来进行。在中国信息安全评测中心的网站上,可以找到中文版的 EAL 1 - 5 的评测细节,其中这个链接指向的是 EAL 3 的指南(PDF)。文档我稍微看了一下,实际它只有 20 页不到,大约就是一个对文档细节的约束。其中对于测试文档的要求,只有半页,还没我的一篇博文长。摘录如下:

基本上它就是要求了测试文档的完整性,对于要测哪些方面、具体测试的实施以及测试的结果,通通没有要求。也就是说,只要文档写得好,通过 EAL 评测并不难。而做过产品的同学们都知道,文档和最终产品的差距还是相当大的。举个例子:

另外,网易的证书上还提到了评测方法:GB/T 30270-2013 信息技术 安全技术 信息技术安全性评估方法。我搜索了一下,这个《方法》没有电子版,只有纸制书籍出售,当当网的卖价是 103 元。我自然不会为了写博客还去买本破书,因为当当的介绍中提到,这本书只有 200 多页,目录显示它的内容就是 EAL1 到 EAL5 的实际内容,外加一些前言备注什么的。大致可以看到,书中没有额外的内容,具体的评测和上面给出的 PDF 链接没有两样。

所以实际上,网易获得了证书 和 系统的安全性 这两件事并没有直接联系。而即使是网易获得证书的企业邮箱,它的安全性也令人堪忧:

上图中,即使我选择了“全程使用 SSL”,登录页面也没有使用 SSL。在登录页面不使用 SSL 的情况下,即使登录接口使用了 SSL 也是形同虚设的,因为未加密的登录页面可能被劫持,只需要添加一段脚本,就可以神不知鬼不觉得拿到帐号信息。详细的分析我曾经在乌云看过一篇文章,一下子找不到了,等找到了再补上。

对于那些担心自己密码失窃的同学们,我只能建议一句:保护个人信息,远离网易。当然,如果你在其它网站使用了和网易一样的密码,请立即修改。

写于博客密码泄露之后

很不幸我的博客密码被盗了,一个不名黑客在半夜入侵了我的主机,植入了菜刀,远程控制了机器。然后他窃取了一些重要资料(比如一些羞羞照),并且把主机变成了一台肉机。我发现的时候,肉机已经偷跑了超过 5000 美元的流量......

在电脑手机前偷笑的各位可以稍微停一下了。以上只是我被害妄想症的一种表现,它实际上并没有发生。

由于对安全的偏执,我假想了各种安全漏洞的情形,然后加以防御。之前讨论过 WordPress 的密码安全性插件安全性,这次来探讨一下密码失窃之后,有哪些亡羊补牢的方法。

假设一名黑客偷取了本博客的管理员密码,(先假设只是博客的密码,而不是主机的管理员权限),那么他能做哪些事情?

一,很明显,他可以操作博客的数据库,新建用户、新建文章、删除文章等。

二,黑客可以在后台直接挂马,然后进行更强大的远程操作。

对于第一条,似乎没有特别好的方法,一旦密码被盗,数据库就只能放弃了。当然,如果你的博客没有任何加密的内容,数据库被盗也没什么好怕的,本来就都是公开的东西。

接下来重点说一下第二条。

PHP 有一个很好用也很危险的特性,就是源代码可以直接执行;而 WordPress 也有一个很好的特性,即可以在后台直接修改插件代码。于是一旦黑客控制了后台,他可以在源代码里嵌入一行如下的语句,然后就可以远程控制了。对,PHP 就是那么强大。

要防止这种情况,最有效的方法是在把所有源代码设置为只读,即 Linux 文件属性 400(或 444),这样可以避免任何人对文件进行修改。但这样做之后,自己真想要修改文件的时候,却是非常麻烦,先要 SSH 登录,把文件属性设为可写(如 755),然后再回到后台改文件。另外,这样做也阻止了 WordPress 的自动更新,一定程度上降低了安全性。

对此, WordPress 提供了一个简单的防御方式,可以 wp-config.php 中添加一行:

这样可以禁用掉 WordPress 中修改源代码的界面,包括插件和主题,同时也禁止了安装新的插件和主题。当然这样同样会有上述的问题,即每次修改文件之前,需要先修改 wp-config.php。为了避免对 wp-config.php 的频繁修改,我们可以加一点小小的逻辑,如下:

它的含义是在不是运行 WP Cron 并且 Session 中没有定义 enable_edit 的时候,才禁用对主题和插件的修改。开启 WP Cron 的原因是它会定期检查并更新 WordPress,而 Session 的定义则可以按需开启修改的界面。

手动启用修改界面,还需要一段代码,写在 functions.php 中:

然后访问 http://你的博客地址/wp-admin/admin-ajax.php?action=temp_enable_edit 即可临时开启对插件和主题的修改,有效期到 Session 过期为止。需要注意的是,并不所有的主机都启用了 Session。如果你的主机把 Session 关了,你可以改成使用 Cookie,效果类似。

这种方法是安全和易用的一个折中,它假设了 WordPress 不会有 Bug,比如 DISALLOW_FILE_MODS 工作正常,并且没有安装可以直接运行 PHP 代码的插件

另外还有一些其它的方法仅供参考:

  • 给 wp-admin/ 文件夹加一个密码,比如 Apache 的 Basic Authentication。我觉得每次登录都需要多输一个密码,实在太麻烦了。
  • 重命名 wp-admin/ 文件夹让别人找不到。根据前几年的讨论贴,这种方法并不能完美工作,也就说是 WordPress 的代码某种程度上依赖于 wp-admin 而不能改名。
  • 创建一个新的域名,只用来访问 wp-admin,而原先的域名供访客浏览。这种方法的前提是你愿意支付双倍的 SSL 证书费用。

这个世界上没有绝对的安全,只不持之以恒的防御。

HTTPS 证书简介

HTTPS,全称是“超文本传输安全协议”,是一种加密的网络通信技术。其中的“安全”,由 TLS(或者 SSL)协议提供。作为用户,我们不必了解 HTTPS、TLS 和 SSL 之间的关系,当我们在谈论网页浏览的时候,这三个术语通常指的是同一个东西。

使用了 HTTPS 加密的网站(比如本站),用户在访问网站的时候,所有的通讯都是被加密的,只有用户的浏览器和网站服务器知道真实的内容,通讯过程中所有的中间节点(路由器、网关等)都无法进行破解,从而保证了浏览过程的安全性。在访问 HTTPS 的网站时,浏览器通常会显示一个绿色或者加锁的图标,表示安全,看一下你的浏览器地址栏,是不是这个样子的?

HTTPS 的工作原理,简单来说就是网站服务器提供了一个证书 A,这个证书可由一个第三方机构的证书 B 来验证其真伪,而这个证书 B 会默认存放在用户的操作系统中。当用户访问网站时,浏览器会获得证书 A 的信息,然后拿本机中已有的证书 B 来验证,如果验证成功,则开始使用证书 A 进行加密通讯。于是,对网站主的要求就是,在一个权威机构获取一个合适的证书。

HTTPS 的证书有分为几类:普通、多域名、通配(Wildcard)、扩展验证以及多域名扩展验证,以下就来一一介绍:

普通证书:只对单一域名有效,在申请的时候需要指定域名,比如本站的证书,就是指定了 leonax.net 作为认证域名,当这个证书用于其它域名如 abc.leonax.net 的时候,浏览器就是给出警告:域名和证书不匹配。

多域名证书:在申请的时候可以指定多个域名,并且域名只对这一系列域名有效。

通配证书:俗称“野卡”。可使用通配符来指定域名,比如 *.leonax.net,这样所有的子域名都可以使用这个证书,适用于子域名多,又不想一个一个单独申请证书的网站。

扩展验证证书:和上述个人证书不同,扩展验证证书只颁发给企业用户,其“扩展验证”的含义就是验证了企业的合法性。有了企业的名声做后盾,这网站的安全性就更上一层楼了。此外,为了突出公司的重要性,浏览器一般会体现出扩展验证证书的公司信息,比如下图是访问 DigiCert 时看到的样子:

多域名扩展验证证书:普通的扩展验证证书只支持单一域名,多域名证书可以提供多个域名的扩展验证。需要注意的是,和上述的个人证书不同,扩展验证证书没有通配证书这一选项。

一个 SSL 证书的有效期通常为一年,最长可以申请到三年,过期之后要去第三方机构续签证书。这个过程是为了避免证书被盗之后的风险,也就是即合证书被盗了,别人也只能使用最多一年时间,从而减少了损失。一些大公司为了安全,只使用有效期为半年的证书。

如果你对 HTTPS 已动心,本站推荐 DigiCert 作为 SSL 证书提供商。

DIY 博客域名解析(三)DNSSEC

DNSSEC,全称是 Domain Name System Security Extensions,它是一个 DNS 解析过程中的安全机制,用来保护 DNS 解析不被污染。传统的 DNS 解析依赖于服务器之间的信任,比如客户端 A 向服务器 B 查询 leonax.net 的 IP 地址,A 会完全信任 B 的应答;在这种情况下,如果 B 故意返回了一个错误的 IP 地址,A 就上当了,用户就无法正常访问本站了。在现实生活中,谁最爱干这种事,大家都很清楚了。

有了 DNSSEC 之后,Zone 的记录列表中会多一些项目,这些项目可以被用来验证服务器 B 返回的数据是否有效。如果客户端 A 在进行 DNS 查询的时候,发现 B 返回的数据不能通过 DNSSEC 的验证,则会抛弃这些数据,直接跳过 B 向权威 Name Server 发送请求。这样虽然查询的时间略长,但至少得到的数据是正确的,用户不会被误导到钓鱼网站去。

配置 DNSSEC 只需要在主服务器中改动,从属服务器则不需要太大的修改。

启用 DNSSEC

在 /etc/bind/named.conf.options 文件中添加下列参数,这些参数同样需要在从属服务器中添加:

创建 Zone Sign Key 文件

如果你的主机上没有安装 haveged,这个过程可能需要很少时间;如果装了的话,则瞬间完成。完成之后,会有类似如下的输出:

创建 Key Sign Key 文件

输出样例:

在 Zone 文件中添加上述的 Key 文件

上述两个命令会在当前文件夹下生成类似如下四个文件:
Kleonax.net.+007+40400.key
Kleonax.net.+007+40400.private
Kleonax.net.+007+62910.key
Kleonax.net.+007+62910.private

把这些文件复制到 /etc/bind/ 目录下,并在 db.leonax.net 文件中添加如下几行,注意文件名要和实际生成的文件名一致:

创建加密的 Zone 文件

这个命令会生成一个新文件:/etc/bind/db.leonax.net.signed,需要修改 /etc/bind/named.conf.local 来使用这个文件:

需要注意的是,db.leonax.net.signed 是一个自动生成的文件,不太方便修改,如果之后需要添加或删除记录,还是要修改 db.leonax.net,然后再次运行 dnssec-signzone 工具生成 .signed 文件。

检验配置文件

重启 bind9 之后,可以能过 dig 工具来验证 DNSSEC 已经启用:

样例输出:

更新 DS 记录

dnssec-signzone 工具会在当前目录下生成一个名为 dsset-leonax.net. 的文件,这个文件中包含了两条 DS 记录。

这两条记录需要在域名注册商那里更新。DS 记录的格式为 <Tag> <Algorithm> <Digest Type> <Digest>,在域名注册商那里一一填进去即可。需要注意的是,第二条记录最后一个空格是不需要的,即实际的 Digest 为“198303E265A856DE8FE6330EDB5AA76F3537C10783151AEF3577859FFFC3F59D”。

修改 bind9 的 UDP 输出大小

某些主机商限制了 UDP 通信的字节数(MTU),在使用了 DNSSEC 之后,bind9 的 UDP 包可能会被防火墙拦截掉,从而导致 DNS 查询失败。在这种情况下,要求修改防火墙设置,要么在 /etc/bind/named.conf.options 文件中添加如下参数:

通常防火墙的 MTU 设置为 1500,这里设置成 1024 就可以保证 UDP 通信不被防火墙拦截掉。

第三方检验工具

可以使用 VeriSign 提供的检验工具,或者 DNSViz 来检验,如果没有任何警告(Warning)或者错误(Error),则说明 DNSSEC 配置成功了。

强制使用 HTTPS

Github 再一次受到攻击,和之前的攻击方式不一样,这一次,Github 被普通网民给 DDos 了。

攻击的大致原理是这样的,百度广告联盟所使用的一个 Javascript 文件被篡改,其中嵌入了一段代码,会每两秒钟给 Github 发送一次请求。由于国内很多网站都使用了百度广告联盟,一旦用户访问这些网站,这些用户的浏览器就开始自动攻击 Github。这一度造成了 Github 的服务瘫痪,一天之后才采取措施修复。具体细节可以查看乌云的一篇文章

至于这是谁干的?大家应该都知道的吧。百度自己是不会砸自己场子的,而对 Github 有仇的,只有我们可爱的防火墙了。

之前我们印象中的 GFW 只是一个屏蔽工具,使得我们无法访问一些网站,而这一次 GFW 的升级可谓是令人恐惧的,因为它具备了修改文件的能力。这种攻击方式为称为“中间人攻击”,比方说,你在和朋友聊天的时候,并没有直接和他对话,而是通过一个中间人传话,那么这个中间人,就有了篡改你们对话能力。这次对于百度广告联盟的修改,表面上并没有让用户察觉到被墙了,但实际却发动了一次前所未有的 DDos 攻击。GFW 可以修改百度的文件,也自然可以修改其它网站的文件。如果下次它直接修改了 jQuery 的源文件,以 jQuery 普及程度,这种 DDos 的强度是大多数网站承受不了的。

作为对策之一,本站开启了 HSTS 以应对可能的中间人攻击。HSTS 是一项浏览器技术,网站通过一个特殊的报头(Header)告诉浏览器,建议浏览器使用 HTTPS 进行访问,在极大程度上避免了中间人攻击。在使用了 HTTPS 之后,你和本站的通讯,只有网站服务器和你的浏览器知道,网络上的各种路由器,包括墙,都无法得知,从而也就不能进行攻击了。

另外我也建议,上网的时候请尽可能地选择 HTTPS 的网站,即地址栏前面有一个小锁,表示当前浏览的网站是安全的。

给 WordPress 添加双重密码

昨天检查服务器日志的时候,发现有一个 IP 在不停地尝试破解博客的管理员密码,即发送数据给 wp-login.php。看上去他坚持不懈,尝试了至少两天,每五秒钟左右就尝试一次。当然我知道那是一个自动化的工具在尝试破解,并不是有人手工一个一个地输密码,但这样真的有意义么?

不过,既然有人想破解,那防御一下还是必要的。Wordpress 自带的密码管理是基于哈希(Hash)的,有哈希就有碰撞,即便使用了很长的密码,如果哈希值不够长的话,碰撞机率会增加,从而减小了密码的安全性。于是我就增加了一个额外的密码。这个密码被明文保存,无法被碰撞破解。当然,用户需要同时输对两个密码才可以登录。

改动的代码如下:

以上代码在登录框中增加一项“L-Value”,想看效果的同学请移步登录页面自行查看。

以上代码接收“L-Value”的值并进行检查,如果它的值不是“Password12345”,即认为登录不功能。

这样做的好处是增加了一层防御,和防止垃圾评论一样,如果“L-Value”的值不对,黑客根本无法破解真正的密码。这么做可以抵御常规的 WordPress 破解程序,如果哪天 WordPress 的登录逻辑出了 bug,黑客也破解不了我的博客。

当然坏处也是有的,如果你的博客是由多人同时管理,这个机制不能很好地工作,如果需要为每个人单独设定不同的密码,这样的明文保存的方式就不行了。