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

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

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

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

加密解密实际上是纯数学的东西。如果把一个需要加密的文件看成是一串数字,比如一个文件由一串数字序列(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 的加密内容分享是无法被解密的,这也加速了全球日益高涨的恐怖威胁。全世界的政府都在要求商业公司提供用户的解密数据,与之相对的是数学领域的加密理论已经远远把监控和破解甩在了身后。我不认为任何公司需要对技术的进步负责,科技的进步是大势所趋,而需要改进的,是那些仍处于落后状态的事物。

Google 的面试流程

在 Google 工作有一段时间了,是时候和大家分享一下 Google 的面试流程,以方便广大求职的同学参考,也顺便给 Google 打个广告。

Google 有一个全球统一的招聘网站:Google Careers。里面不仅有空缺职位的介绍,还有 Google 在世界各地的办公室的介绍,比如这个是我所在的苏黎世办公室

前期准备

在申请 Google 的工作之前,最好对自己想做的工作和对未来的团队有一个期望。比如自己想从事哪个方面的工作,前端还是后端,网络服务还是客户端软件,团队在美国、欧洲或是中国。尽管不论你的目标团队是什么,面试的难度和流程都是统一的,但毕竟将来你要和你的团队长期协同工作,选一个自己喜欢的产品和团队,何乐而不为呢,对吧。

除了选职位之外,面试的基本工也不可少,去 LeetCode 温习一下算法题吧。

递交申请

你可以通过上述的招聘网站递交你的简历,也可以找正在 Google 工作的朋友帮你递交。当然,后者是有好处的,下面会提到。对于应届的同学,也可以留意一下各大高校的招聘活动,应届招聘的人数较多,多数会有统一的线下安排,效率比较高。

面试

面试分为三种:笔试、电话面试和现场面试。

笔试通常是针对应届毕业生,由于人数多,HR 没有办法一个个打电话来面试,只好统一进行笔试。

电话面试,如果你不慎错过了笔试,并且 HR 又看中了你的简历,或是对于社招的求职者,那么你将接到至少一轮的电话面试。电话面试通常需要写代码,如果条件可行,可以通过 Google Docs 实时交流代码;最不济的情况,则是在电话中口述。这个阶段中,HR 也会打电话过来了解一下你的背景,咨询一下你中意的产品和团队,以及你在 Google 有没有认识的朋友。

现场面试,电话面试(或笔试)通过之后,你将会收到现场面试的邀请,地点一般会选在离你最近的办公室。现场面试至少有四轮,每轮一小时,几乎全是技术面试,要求在白板或者纸上写代码。由于内部规定,这些代码会被记录下来交由招聘委员会审阅,所以在白板上写代码的时候,你可能会注意到面试官在积(mang)极(lu)地抄写你的代码。如果面试期间碰到中饭时间,会有面试官带你去吃中饭,顺便感受一下传说中的免费午餐 :P

面试结束之后不会立即知道结果,即使主动询问面试官或者 HR,得到的回复一般都是“等通知”。

审核

所有的面试结果会交给招聘委员会(Hiring Commitee)进行审核。与此同时,HR 会发信给 Google 内部可能是你以前同学或同事的员工,要求他们写评价。这些人的评价也会一起交给招聘委员会作为参考。这时就能体现出之前提到过的内部推荐的好处了,至少有一个人帮你写了评价,聊胜于无。

招聘委员会审核通过之后,结果会交由 Larry Page (和他的团队)过目。是的,你没有看错,CEO 会亲自审阅你的资料。

讨论合同

上述的审核通过之后,HR 就会开始准备发 Offer。它实际是一个套餐(Package),套餐中注明了基础工资,奖金的比例,入职时的股票奖励等。你可以多多少少谈点条件,当然,大公司有着成熟的等级体系,可商量的余地不大。如果你需要搬家(Relocation),Offer 中会包含搬家的补贴,或许会有一个中介(Agent)来协助你完成搬家的过程。

签订合同和入职

最终会有一堆的文件寄给你,一份一份签名之后再寄回(或交予 HR)。

签完合同之后就等着入职吧。这段时间里,你可能需要办签证、搬家等一些琐碎的事情。由于美国签证名额的限制,H1B 签证现在实行的抽签制度,约有三分之一的概率签不出。如果发生这种情况,你可能需要重新签一份合同,并前往另一个地区的办公室,等待最长可能有一年半的时间,再去美国。这个过程称为 Parking。Parking 的地点可以和 HR 商量,比如瑞士、加拿大或者其它地方。为了避免这种尴尬的情况,你也可以不选择美国的职位,其它地区也有很好的办公室和职位。

试用期

和多数公司一样,入职之后的三个月是试用期,试用期内可能会因为能力不行而被解雇。当然这是小概率事件,大多数新员工都可以顺利度过试用期。在试用期满之后,推荐你入职的同学/朋友,可以得到一笔奖金,金额视你的职位高低不同而略有差异。到时候就找他/她请客吧。

完成整个流程之后,恭喜你,你已成为一名 Googler。如有什么问题或者想加入 Google,可以私下联系我。

如何提高电脑的运行速度

随着个人电脑的普及,各种电脑性能优化的歪门邪道也随之而来。尽管我自己不需要这些个所谓的“技巧”,但流言止于智者,写篇博客也可以帮助其他人。

常见的优化误区有那么几类:

清理硬盘,把临时文件甚至 Windows 系统文件都删掉,删得越多,速度越快

实际上,硬盘空间的使用量和电脑的速度并没有直接联系,只要不是完全用满,基本不会影响性能。不论是传统的机械硬盘,还是固态硬盘,硬盘的寻址速度并不取决于已用空间,换言之,不论存放了多少东西,Windows 找寻一个文件所用的时间是一样的。在 XP 的时代,磁盘碎片会降低文件读取的速度,但这一情况在 Windows 7 之后已经显著改善,没有必要经常进行清理了。

安装各种内存优化工具,降低内存使用率,内存用得越少,速度越快

让我们先来看看内存的用处是什么:硬盘的读写速度过慢,CPU 如果直接读写硬盘,则会使电脑非常缓慢,所以就有了内存,夹在当中做缓存之用。内存的读写速度是机械硬盘的十万倍以上,把硬盘的数据预先读取到内存中,再进行后续操作,可以提升电脑的总体运行速度。于是乎,操作系统更倾向于把不用的数据,或者还没用到的数据,暂时先放在内存中,直到用完,或者被其它更高优先级的数据所替代。而内存优化工具所做的事情,就是把这部分暂时不用的数据,从内存中清理出去,造成的结果就是,下一次用到这些数据的时候,操作系统要再去硬盘里读取,反而降低了电脑的运行速度。从另一个角度来说,如果你的电脑有 8G 内存,但你每天都只用其中的 1G 不到,那你买 8G 内存干啥,省点钱买 1G 就行了。

修改 Windows 的深层设置,“提升”速度

每个人使用电脑的方式不同,常用的功能也不尽相同,肯定会有一些设置,可以提升在某些场景下的性能。但这些设置需要按实际情况来调整,并不是使用工具“一键优化”就可以做到的。制作工具的人怎么可能想到每个人不同的需求,把这些需求都做进优化软件中。再说了,如果有一些常用的优化设置,优化软件的开发人员想得到,那 Windows 的开发人员也一定想得到,直接把 Windows 默认设置成优化过的状态不就行了,为何还需要进行二次优化。

那么,提升电脑速度的方式究竟是什么?

很简单,三个字:买买买。

为什么大家常常抱怨 Windows 没有 Mac OS 流畅?是因为 Windows 优化得不好么?显然不是。是因为很多人拿着 2000 元的 Windows 笔记本,去和上万元的 Macbook 去比。即使 Windows 优化得再好,在这种情况下也是比不过 Mac OS 的。不信的话,大可以去整一台万元的 Windows 笔记本,比如著名的 Alienware,再去和 Macbook 比,高下立见。或许多数人对 Alienware 都没什么概念,那我们就换个比喻。2000 元的笔记本,大约就相当于奇瑞 QQ。(2000 元以下的电脑属于二手 QQ。)而 Alienware 就好比宝马 M4,尽管哪辆车开得快还取决于驾驶员,但正常人都不会想着把 QQ 改装成 M4 吧。

既不肯花钱买高档的硬件,又钟情于各种歪门邪道来优化,最终只会适得其反。

HTTP vs HTTPS

今天看到一条新闻,说是银联提醒用户注意网站的https前缀

在识别网络诈骗方面,银联特别提醒任何网购退款均无需提供银行卡密码和CVN2。任何索要短信验证码的行为都是诈骗。在登录网址时,警惕所谓的“安全中心”“认证中心”,不要轻信“低价”购物网站,并警惕通过邮件、短信、聊天工具发来的所谓“安全中心”“认证中心”“担保平台”等钓鱼网站链接。支付时留意“https”前缀。完成网购订单进入支付页面时,网址前缀会变成“https”,表示数据传输加密;若支付页面网址前缀仍是“http”,请提高警惕。

HTTPS是什么,它和我们常用的HTTP有什么不同呢?

传统的HTTP通讯是不安全的,因为在浏览器和服务器之间传输的数据,有可能被中间节点截获。互联网的架构决定了网络通讯都不是点对点直接传输的,一个数据包从客户端发送到服务器的过程中,当中会经过多个节点。通俗点说,数据包会先传到家里的路由器,路由器再发送给它上一级的(可能是电信的)路由器,这么一级一级地传出去,最终传到了服务器端。这个过程中,每一个路由器都有机会截获到传输的内容。如果这些内容中包含了密码等重要信息,就有可能会被坏人所利用。

HTTPS中的S表示安全(Secure),它代表了浏览器和服务器之间的通讯是加密的,不可被第三方获取。由HTTPS协议保证,除非得到服务器端的密钥,否则(几乎)无法破解出通讯的内容。为什么说几乎?因为暴力破解在理论上是有可能的,但是因为现在的计算机性能的限制,暴力破解需要上亿年的时间才能成功,所以说,暂时它是安全的。

那么怎样的HTTPS才算是安全的?以Chrome为例,正常的HTTPS连接会显示为绿色,其它的浏览器里大同小异。如下:

这两种都是正常的,前一种是个人的HTTPS,后一种是企业的。如果浏览器认为HTTPS有问题,它会显示成红色或者灰色,或者弹出对话框来提醒用户。

经过加密之后,基本可以认为是所有数据都是安全的。具体来说,以下这些数据被加密了:

  • URL中的路径、参数;
  • 发送(Post)的数据;
  • 接收的整个页面的数据;

唯一没有被加密的部份是URL中的域名部分。以一个URL为例:

https://www.google.com/search?q=leonax&sourceid=chrome&ie=UTF-8

其中只有www.google.com这一段数据没有加密,其余的/search?....外加网页内容,都是经过加密的。

上文提到的过,本站也支持HTTPS,点击这里试用一下,除了速度稍慢(安全的提升总是与性能的牺牲相关),其它并没有什么与HTTP不同的地方。

软件测试的目标

毕业之后的第一份工作就是软件测试,刚上班不久,就有一位大牛告诫了我一句话:

软件测试的目标不是验证软件的功能是对的,而是验证其功能是符合预期的。

这句看似是文字游戏的话,却蕴含了很多道理。

到目前为止,计算机还不具备思考的能力,它只能按照使用者的指令来运转。计算机没有办法自己推算出一个软件的行为是正确还是错误的,它需要使用者输入额外的数据才能做到这一点。举一个简单的例子,在单元测试(Unit Test)的时候,断言(Assertion)的写法通常是 assertEquals(expected, actual),而不是 assertCorrect(actual)。如果计算机拥有智慧,它就不需要 expected 表达式,只需 assertCorrect。

在日常工作中,预期的行为是需要明确定义的,通常是写在测试计划(Test Plan 或者 Test Spec)中。一份好的测试计划,需要明确定义一系列的软件行为,比如“当XXXX的时候,软件的行为是YYYY”。具体的内容通常来源于产品设计(Design Spec),当然不是照抄,这个以后再说。有了这一系列的定义,测试用例(Test Case)的编写就变得非常简单,也可以避免在后续开发过程中,其他人对测试用例产生的疑问。如果测试计划中只写了“软件可以正确处理XXXX的情况”,由于每个人对“正确”的理解不一样,写出来的测试用例也就各有千秋,软件质量也就不能保证了。

于是,有一些观点认为,专职的测试人员最终会被机器所替代。这显然是不正确的。当机器能自主进行测试的时候,那它也就具备的思考的能力,那是非常可怕的一件事……

Windows还是Linux

先交待一下背景,大学期间,除了课程需要和比赛之外,我基本没有用过Linux。对Linux可以算是一点都不了解。狗屎运的是,毕业后第一家公司对Linux也没什么好感,第二家公司是做广告的,对Linux知识要求也不高。于是就这么稀里糊涂地混了好几年。所以以下言论你可以认为是一面之辞。

言归正传,在大学里需要学习Linux吗?或者再深入一点,需要用Linux来替代Windows吗?

简单来说,完全没必要。除非你打定了主意以后开发Linux软件,或者从事Linux相关行业(我也不知道有没有这类的行业),那可以从大学的时候就开始准备起来。如果你还不确认以后会做什么,或者根本不知道Linux和Windows有什么差异,那基本可以不用专注于Linux,因为两者没什么本质差别,而日常使用显然是Windows有优势,比如国内的网银客户端。

那么为什么似乎身边的同学都对Linux情有独钟呢?我刚进大学的时候,有个同学一脸羡慕地跟我说,"某同学可以自行编译并安装SuSE"。好吧,当年我连SuSE是什么都不知道,装个Windows也需要光盘而不是用硬盘启动那么高深的技能,就更别说“能编译一个OS”那么牛逼的举动了,要知道有一票人连"Hello World"也编译不过……不过回过头来仔细想一下,会装个系统有什么了不起,安装程序是别人写好的,那同学只是按着说明书操作一下罢了。真正牛逼的不是跟着说明书走一遍,而是发现说明书中不合理的地方,然后尝试去改进它。多数人只是止步于如何使用,而不进一步研究一下内部的状况,从何想想如何改进。

回到Windows和Linux的问题上,从操作系统的角度来说,这两者没有本质的差别。操作系统发展了这么多年,该有的大家都有,就大学期间需要掌握的程度,学Windows和学Linux的效果是一样的。只是Windows对于日常使用更方便,所以没有必要在艰难困苦中自欺欺人,大学生活有很多更有意义的事情等着你。

什么是 DNS?

这个问题要从 IP 地址说起。IP 地址相关于网络设备的“门牌号”,每个在连上互联网的设备,都至少有一个 IP 地址。IP 地址的形式有两种,形如 104.155.216.90(IPv4)或者 2a00:1450:4002:804::1003(IPv6)。每个网络设备,包括服务器(网站)、终端用户,都有一个独立的 IP 地址(在使用的时候独立,使用完之后可能会被回收并复用)。

这样就产生了一个问题,IP 地址非常难记,显然 104.155.216.90 没有"leonax.net"好记。于是开发人员就发明了一种把 IP 地址转换成域名的服务。域名就是类似 leonax.net 这样的字符串,俗称网址。这个转换的服务被称为 DNS,全称是 Domain Name System。

DNS 的工作原因大致是这样的:如果终端计算机需要访问 leonax.net,它会先向管理 .net 域名的根 DNS 服务器发向请求,得到负责管理 leonax.net 的 DNS 服务器(假设是 A),然后再发送请求给 A,询问 leonax.net 的 IP 地址,最终得到结果为 104.155.216.90。然后终端计算机的浏览器就可以访问到http://leonax.net了。

根 DNS 服务器在全球一共有 13 个(以及一些镜像),显然这 13 个服务器没有能力响应来世界各地的所有 DNS 请求,于是就有了各种 DNS 缓存技术。通常终端计算机只需连接到最近的一台 DNS 缓存服务器上,如果那台服务器刚好有 leonax.net 的数据,就可以直接告诉终端计算机,而不需要麻烦根服务器。这样就大大地平衡了各个 DNS 服务器之间的负载,也减少了终端设备的等待时间。比如 Google 就开设了两个 DNS 缓存服务器,IP 地址分别为 8.8.8.8 和 8.8.4.4。

至于 DNS 的具体技术细节和实现,请自行 Google……