数字证书原理

文中首先解释了加密解密的一些基础知识和概念,然后通过一个加密通信过程的例子说明了加密算法的作用,以及数字证书的出现所起的作用。接着对数字证书做一个详细的解释,并讨论一下windows中数字证书的管理,最后演示使用makecert生成数字证书。如果发现文中有错误的地方,或者有什么地方说得不够清楚,欢迎指出!

 

1、基础知识

这部分内容主要解释一些概念和术语,最好是先理解这部分内容。

1.1、公钥密码体制(public-key cryptography)

公钥密码体制分为三个部分,公钥、私钥、加密解密算法,它的加密解密过程如下:

  • 加密:通过加密算法和公钥对内容(或者说明文)进行加密,得到密文。加密过程需要用到公钥。
  • 解密:通过解密算法和私钥对密文进行解密,得到明文。解密过程需要用到解密算法和私钥。注意,由公钥加密的内容,只能由私钥进行解密,也就是说,由公钥加密的内容,如果不知道私钥,是无法解密的。

公钥密码体制的公钥和算法都是公开的(这是为什么叫公钥密码体制的原因),私钥是保密的。大家都以使用公钥进行加密,但是只有私钥的持有者才能解密。在实际的使用中,有需要的人会生成一对公钥和私钥,把公钥发布出去给别人使用,自己保留私钥。

 

1.2、对称加密算法(symmetric key algorithms)

在对称加密算法中,加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥。因此对称加密算法要保证安全性的话,密钥要做好保密,只能让使用的人知道,不能对外公开。这个和上面的公钥密码体制有所不同,公钥密码体制中加密是用公钥,解密使用私钥,而对称加密算法中,加密和解密都是使用同一个密钥,不区分公钥和私钥。

 

// 密钥,一般就是一个字符串或数字,在加密或者解密时传递给加密/解密算法。前面在公钥密码体制中说到的公钥、私钥就是密钥,公钥是加密使用的密钥,私钥是解密使用的密钥。

1.3、非对称加密算法(asymmetric key algorithms)

在非对称加密算法中,加密使用的密钥和解密使用的密钥是不相同的。前面所说的公钥密码体制就是一种非对称加密算法,他的公钥和是私钥是不能相同的,也就是说加密使用的密钥和解密使用的密钥不同,因此它是一个非对称加密算法。

 

1.4、RSA简介

RSA是一种公钥密码体制,现在使用得很广泛。如果对RSA本身有兴趣的,后面看我有没有时间写个RSA的具体介绍。

RSA密码体制是一种公钥密码体制,公钥公开,私钥保密,它的加密解密算法是公开的。 由公钥加密的内容可以并且只能由私钥进行解密,并且由私钥加密的内容可以并且只能由公钥进行解密。也就是说,RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密

 

1.5、签名和加密

我们说加密,是指对某个内容加密,加密后的内容还可以通过解密进行还原。 比如我们把一封邮件进行加密,加密后的内容在网络上进行传输,接收者在收到后,通过解密可以还原邮件的真实内容。

这里主要解释一下签名,签名就是在信息的后面再加上一段内容,可以证明信息没有被修改过,怎么样可以达到这个效果呢?一般是对信息做一个hash计算得到一个hash值,注意,这个过程是不可逆的,也就是说无法通过hash值得出原来的信息内容。在把信息发送出去时,把这个hash值加密后做为一个签名和信息一起发出去。 接收方在收到信息后,会重新计算信息的hash值,并和信息所附带的hash值(解密后)进行对比,如果一致,就说明信息的内容没有被修改过,因为这里hash计算可以保证不同的内容一定会得到不同的hash值,所以只要内容一被修改,根据信息内容计算的hash值就会变化。当然,不怀好意的人也可以修改信息内容的同时也修改hash值,从而让它们可以相匹配,为了防止这种情况,hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。至于如何让别人可以解密这个签名,这个过程涉及到数字证书等概念,我们后面在说到数字证书时再详细说明,这里您先只需先理解签名的这个概念。

 

2、一个加密通信过程的演化

我们来看一个例子,现在假设“服务器”和“客户”要在网络上通信,并且他们打算使用RSA(参看前面的RSA简介)来对通信进行加密以保证谈话内容的安全。由于是使用RSA这种公钥密码体制,“服务器”需要对外发布公钥(算法不需要公布,RSA的算法大家都知道),自己留着私钥。“客户”通过某些途径拿到了“服务器”发布的公钥,客户并不知道私钥。“客户”具体是通过什么途径获取公钥的,我们后面再来说明,下面看一下双方如何进行保密的通信:

 

2.1 第一回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:????

因为消息是在网络上传输的,有人可以冒充自己是“服务器”来向客户发送信息。例如上面的消息可以被黑客截获如下:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“黑客”:你好        // 黑客在“客户”和“服务器”之间的某个路由器上截获“客户”发给服务器的信息,然后自己冒充“服务器”

“黑客”->“客户”:你好,我是服务器

因此“客户”在接到消息后,并不能肯定这个消息就是由“服务器”发出的,某些“黑客”也可以冒充“服务器”发出这个消息。如何确定信息是由“服务器”发过来的呢?有一个解决方法,因为只有服务器有私钥,所以如果只要能够确认对方有私钥,那么对方就是“服务器”。因此通信过程可以改进为如下:

 

2.2 第二回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

// 意这里约定一下,{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,例如上面的 {你好,我是服务器}[私钥|RSA]  就表示用私钥对“你好,我是服务器”进行加密后的结果。

为了向“客户”证明自己是“服务器”, “服务器”把一个字符串用自己的私钥加密,把明文和加密后的密文一起发给“客户”。对于这里的例子来说,就是把字符串 “你好,我是服务器”和这个字符串用私钥加密后的内容 {你好,我是服务器}[私钥|RSA] 发给客户。

“客户”收到信息后,她用自己持有的公钥解密密文,和明文进行对比,如果一致,说明信息的确是由服务器发过来的。也就是说“客户”把 {你好,我是服务器}[私钥|RSA] 这个内容用公钥进行解密,然后和“你好,我是服务器”对比。因为由“服务器”用私钥加密后的内容,由并且只能由公钥进行解密,私钥只有“服务器”持有,所以如果解密出来的内容是能够对得上的,那说明信息一定是从“服务器”发过来的。

假设“黑客”想冒充“服务器”:

“黑客”->“客户”:你好,我是服务器

“客户”->“黑客”:向我证明你就是服务器

“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[???|RSA]    //这里黑客无法冒充,因为他不知道私钥,无法用私钥加密某个字符串后发送给客户去验证。

“客户”->“黑客”:????

由于“黑客”没有“服务器”的私钥,因此它发送过去的内容,“客户”是无法通过服务器的公钥解密的,因此可以认定对方是个冒牌货!

到这里为止,“客户”就可以确认“服务器”的身份了,可以放心和“服务器”进行通信,但是这里有一个问题,通信的内容在网络上还是无法保密。为什么无法保密呢?通信过程不是可以用公钥、私钥加密吗?其实用RSA的私钥和公钥是不行的,我们来具体分析下过程,看下面的演示:

 

2.3 第三回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[公钥|RSA]

“服务器”->“客户”:{你的余额是100元}[私钥|RSA]

注意上面的的信息 {你的余额是100元}[私钥],这个是“服务器”用私钥加密后的内容,但是我们之前说了,公钥是发布出去的,因此所有的人都知道公钥,所以除了“客户”,其它的人也可以用公钥对{你的余额是100元}[私钥]进行解密。所以如果“服务器”用私钥加密发给“客户”,这个信息是无法保密的,因为只要有公钥就可以解密这内容。然而“服务器”也不能用公钥对发送的内容进行加密,因为“客户”没有私钥,发送个“客户”也解密不了。

这样问题就又来了,那又如何解决呢?在实际的应用过程,一般是通过引入对称加密来解决这个问题,看下面的演示:

 

2.4 第四回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

“客户”->“服务器”:{我们后面的通信过程,用对称加密来进行,这里是对称加密算法和密钥}[公钥|RSA]    //蓝色字体的部分是对称加密的算法和密钥的具体内容,客户把它们发送给服务器。

“服务器”->“客户”:{OK,收到!}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你的余额是100元}[密钥|对称加密算法]

在上面的通信过程中,“客户”在确认了“服务器”的身份后,“客户”自己选择一个对称加密算法和一个密钥,把这个对称加密算法和密钥一起用公钥加密后发送给“服务器”。注意,由于对称加密算法和密钥是用公钥加密的,就算这个加密后的内容被“黑客”截获了,由于没有私钥,“黑客”也无从知道对称加密算法和密钥的内容。

由于是用公钥加密的,只有私钥能够解密,这样就可以保证只有服务器可以知道对称加密算法和密钥,而其它人不可能知道(这个对称加密算法和密钥是“客户”自己选择的,所以“客户”自己当然知道如何解密加密)。这样“服务器”和“客户”就可以用对称加密算法和密钥来加密通信的内容了。

 

总结一下,RSA加密算法在这个通信过程中所起到的作用主要有两个:

  • 因为私钥只有“服务器”拥有,因此“客户”可以通过判断对方是否有私钥来判断对方是否是“服务器”。
  • 客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法和密钥来保证后面通信过程内容的安全。

如果这里您理解了为什么不用RSA去加密通信过程,而是要再确定一个对称加密算法来保证通信过程的安全,那么就说明前面的内容您已经理解了。(如果不清楚,再看下2.3和2.4,如果还是不清楚,那应该是我们说清楚,您可以留言提问。)

到这里,“客户”就可以确认“服务器”的身份,并且双方的通信内容可以进行加密,其他人就算截获了通信内容,也无法解密。的确,好像通信的过程是比较安全了。

 

但是这里还留有一个问题,在最开始我们就说过,“服务器”要对外发布公钥,那“服务器”如何把公钥发送给“客户”呢?我们第一反应可能会想到以下的两个方法:

a)把公钥放到互联网的某个地方的一个下载地址,事先给“客户”去下载。

b)每次和“客户”开始通信时,“服务器”把公钥发给“客户”。

但是这个两个方法都有一定的问题,

对于a)方法,“客户”无法确定这个下载地址是不是“服务器”发布的,你凭什么就相信这个地址下载的东西就是“服务器”发布的而不是别人伪造的呢,万一下载到一个假的怎么办?另外要所有的“客户”都在通信前事先去下载公钥也很不现实。

对于b)方法,也有问题,因为任何人都可以自己生成一对公钥和私钥,他只要向“客户”发送他自己的私钥就可以冒充“服务器”了。示意如下:

“客户”->“黑客”:你好           //黑客截获“客户”发给“服务器”的消息

“黑客”->“客户”:你好,我是服务器,这个是我的公钥    //黑客自己生成一对公钥和私钥,把公钥发给“客户”,自己保留私钥

“客户”->“黑客”:向我证明你就是服务器

“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[黑客自己的私钥|RSA]      //客户收到“黑客”用私钥加密的信息后,是可以用“黑客”发给自己的公钥解密的,从而会误认为“黑客”是“服务器”

因此“黑客”只需要自己生成一对公钥和私钥,然后把公钥发送给“客户”,自己保留私钥,这样由于“客户”可以用黑客的公钥解密黑客的私钥加密的内容,“客户”就会相信“黑客”是“服务器”,从而导致了安全问题。这里问题的根源就在于,大家都可以生成公钥、私钥对,无法确认公钥对到底是谁的。 如果能够确定公钥到底是谁的,就不会有这个问题了。例如,如果收到“黑客”冒充“服务器”发过来的公钥,经过某种检查,如果能够发现这个公钥不是“服务器”的就好了。

为了解决这个问题,数字证书出现了,它可以解决我们上面的问题。先大概看下什么是数字证书,一个证书包含下面的具体内容:

  • 证书的发布机构
  • 证书的有效期
  • 公钥
  • 证书所有者(Subject)
  • 签名所使用的算法
  • 指纹以及指纹算法

证书的内容的详细解释会在后面详细解释,这里先只需要搞清楚一点,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。至于是如何判断的,后面会在详细讨论数字证书时详细解释。现在把前面的通信过程使用数字证书修改为如下:

 

2.5 第五回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书        //这里用证书代替了公钥

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

注意,上面第二次通信,“服务器”把自己的证书发给了“客户”,而不是发送公钥。“客户”可以根据证书校验这个证书到底是不是“服务器”的,也就是能校验这个证书的所有者是不是“服务器”,从而确认这个证书中的公钥的确是“服务器”的。后面的过程和以前是一样,“客户”让“服务器”证明自己的身份,“服务器”用私钥加密一段内容连同明文一起发给“客户”,“客户”把加密内容用数字证书中的公钥解密后和明文对比,如果一致,那么对方就确实是“服务器”,然后双方协商一个对称加密来保证通信过程的安全。到这里,整个过程就完整了,我们回顾一下:

 

2.6 完整过程:

step1: “客户”向服务端发送一个通信请求

“客户”->“服务器”:你好

step2: “服务器”向客户发送自己的数字证书。证书中有一个公钥用来加密信息,私钥由“服务器”持有

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书

 

step3: “客户”收到“服务器”的证书后,它会去验证这个数字证书到底是不是“服务器”的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是“服务器”的。检查数字证书后,“客户”会发送一个随机的字符串给“服务器”用私钥去加密,服务器把加密的结果返回给“客户”,“客户”用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是“服务器”。

“客户”->“服务器”:向我证明你就是服务器,这是一个随机字符串     //前面的例子中为了方便解释,用的是“你好”等内容,实际情况下一般是随机生成的一个字符串。

“服务器”->“客户”:{一个随机字符串}[私钥|RSA]

 

step4: 验证“服务器”的身份后,“客户”生成一个对称加密算法和密钥,用于后面的通信的加密和解密。这个对称加密算法和密钥,“客户”会用公钥加密后发送给“服务器”,别人截获了也没用,因为只有“服务器”手中有可以解密的私钥。这样,后面“服务器”和“客户”就都可以用对称加密算法来加密和解密通信内容了。

“服务器”->“客户”:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你好,你的余额是100元}[密钥|对称加密算法]

…… //继续其它的通信

 

2.7 其它问题:

上面的过程已经十分接近HTTPS的真实通信过程了,完全可以按照这个过程去理解HTTPS的工作原理。但是我为了方便解释,上面有些细节没有说到,有兴趣的人可以看下这部分的内容。可以跳过不看,无关紧要。

 

【问题1】

上面的通信过程中说到,在检查完证书后,“客户”发送一个随机的字符串给“服务器”去用私钥加密,以便判断对方是否真的持有私钥。但是有一个问题,“黑客”也可以发送一个字符串给“服务器”去加密并且得到加密后的内容,这样对于“服务器”来说是不安全的,因为黑客可以发送一些简单的有规律的字符串给“服务器”加密,从而寻找加密的规律,有可能威胁到私钥的安全。所以说,“服务器”随随便便用私钥去加密一个来路不明的字符串并把结果发送给对方是不安全的。

〖解决方法〗

每次收到“客户”发来的要加密的的字符串时,“服务器”并不是真正的加密这个字符串本身,而是把这个字符串进行一个hash计算,加密这个字符串的hash值(不加密原来的字符串)后发送给“客户”,“客户”收到后解密这个hash值并自己计算字符串的hash值然后进行对比是否一致。也就是说,“服务器”不直接加密收到的字符串,而是加密这个字符串的一个hash值,这样就避免了加密那些有规律的字符串,从而降低被破解的机率。“客户”自己发送的字符串,因此它自己可以计算字符串的hash值,然后再把“服务器”发送过来的加密的hash值和自己计算的进行对比,同样也能确定对方是否是“服务器”。

 

【问题2】

在双方的通信过程中,“黑客”可以截获发送的加密了的内容,虽然他无法解密这个内容,但是他可以捣乱,例如把信息原封不动的发送多次,扰乱通信过程。

〖解决方法〗

可以给通信的内容加上一个序号或者一个随机的值,如果“客户”或者“服务器”接收到的信息中有之前出现过的序号或者随机值,那么说明有人在通信过程中重发信息内容进行捣乱,双方会立刻停止通信。有人可能会问,如果有人一直这么捣乱怎么办?那不是无法通信了? 答案是的确是这样的,例如有人控制了你连接互联网的路由器,他的确可以针对你。但是一些重要的应用,例如军队或者政府的内部网络,它们都不使用我们平时使用的公网,因此一般人不会破坏到他们的通信。

 

【问题3】

在双方的通信过程中,“黑客”除了简单的重复发送截获的消息之外,还可以修改截获后的密文修改后再发送,因为修改的是密文,虽然不能完全控制消息解密后的内容,但是仍然会破坏解密后的密文。因此发送过程如果黑客对密文进行了修改,“客户”和“服务器”是无法判断密文是否被修改的。虽然不一定能达到目的,但是“黑客”可以一直这样碰碰运气。

〖解决方法〗

在每次发送信息时,先对信息的内容进行一个hash计算得出一个hash值,将信息的内容和这个hash值一起加密后发送。接收方在收到后进行解密得到明文的内容和hash值,然后接收方再自己对收到信息内容做一次hash计算,与收到的hash值进行对比看是否匹配,如果匹配就说明信息在传输过程中没有被修改过。如果不匹配说明中途有人故意对加密数据进行了修改,立刻中断通话过程后做其它处理。

 

3. 证书的构成和原理
3.1 证书的构成和原理

之前已经大概说了一个证书由什么构成,但是没有仔细进行介绍,这里对证书的内容做一个详细的介绍。先看下一个证书到底是个什么东西,在windows下查看一个证书时,界面是这样的,我们主要关注一下Details Tab页,其中的内容比较长,我滚动内容后后抓了三个图,把完整的信息显示出来:

certificateDetails_thumb

 

文中首先解释了加密解密的一些基础知识和概念,然后通过一个加密通信过程的例子说明了加密算法的作用,以及数字证书的出现所起的作用。接着对数字证书做一个详细的解释,并讨论一下windows中数字证书的管理,最后演示使用makecert生成数字证书。如果发现文中有错误的地方,或者有什么地方说得不够清楚,欢迎指出!

 

1、基础知识

这部分内容主要解释一些概念和术语,最好是先理解这部分内容。

1.1、公钥密码体制(public-key cryptography)

公钥密码体制分为三个部分,公钥、私钥、加密解密算法,它的加密解密过程如下:

  • 加密:通过加密算法和公钥对内容(或者说明文)进行加密,得到密文。加密过程需要用到公钥。
  • 解密:通过解密算法和私钥对密文进行解密,得到明文。解密过程需要用到解密算法和私钥。注意,由公钥加密的内容,只能由私钥进行解密,也就是说,由公钥加密的内容,如果不知道私钥,是无法解密的。

公钥密码体制的公钥和算法都是公开的(这是为什么叫公钥密码体制的原因),私钥是保密的。大家都以使用公钥进行加密,但是只有私钥的持有者才能解密。在实际的使用中,有需要的人会生成一对公钥和私钥,把公钥发布出去给别人使用,自己保留私钥。

 

1.2、对称加密算法(symmetric key algorithms)

在对称加密算法中,加密使用的密钥和解密使用的密钥是相同的。也就是说,加密和解密都是使用的同一个密钥。因此对称加密算法要保证安全性的话,密钥要做好保密,只能让使用的人知道,不能对外公开。这个和上面的公钥密码体制有所不同,公钥密码体制中加密是用公钥,解密使用私钥,而对称加密算法中,加密和解密都是使用同一个密钥,不区分公钥和私钥。

 

// 密钥,一般就是一个字符串或数字,在加密或者解密时传递给加密/解密算法。前面在公钥密码体制中说到的公钥、私钥就是密钥,公钥是加密使用的密钥,私钥是解密使用的密钥。

1.3、非对称加密算法(asymmetric key algorithms)

在非对称加密算法中,加密使用的密钥和解密使用的密钥是不相同的。前面所说的公钥密码体制就是一种非对称加密算法,他的公钥和是私钥是不能相同的,也就是说加密使用的密钥和解密使用的密钥不同,因此它是一个非对称加密算法。

 

1.4、RSA简介

RSA是一种公钥密码体制,现在使用得很广泛。如果对RSA本身有兴趣的,后面看我有没有时间写个RSA的具体介绍。

RSA密码体制是一种公钥密码体制,公钥公开,私钥保密,它的加密解密算法是公开的。 由公钥加密的内容可以并且只能由私钥进行解密,并且由私钥加密的内容可以并且只能由公钥进行解密。也就是说,RSA的这一对公钥、私钥都可以用来加密和解密,并且一方加密的内容可以由并且只能由对方进行解密

 

1.5、签名和加密

我们说加密,是指对某个内容加密,加密后的内容还可以通过解密进行还原。 比如我们把一封邮件进行加密,加密后的内容在网络上进行传输,接收者在收到后,通过解密可以还原邮件的真实内容。

这里主要解释一下签名,签名就是在信息的后面再加上一段内容,可以证明信息没有被修改过,怎么样可以达到这个效果呢?一般是对信息做一个hash计算得到一个hash值,注意,这个过程是不可逆的,也就是说无法通过hash值得出原来的信息内容。在把信息发送出去时,把这个hash值加密后做为一个签名和信息一起发出去。 接收方在收到信息后,会重新计算信息的hash值,并和信息所附带的hash值(解密后)进行对比,如果一致,就说明信息的内容没有被修改过,因为这里hash计算可以保证不同的内容一定会得到不同的hash值,所以只要内容一被修改,根据信息内容计算的hash值就会变化。当然,不怀好意的人也可以修改信息内容的同时也修改hash值,从而让它们可以相匹配,为了防止这种情况,hash值一般都会加密后(也就是签名)再和信息一起发送,以保证这个hash值不被修改。至于如何让别人可以解密这个签名,这个过程涉及到数字证书等概念,我们后面在说到数字证书时再详细说明,这里您先只需先理解签名的这个概念。

 

2、一个加密通信过程的演化

我们来看一个例子,现在假设“服务器”和“客户”要在网络上通信,并且他们打算使用RSA(参看前面的RSA简介)来对通信进行加密以保证谈话内容的安全。由于是使用RSA这种公钥密码体制,“服务器”需要对外发布公钥(算法不需要公布,RSA的算法大家都知道),自己留着私钥。“客户”通过某些途径拿到了“服务器”发布的公钥,客户并不知道私钥。“客户”具体是通过什么途径获取公钥的,我们后面再来说明,下面看一下双方如何进行保密的通信:

 

2.1 第一回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:????

因为消息是在网络上传输的,有人可以冒充自己是“服务器”来向客户发送信息。例如上面的消息可以被黑客截获如下:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“黑客”:你好        // 黑客在“客户”和“服务器”之间的某个路由器上截获“客户”发给服务器的信息,然后自己冒充“服务器”

“黑客”->“客户”:你好,我是服务器

因此“客户”在接到消息后,并不能肯定这个消息就是由“服务器”发出的,某些“黑客”也可以冒充“服务器”发出这个消息。如何确定信息是由“服务器”发过来的呢?有一个解决方法,因为只有服务器有私钥,所以如果只要能够确认对方有私钥,那么对方就是“服务器”。因此通信过程可以改进为如下:

 

2.2 第二回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

// 意这里约定一下,{} 表示RSA加密后的内容,[ | ]表示用什么密钥和算法进行加密,后面的示例中都用这种表示方式,例如上面的 {你好,我是服务器}[私钥|RSA]  就表示用私钥对“你好,我是服务器”进行加密后的结果。

为了向“客户”证明自己是“服务器”, “服务器”把一个字符串用自己的私钥加密,把明文和加密后的密文一起发给“客户”。对于这里的例子来说,就是把字符串 “你好,我是服务器”和这个字符串用私钥加密后的内容 {你好,我是服务器}[私钥|RSA] 发给客户。

“客户”收到信息后,她用自己持有的公钥解密密文,和明文进行对比,如果一致,说明信息的确是由服务器发过来的。也就是说“客户”把 {你好,我是服务器}[私钥|RSA] 这个内容用公钥进行解密,然后和“你好,我是服务器”对比。因为由“服务器”用私钥加密后的内容,由并且只能由公钥进行解密,私钥只有“服务器”持有,所以如果解密出来的内容是能够对得上的,那说明信息一定是从“服务器”发过来的。

假设“黑客”想冒充“服务器”:

“黑客”->“客户”:你好,我是服务器

“客户”->“黑客”:向我证明你就是服务器

“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[???|RSA]    //这里黑客无法冒充,因为他不知道私钥,无法用私钥加密某个字符串后发送给客户去验证。

“客户”->“黑客”:????

由于“黑客”没有“服务器”的私钥,因此它发送过去的内容,“客户”是无法通过服务器的公钥解密的,因此可以认定对方是个冒牌货!

到这里为止,“客户”就可以确认“服务器”的身份了,可以放心和“服务器”进行通信,但是这里有一个问题,通信的内容在网络上还是无法保密。为什么无法保密呢?通信过程不是可以用公钥、私钥加密吗?其实用RSA的私钥和公钥是不行的,我们来具体分析下过程,看下面的演示:

 

2.3 第三回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[公钥|RSA]

“服务器”->“客户”:{你的余额是100元}[私钥|RSA]

注意上面的的信息 {你的余额是100元}[私钥],这个是“服务器”用私钥加密后的内容,但是我们之前说了,公钥是发布出去的,因此所有的人都知道公钥,所以除了“客户”,其它的人也可以用公钥对{你的余额是100元}[私钥]进行解密。所以如果“服务器”用私钥加密发给“客户”,这个信息是无法保密的,因为只要有公钥就可以解密这内容。然而“服务器”也不能用公钥对发送的内容进行加密,因为“客户”没有私钥,发送个“客户”也解密不了。

这样问题就又来了,那又如何解决呢?在实际的应用过程,一般是通过引入对称加密来解决这个问题,看下面的演示:

 

2.4 第四回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

“客户”->“服务器”:{我们后面的通信过程,用对称加密来进行,这里是对称加密算法和密钥}[公钥|RSA]    //蓝色字体的部分是对称加密的算法和密钥的具体内容,客户把它们发送给服务器。

“服务器”->“客户”:{OK,收到!}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你的余额是100元}[密钥|对称加密算法]

在上面的通信过程中,“客户”在确认了“服务器”的身份后,“客户”自己选择一个对称加密算法和一个密钥,把这个对称加密算法和密钥一起用公钥加密后发送给“服务器”。注意,由于对称加密算法和密钥是用公钥加密的,就算这个加密后的内容被“黑客”截获了,由于没有私钥,“黑客”也无从知道对称加密算法和密钥的内容。

由于是用公钥加密的,只有私钥能够解密,这样就可以保证只有服务器可以知道对称加密算法和密钥,而其它人不可能知道(这个对称加密算法和密钥是“客户”自己选择的,所以“客户”自己当然知道如何解密加密)。这样“服务器”和“客户”就可以用对称加密算法和密钥来加密通信的内容了。

 

总结一下,RSA加密算法在这个通信过程中所起到的作用主要有两个:

  • 因为私钥只有“服务器”拥有,因此“客户”可以通过判断对方是否有私钥来判断对方是否是“服务器”。
  • 客户端通过RSA的掩护,安全的和服务器商量好一个对称加密算法和密钥来保证后面通信过程内容的安全。

如果这里您理解了为什么不用RSA去加密通信过程,而是要再确定一个对称加密算法来保证通信过程的安全,那么就说明前面的内容您已经理解了。(如果不清楚,再看下2.3和2.4,如果还是不清楚,那应该是我们说清楚,您可以留言提问。)

到这里,“客户”就可以确认“服务器”的身份,并且双方的通信内容可以进行加密,其他人就算截获了通信内容,也无法解密。的确,好像通信的过程是比较安全了。

 

但是这里还留有一个问题,在最开始我们就说过,“服务器”要对外发布公钥,那“服务器”如何把公钥发送给“客户”呢?我们第一反应可能会想到以下的两个方法:

a)把公钥放到互联网的某个地方的一个下载地址,事先给“客户”去下载。

b)每次和“客户”开始通信时,“服务器”把公钥发给“客户”。

但是这个两个方法都有一定的问题,

对于a)方法,“客户”无法确定这个下载地址是不是“服务器”发布的,你凭什么就相信这个地址下载的东西就是“服务器”发布的而不是别人伪造的呢,万一下载到一个假的怎么办?另外要所有的“客户”都在通信前事先去下载公钥也很不现实。

对于b)方法,也有问题,因为任何人都可以自己生成一对公钥和私钥,他只要向“客户”发送他自己的私钥就可以冒充“服务器”了。示意如下:

“客户”->“黑客”:你好           //黑客截获“客户”发给“服务器”的消息

“黑客”->“客户”:你好,我是服务器,这个是我的公钥    //黑客自己生成一对公钥和私钥,把公钥发给“客户”,自己保留私钥

“客户”->“黑客”:向我证明你就是服务器

“黑客”->“客户”:你好,我是服务器 {你好,我是服务器}[黑客自己的私钥|RSA]      //客户收到“黑客”用私钥加密的信息后,是可以用“黑客”发给自己的公钥解密的,从而会误认为“黑客”是“服务器”

因此“黑客”只需要自己生成一对公钥和私钥,然后把公钥发送给“客户”,自己保留私钥,这样由于“客户”可以用黑客的公钥解密黑客的私钥加密的内容,“客户”就会相信“黑客”是“服务器”,从而导致了安全问题。这里问题的根源就在于,大家都可以生成公钥、私钥对,无法确认公钥对到底是谁的。 如果能够确定公钥到底是谁的,就不会有这个问题了。例如,如果收到“黑客”冒充“服务器”发过来的公钥,经过某种检查,如果能够发现这个公钥不是“服务器”的就好了。

为了解决这个问题,数字证书出现了,它可以解决我们上面的问题。先大概看下什么是数字证书,一个证书包含下面的具体内容:

  • 证书的发布机构
  • 证书的有效期
  • 公钥
  • 证书所有者(Subject)
  • 签名所使用的算法
  • 指纹以及指纹算法

证书的内容的详细解释会在后面详细解释,这里先只需要搞清楚一点,数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方的身份。也就是说,我们拿到一个数字证书,我们可以判断出这个数字证书到底是谁的。至于是如何判断的,后面会在详细讨论数字证书时详细解释。现在把前面的通信过程使用数字证书修改为如下:

 

2.5 第五回合:

“客户”->“服务器”:你好

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书        //这里用证书代替了公钥

“客户”->“服务器”:向我证明你就是服务器

“服务器”->“客户”:你好,我是服务器 {你好,我是服务器}[私钥|RSA]

注意,上面第二次通信,“服务器”把自己的证书发给了“客户”,而不是发送公钥。“客户”可以根据证书校验这个证书到底是不是“服务器”的,也就是能校验这个证书的所有者是不是“服务器”,从而确认这个证书中的公钥的确是“服务器”的。后面的过程和以前是一样,“客户”让“服务器”证明自己的身份,“服务器”用私钥加密一段内容连同明文一起发给“客户”,“客户”把加密内容用数字证书中的公钥解密后和明文对比,如果一致,那么对方就确实是“服务器”,然后双方协商一个对称加密来保证通信过程的安全。到这里,整个过程就完整了,我们回顾一下:

 

2.6 完整过程:

step1: “客户”向服务端发送一个通信请求

“客户”->“服务器”:你好

step2: “服务器”向客户发送自己的数字证书。证书中有一个公钥用来加密信息,私钥由“服务器”持有

“服务器”->“客户”:你好,我是服务器,这里是我的数字证书

 

step3: “客户”收到“服务器”的证书后,它会去验证这个数字证书到底是不是“服务器”的,数字证书有没有什么问题,数字证书如果检查没有问题,就说明数字证书中的公钥确实是“服务器”的。检查数字证书后,“客户”会发送一个随机的字符串给“服务器”用私钥去加密,服务器把加密的结果返回给“客户”,“客户”用公钥解密这个返回结果,如果解密结果与之前生成的随机字符串一致,那说明对方确实是私钥的持有者,或者说对方确实是“服务器”。

“客户”->“服务器”:向我证明你就是服务器,这是一个随机字符串     //前面的例子中为了方便解释,用的是“你好”等内容,实际情况下一般是随机生成的一个字符串。

“服务器”->“客户”:{一个随机字符串}[私钥|RSA]

 

step4: 验证“服务器”的身份后,“客户”生成一个对称加密算法和密钥,用于后面的通信的加密和解密。这个对称加密算法和密钥,“客户”会用公钥加密后发送给“服务器”,别人截获了也没用,因为只有“服务器”手中有可以解密的私钥。这样,后面“服务器”和“客户”就都可以用对称加密算法来加密和解密通信内容了。

“服务器”->“客户”:{OK,已经收到你发来的对称加密算法和密钥!有什么可以帮到你的?}[密钥|对称加密算法]

“客户”->“服务器”:{我的帐号是aaa,密码是123,把我的余额的信息发给我看看}[密钥|对称加密算法]

“服务器”->“客户”:{你好,你的余额是100元}[密钥|对称加密算法]

…… //继续其它的通信

 

2.7 其它问题:

上面的过程已经十分接近HTTPS的真实通信过程了,完全可以按照这个过程去理解HTTPS的工作原理。但是我为了方便解释,上面有些细节没有说到,有兴趣的人可以看下这部分的内容。可以跳过不看,无关紧要。

 

【问题1】

上面的通信过程中说到,在检查完证书后,“客户”发送一个随机的字符串给“服务器”去用私钥加密,以便判断对方是否真的持有私钥。但是有一个问题,“黑客”也可以发送一个字符串给“服务器”去加密并且得到加密后的内容,这样对于“服务器”来说是不安全的,因为黑客可以发送一些简单的有规律的字符串给“服务器”加密,从而寻找加密的规律,有可能威胁到私钥的安全。所以说,“服务器”随随便便用私钥去加密一个来路不明的字符串并把结果发送给对方是不安全的。

〖解决方法〗

每次收到“客户”发来的要加密的的字符串时,“服务器”并不是真正的加密这个字符串本身,而是把这个字符串进行一个hash计算,加密这个字符串的hash值(不加密原来的字符串)后发送给“客户”,“客户”收到后解密这个hash值并自己计算字符串的hash值然后进行对比是否一致。也就是说,“服务器”不直接加密收到的字符串,而是加密这个字符串的一个hash值,这样就避免了加密那些有规律的字符串,从而降低被破解的机率。“客户”自己发送的字符串,因此它自己可以计算字符串的hash值,然后再把“服务器”发送过来的加密的hash值和自己计算的进行对比,同样也能确定对方是否是“服务器”。

 

【问题2】

在双方的通信过程中,“黑客”可以截获发送的加密了的内容,虽然他无法解密这个内容,但是他可以捣乱,例如把信息原封不动的发送多次,扰乱通信过程。

〖解决方法〗

可以给通信的内容加上一个序号或者一个随机的值,如果“客户”或者“服务器”接收到的信息中有之前出现过的序号或者随机值,那么说明有人在通信过程中重发信息内容进行捣乱,双方会立刻停止通信。有人可能会问,如果有人一直这么捣乱怎么办?那不是无法通信了? 答案是的确是这样的,例如有人控制了你连接互联网的路由器,他的确可以针对你。但是一些重要的应用,例如军队或者政府的内部网络,它们都不使用我们平时使用的公网,因此一般人不会破坏到他们的通信。

 

【问题3】

在双方的通信过程中,“黑客”除了简单的重复发送截获的消息之外,还可以修改截获后的密文修改后再发送,因为修改的是密文,虽然不能完全控制消息解密后的内容,但是仍然会破坏解密后的密文。因此发送过程如果黑客对密文进行了修改,“客户”和“服务器”是无法判断密文是否被修改的。虽然不一定能达到目的,但是“黑客”可以一直这样碰碰运气。

〖解决方法〗

在每次发送信息时,先对信息的内容进行一个hash计算得出一个hash值,将信息的内容和这个hash值一起加密后发送。接收方在收到后进行解密得到明文的内容和hash值,然后接收方再自己对收到信息内容做一次hash计算,与收到的hash值进行对比看是否匹配,如果匹配就说明信息在传输过程中没有被修改过。如果不匹配说明中途有人故意对加密数据进行了修改,立刻中断通话过程后做其它处理。

 

3. 证书的构成和原理
3.1 证书的构成和原理

之前已经大概说了一个证书由什么构成,但是没有仔细进行介绍,这里对证书的内容做一个详细的介绍。先看下一个证书到底是个什么东西,在windows下查看一个证书时,界面是这样的,我们主要关注一下Details Tab页,其中的内容比较长,我滚动内容后后抓了三个图,把完整的信息显示出来:

2009121816032340

 

上面的步骤结束后,会又弹出一个对话框,里面有三个单选按钮如下:

  • My user account
  • Service account
  • Computer account

可以选择第一或者第三个选项,用来查看当前用户的证书或整个计算里面安装的证书。我们这里就默认选择第一个,平时一般安装证书的时候都会给所有用户安装,所以选择第一个和第三个选项看到的证书会差不多。我们在左边的导航树中选中受信任的证书发布机构(Trusted Root Certificate Authorities),然后点击下面的证书(Certificates),在右边的区域中就可以看到所有的受信任的证书发布机构的证书。

trustedcaAuth_thumb

 

注意上面的图片中,右边我们选中的这个证书发布机构”SecureTrust CA”,我们前面在第3章3.2节中举例子的时候,就是去向这个证书发布机构申请的证书,由于我们申请的证书是这个机构发布的,所以应用程序在检查我们的证书的发布机构时(会检查我们证书的签名,确认是该机构发布的证书),就会发现是可以信任的证书发布机构,从而就会相信我们证书的真实性。

删除数字证书很简单,直接在右边的列表中右键然后删除就可以了。

数字证书的安装也比较简单,直接双击数字证书文件,会打开数字证书,对话框下面会有一个Install Certificate按钮,点击后就可以根据向导进行安装,如下图所示:

installCertificate_thumb_1

这个证书是我自己生成的测试证书,在证书的导入向导里面,它会让你选择导入到什么位置,如果是一个我们自己信任的证书发布机构自己的证书,只要导入到Certificate Authorities就可以了。Trusted Root Certificate Authorities, Intermediate Certification Authorities, Third-Party Root Certification Authorities 都是可以的,他们只是对证书的发布机构做了一个分类,还有一些其它的证书类型,例如Personal(个人证书)等等,具体就不介绍了。安装的时候一般来说可以用默认的选择项一直”下一步”到底。

4.2 如何自己创建证书

每个证书发布机构都有自己的用来创建证书的工具,当然,具体他们怎么去创建一个证书的我也不太清楚,不同类型的证书都有一定的格式和规范,我没有仔细去研究过这部分内容。 微软为我们提供了一个用来创建证书的工具makecert.exe,在安装Visual Studio的时候会安装上。如果没有安装也无所谓,可以上网去下一个,搜索makecert就可以了。可以直接从我的博客下载,这是链接

向一些正规的证书发布机构申请证书一般是要收费的(因为别人要花时间检查你的身份,确认有没有同名的证书等等),这里我们看下如何自己创建一个证书,为后面在IIS中配置Https做准备。

我们用到的是makecert这个工具,微软有很详细的使用帮助,我这里只做一个简单的解释,详细的各种参数和使用方法请查看MSDN的makecert的帮助。但是里面有些参数说得不够清楚,而且还有遗漏的,可以参看我后面的解释作为一个补充。

 

先看下makecert最简单的使用方式:

makecert.exe test.cer

上面的命令会在makecert.exe所在的目录生成一个证书文件test.cer的数字证书文件。可以双击证书打开,看看证书的内容如下:

testCertificate1_thumb (1)

证书的发布机构是”Root Agency”,证书的主题(证书发布给谁)是”Joe’s-Software-Emporium”,因为我们没有指定把证书发布给谁,makecert自己给我们随便生成了一个公司的名字。另外还指定了公钥、签名算法(用来解密签名)、指纹和指纹算法等。

注意,因为这个证书是由微软的工具生成的,严格来说它没什么发布机构,所以微软虚拟了一个叫做”Root Agency”的发布机构,默认情况下,windows里面安装了这个所谓的证书发布机构的证书,但是这证书默认情况下不是受信任的,原因很简单,这样做大家都可以用makecert来制作合法的数字证书了。如果我们自己硬是要,也可以把它设置为受信任的。

 

下面我们看下其它的参数,比如我们要给网站 www.jefferysun.com 生成一个证书MyCA.cer,假设我们把makecert.exe放在C:盘下,命令行如下:

makecert -r -pe -n “CN=10.30.146.206″ -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp “Microsoft RSA SChannel Cryptographic Provider” -sy 12

C:\> makecert.exe –pe -r  –n  “CN=www.jefferysun.com” -ss my -sr LocalMachine -a sha1 -len 2048  MyCA.cer

解释一下makecert的常用参数的意思:

  • -n 指定主题的名字,这个是有固定的格式的, CN=主题名字 ,CN应该是Certificate Name的缩写。我这里的主题的名字就是我们的IIS所在机器的IP。这里可以指定一些主题的其它附加信息,例如 O= *** 表示组织信息等等。
  • -r 创建自签署证书,意思就是说在生成证书时,将证书的发布机构设置为自己。
  • -pe 将所生成的私钥标记为可导出。注意,服务器发送证书给客户端的时候,客户端只能从证书里面获取公钥,私钥是无法获取的。如果我们指定了这个参数,证书在安装在机器上后,我们还可以从证书中导出私钥,默认情况下是不能导出私钥的。正规的途径发布的证书,是不可能让你导出私钥的。
  • -b –e 证书的有效期
  • -ss 证书的存储名称,就是windows证书存储区的目录名,如果不存在在的话就创建一个。
  • -sr 证书的存储位置,只有currentuser(默认值)或 localmachine两个值。
  • -sv 指定保存私钥的文件,文件里面除了包含私钥外,其实也包含了证书。这个文件是需要保密的,这个文件在服务端配置时是需要用到的。
  • 这个CN=10.30.146.206要与自己的服务器相对应,要不然在配置HTTPS的时候会出现错误
  • -a 指定签名算法,必须是md5或rsa1。(还记得签名算法的作用不?可以看一下3章的第1节中关于签名算法的介绍)
  • -in 指定证书发布机构的名称
  • -len 这个参数在中文的帮助文档中好像没有提到,但是这个其实很重要,用于指定公钥的位数,越大越安全,默认值是1024,推荐2048。我试了下,这个不为1024的倍数也是可以的。

生成证书后可以进行安装,安装过程可以参看4.1节。

数字证书原理,首发于博客 – 伯乐在线

Android新漏洞曝光:黑客可假冒正规应用

周二发布的一份研究报告显示,谷歌Android操作系统存在一项安全漏洞,可以让黑客假冒受信任的正规应用,从而劫持用户的智能手机或平板电脑。

安全公司Bluebox Security在报告中表示,根本问题在于Android校验应用身份时采取的方式。

验证身份是网络世界中最根本的问题之一。例如,登录银行账号的人是否是该账号的所有者?某款应用是否真如其所宣称的那样?总部位于旧金山的Bluebox的主要业务是帮助企业保护其移动设备上的数据安全,因此该公司的员工正在研究和了解移动操作系统的架构。

每一款Android应用都有自己的数字签名,也就是ID卡。例如,Adobe(72.27, -0.43, -0.59%)公司在Android上有一个指定签名,而该公司开发的所有程序都有一个基于该签名的ID。但Bluebox却发现,当一款应用亮出Adobe ID时,Android不会却向Adobe核实该ID的真实性。

换句话说,网络犯罪分子可以利用假冒的Adobe签名来开发恶意软件,从而感染用户的系统。当然,该问题并不局限于Adobe:黑客还可以创建一个假冒谷歌钱包的恶意应用,然后访问用户的支付账号和财务数据。系统管理软件也会存在同样的问题,使得黑客能够控制整个系统。

Bluebox表示,该问题会影响到2010年1月发布的Android 2.1系统及更高版本,但最近的Android 4.4奇巧系统已经修复了与Adobe有关的漏洞。

但受影响的设备依然数量庞大,根据美国市场研究公司Gartner的测算,2012至2013年间,新出货的Android设备高达14亿部,预计今年的出货量还将增加11.7亿部。

“我们感谢Bluebox的认真负责,感谢他们将问题报告给我们。第三方研究一直是Android系统进步的方式之一。”谷歌发言人克里斯多夫·凯特萨罗斯(Christopher Katsaros)说。

此次问题凸显出安全研究人员与谷歌对安全漏洞的处理方式,但也表明这类问题十分复杂:不仅需要谷歌方面的协调,还需要众多开发者和设备制造商的配合。

Bluebox表示,该公司在今年3月末完成了这项研究,并在3月31日将漏洞提交给谷歌。Android安全团队于今年4月开发了一个解决方案,并提交给了相关厂商。因此,在Bluebox发布研究结果前,这些企业有90天的时间修补该漏洞。Bluebox已经在大约6300款Android设备中挑选了大约40款进行测试,但似乎只有一家厂商修补了该漏洞。

谷歌发言人凯特萨罗斯表示,该公司已经通过改进Google Play和Verify Apps来提升安全性,让用户免受虚假ID问题的影响。

“我们已经扫描了所有提交给Google Play的应用,以及谷歌谷歌在Google Play之外评估的应用,目前没有发现任何证据显示,有人试图利用该漏洞。”凯特萨罗斯说。

Bluebox计划在下周的黑帽黑客大会上讨论这一问题,预计在此之前还将出现更多与安全问题有关的新闻。(鼎宏)

Android新漏洞曝光:黑客可假冒正规应用,首发于博客 – 伯乐在线

一比特之差:无需利用漏洞的DNS劫持

Bitsquatting表示去注册一个域名,它和知名的域名只有一个bit的差别。这个单词源自typosquatting,意为注册一个和知名域名只有一字之差的域名。在解析域名时,bitsquatting可能通过DNS导致计算机上的硬件错误。关于bitsquatting更详细的信息,可以参看我的Blackhat 2011 whitepaper。YouTube上有人发布了我在DEF CON 19上有关此话题的演讲视频,当时使用的幻灯片可以在这里下载

引言

计算机常常由于一个或多比特的内存损坏出现错误,而造成这些错误的原因可能是制造上的缺陷或者宇宙射线、高温之类的环境因素。虽然单个机器中出现这样的错误的可能性是极小的,但是整个互联网上设备的总量却非常庞大:2010年时就有大约50亿个设备连接到互联网。我们可以将这种存在于各个设备上的小概率错误更加形象地描述,那就是买彩票。赢得头奖的概率是极小的,但是只要有足够多的人去买,总有人会成为赢家。

研究人员之前就在很多惊人的地方利用了比特错误(bit-errors)。现在,在互联网尺度上,我们又有新的办法去利用它。Bitsquatting是其中之一,也就是注册和某个常被访问的域名仅一比特之差的新域名。

工作原理

当比特错误发生时,内存中的数据会被修改。计算机内存的内容可能代表各种意义,有时,它刚好就表示域名。如果程序使用这块内存,就会读取到错误的域名。

下面的图解能够更清楚的说明这个问题,表中是cnn.com的二进制表示方法:

01100011 01101110 0110111 0101110 01100011 01101111 01101101
c n n . c o m

现在假设你使用的计算机含有损坏的内存模块,你打开一个包含超链接到cnn.com的网页,然后你点击了这个链接。会有多少个操作将cnn.com的二进制数据保存到你的内存?写这篇文章时,我想到了下面这些:

  • TCP/IP协议栈由核心态向用户态转化时(根据操作系统的具体实现各有区别)
  • 在浏览器解析HTML时
  • 在创建DOM树的内部表示时
  • 在创建新的HTTP请求时
  • 在操作系统解析域名时

更进一步,假设其中有一次将域名写入到了损坏的内存模块,它的二进制形式被修改了1bit,现在表示为:

01100011 01101111 0110111 0101110 01100011 01101111 01101101
c o n . c o m

 这样一来,当你点击链接时,浏览器将会跳转到con.com,而不是cnn.com。

实验

这个实验背后的概念很简单:如果比特错误确实改变了设备内存中的域名,那么这些设备会访问到和正确域名一比特之差的bitsquat域名。因此很多频繁解析的域名的bitsquat域名会被全球各地的设备访问到。

然而这个实验实施起来却没有那么容易,首要的问题是选择合适的域名来进行比特修改。流行的网站和常被解析的域名是不太相同的,很多鲜为人知的域名实际上会被频繁解析。这类域名一般属于内容分发网络或者广告网络,例如fbcdn.net,、2mdn.net和 akamai.com。由于很少有人实际在浏览器中输入这些域名,它们也成为本次实验中最合适的目标。还有个问题就是每次DNS查询必须有两次响应:一次是原本的域名,一次是经过比特修改的域名。因为原始的请求可能会得到正确域名的响应,而丢弃对无效域名的响应。这方面更多的信息,请参考白皮书或者幻灯片

为了这次实验我注册了下面这些域名。

注:目前它们全都已经过期,不再属于我了。

Bitsquat Domain Original Domain
ikamai.net akamai.net
aeazon.com amazon.com
a-azon.com amazon.com
amazgn.com amazon.com
microsmft.com microsoft.com
micrgsoft.com microsoft.com
miarosoft.com microsoft.com
iicrosoft.com microsoft.com
microsnft.com microsoft.com
mhcrosoft.com microsoft.com
eicrosoft.com microsoft.com
mic2osoft.com microsoft.com
micro3oft.com microsoft.com
li6e.com live.com
0mdn.net 2mdn.net
2-dn.net 2mdn.net
2edn.net 2mdn.net
2ldn.net 2mdn.net
2mfn.net 2mdn.net
2mln.net 2mdn.net
2odn.net 2mdn.net
6mdn.net 2mdn.net
fbbdn.net fbcdn.net
fbgdn.net fbcdn.net
gbcdn.net fbcdn.net
fjcdn.net fbcdn.net
dbcdn.net fbcdn.net
roop-servers.net root-servers.net
doublechick.net doubleclick.net
do5bleclick.net doubleclick.net

我使用Python脚本应答DNS请求,并且使用Apache记录HTTP请求。令我惊讶的是,有设备连接了。

实验发现

以下结论是基于2010年9月26日至2011年5月5日间的Apache日志得出的。由搜索引擎爬虫和Web漏洞扫描器引起的日志已经被手动过滤了。正因为是手动操作,所以最后统计时可能还有很小一部分漏网之鱼。

发现1:比特错误可以被利用在DNS上

在记录日志期间总共有52317次针bitsquat域名的请求,它们来自与12949个独立IP。除去其中3次产生巨大网络流量的事件,平均每天有59个独立IP对32个bitsquat域名进行了请求。这些请求不是来自于拼写错误或者其他形式的手工输入URL,还有一部分表现出有多个比特错误的特征。以下是一些实际的例子(个人信息已经移除):

static.ak.fjcdn.net 109.242.50.xxx “GET /rsrc.php/z67NS/hash/4ys0envq.js HTTP/1.1″ “http://www.facebook.com/profile.php?id=xxxxxxxxxx” “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; GTB6.5; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.2; Hotbar 11.0.78.0; OfficeLiveConnector.1.5; OfficeLivePatch.1.3; AskTbZTV/5.8.0.12304)”

msgr.dlservice.mic2osoft.com 213.178.224.xxx “GET /download/A/6/1/A616CCD4-B0CA-4A3D-B975-3EDB38081B38/ar/wlsetup-cvr.exe HTTP/1.1″ 404 268 “Microsoft BITS/6.6″

s0.2ldn.net 66.82.9.xxx “GET /879366/flashwrite_1_2.js HTTP/1.1″ “http://webmail.satx.rr.com/_uac/adpage.html” “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPNTDF; AskTB5.2)”

mmv.admob.com 109.175.185.xxx “GET /static/iphone/img/app@2x.png HTTP/1.1″ “Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; HW iPhone2,1; en_gb) AppleWebKit/525.18.1 (KHTML, like Gecko) (AdMob-iSDK-20101108; iphoneos4.2)”

发现2:并不是所有的比特错误都造成同等程度的影响

有些机器相比其他而言,明显控制着更多的网络流量。当一个比特错误发生在普通PC机或者手机上时,它只会影响到一个用户。然而当它发生在代理、DNS服务器或者数据库缓存中时,将会影响到成千上万的用户。在我的实验中,已经观察到了比特错误出现在Web应用、DNS解析服务器和代理服务器中。例如,一个比特错误将fbcnd.net变为fbbdn.net,将使上千个开心农场的玩家请求到我的服务器。

发现3:手机和嵌入式设备可能比传统硬件受的影响更大

我对2011年3月期间访问Wikipedia和bitsquat域名的HTTP User-Agent进行了对比,展示在下面的图例中。其中Other包括了各种手机、游戏机控制台和其他嵌入式设备,它们在对bitsquat域名的访问中,增加的幅度最大。令人好奇的是,来自MacOS针对bitsquat域名的访问相比Wikipedia有显著减少,对此我还没有一个合理的解释。(译注:这里是按两个域名各自的设备分布算的,其中有增多必然有减少,也许分别计算每种设备访问错域名的几率更加合理,即访问错误域名的次数 / 对两种域名的访问总数。)

bitsquat_1

发现4:对bitsquat域名的访问流量是日常网络流量的真实写照

Bitsquat域名的访问者来自于全球各地,其使用的设备也几乎涵盖每种主流的操作系统和嵌入式平台。除使用MacOS的访问者所占的百分比在两种域名间有显著差别之外,使用Windows、Linux、Android和iPhones的百分比基本相同。另外,基于IP地理位置数据库,我们可以观察到来自于美国的访问者在一天内的流量走势。


bitsquat_2

发现5:HTTPS/TLS不会有帮助,DNSSEC可能会有一丁点

HTTP 1.1在头中包含了一个叫Host的字段,其数值是客户端想要访问的域名。如果Host中包含着bitsquat域名,那么比特错误在域名解析前就发生了。如果Host中是原始域名,那么错误就是发生在域名解析中。我数据中96%的情况是在DNS解析前就出现了比特错误。

bitsquat_3

像SSL和TLS这种安全传输技术是用于保证两端之间数据的机密性、真实性和完整性,但是比特错误更多发生在数据在某一端还未传输的时候。DNSSEC只能解决那4%发生在域名解析过程中的比特错误。

数据

DNS流量的全部PCAP在此:dnslogs.tar.7z,56Mb

HTTP日志可能包含个人信息,因此不会公开发布。如果你有正当的研究目的需要它们,请联系我

这里有个工具可以快速识别潜在的bitsquat域名:bitsquat.pygithub

进一步研究

来自Verisign的Duane Wessels也在DNS查询中寻找过网络级别的比特错误,他指出“网络中比特错误相对而言是很少见的,但是有一个可预期的概率”。他研究的主要目的,是确定那4%发生在域名解析时的比特错误是否由UDP包在传输后的损坏造成。结论是网络中传输的包不太可能被损坏,用他自己的话说:“我们相信UDP的校验和能够有效防范bitsquat攻击或者其他DNS查询时的错误。无论如何,在进入网络前发生的比特错误不会从中受益,因为在传输前计算的校验和是基于错误的数据得出的。“

我非常鼓励读者重复我的实验,并且分享你们的结果。如果需要更多信息,请随时联系我

一比特之差:无需利用漏洞的DNS劫持,首发于博客 – 伯乐在线

树莓派的联合创始人访谈——我们是怎么让大家都成为DIY黑客的

 

请记住它是为喜欢折腾的人准备的只要35美元的计算机

173429zobbos2f2nf2znw1

 

我永远不会忘记我第一次看到树莓派的情形。那个小巧的,信用卡大小的计算机,性能却足够强劲,可以作为一般家用PC,媒体中心,电视游戏机,或是其他任何你能够想像的东西。只有35美元的价格,它是任何年龄段的动手爱好者都可以拥有的小东西,可以在上面捣腾硬件和软件试验,而不用担心会弄坏昂贵的家庭电脑。

Eben Upton,是树莓派基金会的共同创始人,通常被誉为这个神奇机器背后的魔法师。在剑桥大学的计算机实验室攻读哲学博士学位的时候,他费尽苦心地手工打造了树莓派的原型机。

如今,Upton是树莓派基金会下面贸易公司的CEO,监督着树莓派的生产和销售,目前销量已经达到250万台。

天上的派

ReadWrite网: 一开始是什么让你对技术这么感兴趣?它又是如何偶然地引导你创建树莓派项目的?

Eben Upton: 在我还是孩子的时候就开始对技术感兴趣了。我有个对工程技术有很大兴趣的父亲,他自己不是工程师,而是一个英语老师。我们的房子里经常到处堆着各种电子器件,在还不知道这些东西是干嘛的时候,我就开始摆弄了。都是些小玩意,比如在床头装个灯,在“关灯”后还可以继续看书之类的。

173435v3ssqllylnxmxsfy

 

之后我有了一台计算机。在英国,我们把这种机器叫做BBC微计算机,实际上是8位单片机,做教学用的。我们在学校的时候接触到这种机器,我之后就学会了编程,而且还蛮喜欢的。

这些机器在学校里并不一定是用来编程的,或者说他们根本不是用来编程的,一般都运行教学软件。但是我却给它编程,之后我还买了一台回家,在我买了这台BBC微机后,我就泡在了房间里,再没出来过。[笑]

编程对于小孩来说太神奇了。当你还是小孩的时候,并没有太多力量。没有听话的随从,反而身边有很多的限制。编程最伟大的地方在于,这是一个可以让你随心所欲的小世界。而这当然让我无法抗拒。

我一直都对科学和数学,以及理科感兴趣。我在我的BBC微机上做了大量的计算和编程,之后我拥有了一台Commodore Amiga。

在大学里我学习了物理,工程和计算机科学。这是激发树莓派项目想法的原因,因为当我在学校呆了10年的时候[当时在读博士学位],我发现那些新来的孩子们在他们小时候并没有机会获得这方面的经验。你也许仍然能拥有乐高玩具,但是它不是我们要的梯子。

在一定程度上我们把身后的梯子撤掉了。我们造出了这些非常复杂而且用户友好的计算机给小孩使用,或者不仅仅是计算机,还包括电视游戏机,电话和平板,以及一些家用电器。但是,人们却没有机会自己动手改一改。所以实际上,树莓派是回到最初的一种尝试,当然也不会过于原始,希望找到在过去25年里计算机发展中迷失掉的那种感觉。

RW: 你需要克服的最大的障碍有哪些?

EU: 好吧,我们没有任何投资者,当然这也是一件好事情。我们从2006年就开始尝试做这件事情,你可以看到它花了我们很长时间才把树莓派从一个想法变成一件能卖的东西。在价格和性能之间或是价格和可编程性之间找到平衡,是一件很重要的事情。

另外一件麻烦事是募集资金。我们是非营利组织,所以我们得去找人赞助,而这最后都变成了董事会中的几个人自掏腰包。我们有25万美元的启动资金是从我和其他几个成员自己借的。所以我觉得,当初这样做还挺有勇气。

173438m5aintlfgaplcn5a

 

从东方到西方

为了找到价格合适的生产方式,我们选了一条不同寻常的路线。通常人们生产更传统的产品时,当量不大的时候都会选择在本地生产,然后[制造商]再制定较高的价格。大多数都能获得比树莓派丰厚的利润。

所以他们开始会在西方生产。然后,为了追求更高的利润,当产品有一定的量就会想减少生产成本,所以转到远东地区。

我们的问题是,因为我们没有足够的利润来支撑这种模式的订单,所以我们在中国制造了第一批产品。当然一开始会有一点不好的预感。我一点也不了解中国制造,最后,我们把价值5万美元的芯片和5万美元现金交给一个香港人,他需要还给我们2000片可以工作的树莓派。

之后交期出现了延时,我们甚至都开始相信自己被骗了。然后终于有一天,现在250万台树莓派中最早的2000台放在托板上来到了门口。

那个UPS快递员从卡车里拖出一个托板,并拉到我们车库里。托板上放着2000台树莓派,它们中每一台都比我小时候用过的计算机强多了。我们随机抽查了几台,都可以完美地工作。

所以我觉得还挺幸运,中国你懂的。然后我们的产品终于开始有量了,我们选择了跟其他所有人不同的方向。我觉得这是这个项目中的另一个决定性时刻,我们认识到,以目前的订单量,我们可以用和在中国同样的成本在西方生产。所以我们可以回归,把所有的生产制造搬回威尔士,也是我出生的地方。像是一个美妙的圆圈。

RW: 有没有一些树莓派的前身没有被制造出来的?

EU: 有的,我们做了许多不同的原型机。我们希望做出一个可以编程,也能吸引小朋友兴趣的东西。“吸引小朋友兴趣”意味着,在某些方面要足够强大。比如,播放视频,玩游戏,以及上网。

我们有许多能够达到价格目标和可编程目标的原型,但是等我们确定一个合适的方案,它足够强大能够吸引孩子们的热情,已经挺晚了,都到2010年底2011年初了。

派是从哪儿烤好的

RW: 跟我们说说发明树莓派的故事

EU: 我们尝试过基于所谓的微控制器技术做了几台机器。不知道你有没有听过一个叫Arduino的[开源电子原型]平台?它们的性能跟Arduino是一个级别的,优点是很容易买到,是常用的元器件,非常便宜,也很容易掌握。

173441nqdd3u3my60q3uq9

 

所以我们试了一下。最后的成品只能从技术上来说还是计算机,你可以把它接到电视机或其他显示设备上。但是,它太原始了,很明显不能吸引孩子们的兴趣。这个是一号原型机,它在爱尔兰一家博物馆的叫“失败”的展览中展出[笑]。我下个月会去看看。它现在被装载一个玻璃盒子里,作为一次辉煌失败的典型。

好的一面是它是手工制作的,你不可能手工制作一块现代的树莓派。但是,这个原型太原始了,你实际上可以把所有器件手工焊接到一起,它就是我一个星期里做好的,是个挺好的小玩具。

我在大学里呆了差不多10年以后,进入到一家叫Broadcom的公司工作,总部在南加利福尼亚但是在剑桥有个大办公室,主要生产手机芯片。然后,我意识到这种手机芯片非常适合,它是制作像派这样的设备的非常合适的平台,因为它有优秀的图形性能。

我基于Broadcom开发工具制作了一个原型。这次的原型非常强大,也有更多功能,价格也差不多。不过问题是,它有一套定制的开发环境,而不是一个标准的平台。

我们得写自己的SD卡驱动,自己的文件系统,自己的文本编辑器。你会发现你得做大量基础工作,虽然最后你能够得到一个强大的可编程的平台,但是它却是完全非标准的[而且]和其他设备完全不一样。从而无法重用那些已经在台式机系统中已经做过的工作。这个是二号原型机。

真正的突破是三号原型机。我们从Broadcom拿到了另一种应用了ARM处理器的芯片,可以直接运行标准Linux。我们意识到终于可以做出能够满足所有的需求的机器了,这就是我们推向市场的产品。

黑一黑下一代黑客

RW: 八岁的孩子就开始用树莓派做项目了。这在你意料中吗,还是说让你意外了?

EU: 八岁是很好的年纪。我想每个人都会把自己开始编程的年龄定义成合适的年龄。我就是八岁开始编程的。某种程度上来说,孩子们所需要的只是年龄大到拥有相对完整的认知技能,或者说是解决问题的技能。也许在学校学一点数学就够了。

173446mpzp6x0b1buugyxx

 

年龄大到可以计划任务,编程就是终极的计划任务。还是得有一定的智力基础去做这个事情。八岁的时候,大多数孩子在自己的思维上已经非常成熟了。另外还需要敏捷的身手,对更小的孩子来说还存在一个问题就是,他们还不够灵巧去使用键盘。

所以说,八岁是很好的年纪。你有合适的身体,有合适的心智,而且还处于生命中能轻松学习新知识的时候。你的大脑还具有非常大的可塑性,可以学习语言。。。

我的意思是,你要是想让你的小孩学习法语的话,八岁就开始教他,不要等到16岁才开始。正式的计算机教育有一个历史性的缺点,就是太晚开始了,然后就很惊讶为何学生们理解起来概念有困难。所以我认为越早接触越好,而八岁是奇妙的年纪。八岁,十岁,十二岁,十二岁可能都有点晚了。

我们基金会的CEO,Lance [Howarth],对初级教育特别热心。他真的认为这是一个实际的机会来做点非常特别的事情。

RW: 所以这是树莓派项目的目的,让小孩子们编程?

EU: 我想我们一直认为可以让孩子们玩编程只是举个例子。但是树莓派的目的是把这个东西做出来看看谁会买它。我们一直相信至少有一部分年轻的孩子会觉得它令人激动。现在我们已经有知识宽度和规模来支持孩子们玩它了。

[仅仅]做出一个像树莓派的平台和提供相关支持是有很大区别的,如果只是做出来的话,你会发现有1%的八岁孩子会喜欢它并且玩起来,不管你提供多或者少的支持。

我觉得现在基金会的一个实际的机会是,我们已经可以承担得起开发教材了,我们还可以提倡培训这方面的教师。有个机会是我们可以吸引比1%更多的孩子。还有个机会是吸引那些没有独自处理复杂技术问题倾向的机灵小孩。如果能够提供良好的教程和让他们感兴趣的教材,就能够吸引10%,20%,50%,甚至更多的孩子。

我们认为80年代是[学习编程]的黄金年代,而实际上,只有很少一部分人学习编程并达到一定深度。大部分人也许可以写个几行,但是能够编写大型程序的还是很少见。

所以我认为我们目前有一个实际的机会,因为我们可以参与到教材和教师培训的级别,我们也许可以超越80年代。现在有更多的参与者,两性之间也更平等。在80年代,编程很大程度上是男孩们的事情,而这也能反映到我们的工程师社区构成上。我觉得现在有个很好的机会,让更多的女孩子接触电脑编程。这个是挂在枝头上垂得最低的果子了,做到这个,人数马上增加了一半。

机会有很多,我对树莓派最满意的地方就是我们已经有点规模可以吸引部分人的注意了。

每个人的派

RW: 关于像派这样的项目的潜在需求,对于你来说意味着什么?是不是有一天我们都会变成DIY黑客?

EU: 是的,我意思是,就是这样的。有非常大的这种需求。而且我认为有一条通向制作者社区的纽带。美国的制作者社区比英国成熟多了。我们也确实在举办制作者集会和黑客空间,但是差不多比美国落后了5年左右。

所以在开始讨论树莓派之后我发现了一件事情,在它获得国际关注的时候,我们发现我们受到一些非常稳定的社区的成员的追捧,他们喜欢各种各样的DIY活动:编织,或者,你知道的,木工。

所以,这也是为树莓派带来意外增长的其中一个因素。制作者们把它当作用来构建自己项目的模块。这太棒了!

RW: 你怎么看现在出现的主流硬件黑客文化?

EU: 我觉得,这太美妙了,不是吗?这是在软件工程领域里完全无法想到的。我接触这些之前就有软件背景,所以,实际上人们用树莓派制作的大多数很酷的东西都是硬件相关的,让我很惊讶。当然现在没那么吃惊了,不过一开始是有的。

173449y80odr8f7frhhc8z

 

我认为这是非常积极的趋势,基于所有这些因素。因为它给孩子们带来了相关的经验。在我看来,在屏幕上移动一下像素还是很酷的,不过事实上,它没有像80年代那样酷了。我觉得,在现实世界里移动一些物体,比如机器人,对于现在的孩子来说是非常酷的。

当有更多实用性的时候,就会吸引更多的女孩。确实存在一种潜在趋势,尝试和设计针对女孩子的科技活动。不过实际上这并不是关于女孩子,而是关于扩展用户的迫切要求。

有这样一小段-我之前谈过的关于有1%的小孩会觉得抽象的计算机编程很有趣。“让我们开始学习变量!”我就是他们其中一个。但是,那只是很小一部分,而且看起来更大部分是男孩子。我不知道是不是文化因素或其他的,但是看起来这个世界就是这样的。

在人们谈论追求实用性来吸引女孩子的时候,根本不关女孩子的事。而是吸引那一小部分男孩之外的所有人。不仅仅吸引女孩,也包括其他男孩。

从教育的角度来看有一件美妙的事情是,在现实世界里应用计算机做点实际的东西,自然而然会比仅仅在计算机本身上面做点事情有用多了。所以,这就提供了一个方式来吸引女孩子进入这个领域,同样也可以吸引更多的男孩子进入这个领域。

不再是一个人很好。能够加入到这波兴趣的浪潮中,和许多制作现实世界东西的人一起,也是很精彩的事情。我认识一个南加利福尼亚的小伙,他有两个兴趣就是倒腾派和制作他的锁链甲。有人做这些事情本身就是一件很美妙的事情。

分享你的派

RW: 关于吸引比1%更多人的“实用”项目,能举个例子吗?

EU: 整个机器人技术领域就是个很好的例子。有很多人基于派来制作小型机器人,让它们四周跑跑或做点事情。特别是现在,我们增加了摄像头模块,可以一定程度上实现计算机视觉。

我觉得其他基于摄像头的项目也会变得更活跃。那些从事野外摄影的人们,以及从事缩时摄影的人们,因为有了这个25美元的摄像头模块,应用范围宽了许多。还有红外版本的模块,所以你可以在晚上拍摄野生动物-写脚本在晚上拍摄相片,然后选择保存里面包含了动作的。这些都非常好。

我特别喜欢应用到高空气球的任何项目。环境监控-有一些英国的高中学生在IndieGoGo发起了一个叫AirPi的项目,这是一个污染监控防御系统,底层将用到树莓派。所以会有许多这样的项目,你可以用派来处理物理的,或化学的,或者生物的事情。-这些都是我认为有实用性的事情。这种项目也更容易向孩子们证明,这是值得他们关注的项目。

RW: 我们什么时候可以看到树莓派C型?

EU: 暂时还没有计划。我们目前都还在处理软件工作。我觉得我们还有机会通过调整软件来大幅提升系统性能,再优化一下。

如果我们现在就启动制作C型,将会抛弃250万使用目前平台的用户。所以我觉得,至少现在,我们决心要继续软件工作,因为这可以帮到所有已经在这个领域里的人。我们感觉通过软件优化还有很大的性能提升空间。

显然,我们同时也必须做一点[硬件方面]的事情。我真的不知道具体在什么时候。如果到了2017,2018,我们还在销售树莓派B型的话,那也挺糟糕的。但是,我认为我们也许在一年后再认真考虑后面要做什么。

RW: 很多人的项目同时用到了派和Arduino(一个DIY电子调试工具套件)。你在设计派的时候,有考虑类似Arduino的工具吗?

EU: 实际上没有,但是我们很早就意识到,媒体可能会倾向于把我们和Arduino看作竞争者。对于这件事情我们有点多疑,我觉得,因为我认为派和Arduino分别处理不同的事情,而且他们都做得很好。

我们并没有把它设计成配合Arduino工作,但是Arduino被设计成配合家用PC一起工作。所以,我们实际上为Arduino制作了一台非常低功耗的家用PC。所以好吧,只是巧合,我猜。

RW: 你在家里用树莓派做什么?工作中呢?

EU: 在家里,我把它当作一个媒体中心;这是树莓派一个非常普通的应用。有趣的事,有些从事消费电子的人,把它当作消费电子来用。我当然也是其中之一。

在工作中,我总是没有我想要的那么多时间来玩玩树莓派。通常在工作的时候如果在用派的话,那是因为我需要测试刚拿到的一些软件更新。大多数时候我用它来检查我花钱请的承包人是否把工作做好了。

我真心希望明年会有更多休息时间。有时我感觉,除了媒体中心之外,我参与制作了这么神奇的玩具,但是因为它太成功了,我都没有时间去好好玩玩它。

不过,看到这么多的人喜欢它,看到它被出现在各种不同的地方,也是很开心的。我听说在《生活大爆炸》中提到了我们,我要去找找是哪一集。它出现在所有的这些不可思议的地方。真是非常开心,看到这么多人把它放在心上,开始用它做点事情。

树莓派的联合创始人访谈——我们是怎么让大家都成为DIY黑客的,首发于极客范 – GeekFan.net

树莓派 B+ 发布,售价 35 美元

应对HummingBoard在内的开发主板的挑战近日树莓派(Raspberry Pi)推出了性能更加强悍的新版本B+,相比较前代产品功耗更低,对专用电源的依赖大大降低,不再需要专用的适配器;此外提供了更加丰富的接口,为用户连接更多的设备,提升移动终端和智能家居环境的友好度。

在硬件规格上树莓派B+采用了相同的Broadcom芯片和512MB的内存。模拟和复合视频连接器已经被一个四极连接器端口所替换。更强悍的性能允许用户在没有额外电源和分线器的情况下同时连接4个USB设备。目前树莓派B+的售价为$35,约合217元。

树莓派 B+ 发布,售价 35 美元,首发于极客范 – GeekFan.net

将树莓派打造成音乐播放服务器

几个月前,我发布了一篇文章《我对探寻终极音乐播放器的探寻》(My Quest to Build the Ultimate Music Player),在那篇文章里面描述了我对一款开源的音乐播放服务器Groove Basin断断续续将近4年的痛苦折腾过程。

它的客户端基于web页面,如下图:

groovebasin-screenshot

你也可以在这里尝试它的在线demo版本

如果你把它安装在树莓派里面,你可以把speakers附加上去,使用它你可以远程控制,也可以通过在浏览器中的点击“stream”就可以远程收听自己的音乐。

然而,在鼓捣这个之前,我需要指出的是,如果你在决定是否入手一台树莓派,答案是,不要。树莓派被过度夸大了,其实还有更好的选择。这就是为什么我写这篇教程。在这里我要提到一个,就是Beagle Bone Black 

你可以用这个来代替的原因如下:

  • 更快的cpu和内存
    • 1GHz处理器,而非700MHz
    • DDR3内存,而非SDRAM
  • 它可以直接运行Debian和Ubuntu armhf,而非运行类似Respbian的系统。在Debian已经有armhf端口的情况下仍然存在Raspbian简直就是愚蠢的行为。如果你只是安装普通的armhf Ubuntu在Beagle Bone Black上,这篇文章的剩余部分就没有必要再看下去了,你只需
    # apt-add-repository ppa:andrewrk/libgroove
    # apt-get update
    # apt-get install libgroove-dev

    然后你就已经做完了。

    实际上,libgroove在Debian TestingUbuntu Utopic Unicorn两个版本上面已经存在了,所以一年半载之内这些发行版升级了,你也无需添加额外的个人软件包档案

  • Debian官方不推荐树莓派,因为它在运行时候需要非自由软件。Debian特别推荐了Beagle Bone Black。

如果你像我一样,同时在你收到更好建议之前不幸的买了一台树莓派,你需要跳过很多坑来让它运行起来。这篇文章就会手把手的交给你怎么绕过所有的坑,而无需自己浪费时间去自己费劲琢磨。

这篇文章开始时会假设你手上有一台全新的甚至还未装操作系统的树莓派。如果你已经做过了这一步,可以直接跳到下一部分

目录

  1. 目录
  2. 安装Raspbian并获取SSH连接
  3. 安装Groove Basin

安装Raspbian并获取SSH连接

转到树莓派下载页面,下载Raspbian Debian Wheezy种子(或者直接下载,如果你不是大虾的话)

解压压缩包,得到img文件后将其刷入你有的最大的SD卡上面。因为你需要很大的空间存放音乐!

我是在Ubuntu上面,我所需要做的仅仅是在文件管理器中右击img文件, open with, Disk Image Writer:

disk-image-writer

我确信做这一步有很多种方式,我使用的这种方式只是对我来说最简单的。

这步完成后,找一个键盘、显示器和HDMI线,你就可以看到你正在做的事情了。我们的目标是可以尽快的使用上SSH连接,从而使树莓派可以除了电源线和网线之外什么都不用插就可以工作。

树莓派第一次启动后它会给您一个清单,包含你可以做的事情。下面是我做的事情:

  • Expand the file system to fit the full SD card.
  • Set pi user password.
  • Advanced Options, enable SSH server.

现在我们将其设置为每次启动时候都有固定ip。下面是我使用的设置,你可以按照自己的需要照猫画虎:

sudo vi /etc/network/interfaces

iface eth0 inet dhcp代替为:

auto eth0
iface eth0 inet static
    address 192.168.1.99
    netmask 255.255.255.0
    gateway 192.168.1.1

现在我们可以拔除TV和键盘了,我们已经无须这些废物了。直接插入网线然后开机吧!

在你现在用的电脑上面你可以用ssh连接到树莓派上面了,就像这样:

ssh pi@192.1.68.1.99

我喜欢在我的~/.ssh/config文件中添加传送门,就像这样:

host pi
hostname 192.168.1.99
user pi

它需要你输入密码,但我们也可以解决:

ssh-copy-id pi

现在连接树莓派已经可以ssh pi这么简单了。

你需要做的第一件事就是更新所有的过时的软件到最新版:

$ sudo apt-get update
$ sudo apt-get dist-upgrade

额,我在这里看到了什么?

...
Unpacking replacement raspberrypi-bootloader
...

Bootloader都被代替了?最好重启一下看看他是不是还能用。

好了,这个时候我们还是可以通过ssh连接上我们的树莓派,所有的软件包也完全更新了。

安装Groove Basin

首先安装一些软件包:

$ sudo apt-get install htop vim git cmake screen

建议你在做这个的时候在screen或者tmux这类环境下,因为一旦你的网络断了,我们的命令还可以继续。这也让我们可以在树莓派运行时候去做点其他的事情。

我需要一次解释清楚如何执行这一步。然而,记住有3个重要的编译需要用好长时间,所以如果你想同时开始这3个任务并且离开电脑8个小时或更久,你可以跳过这个教程并开始同时执行它们了。这3个软件的make步骤为:

  • SDL2
  • libav
  • Node.js

libgroove,第一部分

得到libgroove源代码,在源码里面创建build文件夹:

$ cd
$ git clone https://github.com/andrewrk/libgroove
$ cd libgroove
$ mkdir build
$ cd build

我们在debug模式build,这样在有任何错误的时候就可以得到有用的堆栈信息。

记住,你可以跳过下面的步骤,它仅花一两分钟时间就可以完成,这些命令仅供参考,我也已经在下面贴出了在我机器的输出:

$ cmake .. -DCMAKE_BUILD_TYPE=Debug
Installation Summary
——————–
* Install Directory : /usr/local
* Build libgroove : missing dependencies
* Build libgrooveplayer : missing dependencies
* Build libgrooveloudness : missing dependencies
* Build libgroovefingerprinter : yes

Bundled Dependencies
——————–
* SDL2 : ready to build
* libav : missing dependencies, see below
* libebur128 : ready to build

System Dependencies
——————-
* C99 Compiler : OK
* threads : OK
* SDL2 : not found – will use bundled version
* ebur128 : not found – will use bundled version
* chromaprint : not found
* libavformat : not found – will use bundled version
* libavcodec : not found – will use bundled version
* libavfilter : not found – will use bundled version
* libavutil : not found – will use bundled version
* yasm : not found
* bzip2 : not found
* mp3lame : not found
* zlib : OK

信息显示缺失了以下库:

  • chromaprint
  • libebur128
  • SDL2
  • libav

我们可以让安装libgroove自动解决依赖问题,但是在系统上面事先安装这些依赖的软件包更简单。我们就这么做。

chromaprint

幸运的是,chromaprint已经在软件仓库里面了:

$ sudo apt-get install libchromaprint-dev

libebur128

下一步我们编译最简单的一个,libebur128.

$ cd
$ git clone https://github.com/jiixyj/libebur128
$ cd libebur128
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Debug

矮油,好像我们缺少了一些依赖软件:

– checking for module ’speexdsp’
– package ’speexdsp’ not found

最好安装这个:

$ sudo apt-get install libspeexdsp-dev

重新试试那一行配置行:

$ cmake .. -DCMAKE_BUILD_TYPE=Debug
– checking for module ’speexdsp’
– found speexdsp, version 1.2rc1
– speexdsp library dirs:
– speexdsp cflags:
– speexdsp include dirs:
– speexdsp libraries: speexdsp
– speexdsp ldflags:
– status found / disabled –
– queue.h: yes using system copy of queue.h
– speexdsp: yes no
– not building tests, set ENABLE_TESTS to ON to enable
– Configuring done
– Generating done
– Build files have been written to: /home/pi/libebur128/build

这样好多了。

现在编译并安装源码:

$ make
$ sudo make install
[ 50%] Built target ebur128
[100%] Built target ebur128_static
Install the project…
– Install configuration: ”Debug”
– Up-to-date: /usr/local/include/ebur128.h
– Installing: /usr/local/lib/arm-linux-gnueabihf/libebur128.so.1.0.1
– Installing: /usr/local/lib/arm-linux-gnueabihf/libebur128.so.1
– Installing: /usr/local/lib/arm-linux-gnueabihf/libebur128.so
– Installing: /usr/local/lib/arm-linux-gnueabihf/libebur128.a

由于Debian cmake包中的一个bug,它把库文件放在/usr/local/lib/arm-linux-gnueabihf/

我们来改一下:

$ sudo mv /usr/local/lib/arm-linux-gnueabihf/* /usr/local/lib/
$ sudo rmdir /usr/local/lib/arm-linux-gnueabihf
$ sudo ldconfig

SDL2

接下来我们让SDL2跑起来。树莓派自带的SDL有什么问题?是因为它自带的是1.2版本,而libgroove是基于版本2的。

SDK下载页面找到最新的SDL2的源码URL:

$ cd
$ wget https://www.libsdl.org/release/SDL2-2.0.3.tar.gz
$ tar xvf SDL2-2.0.3.tar.gz
$ cd SDL2-2.0.3/

SDL需要音频后端才可以工作,现在我们在配置命令之前先安装它:

$ sudo apt-get install libasound2-dev

我们只需要SDK2的音频特性,而且实际上,它的视频的一些功能还会带有编译的问题。所以我们在configure的时候禁止掉所有我们不需要的功能:

$ ./configure –enable-audio –disable-video –disable-render –disable-events –disable-joystick –disable-haptic –disable-power –disable-file –disable-timers –disable-loadso –disable-cpuinfo

这步要费一些时间,但是在完成后,你可以看到这样的一行:

Audio drivers : disk dummy oss alsa(dynamic)

这很重要,你除了有声卡驱动外还有disk、dummy和oss

$ make

找点事情做,这一步要个把小时才可以完成。或者如果你想让你的树莓派投降,你可以跳过本教程,同时编译libav。但是我要假设你正在按顺序做这些,而且让你自己来决定如何跳过这篇文章。

这个时候,冗长的编译过程终于成功了,我们可以安装SDL了:

$ sudo make install

libav

我们回到home文件夹(或者我们决定安装的目录):

$ cd

libav下载页面(http://www.libav.org/download.html)得到libav最新的版本10的URL:

$ wget http://www.libav.org/releases/libav-10.1.tar.gz
$ tar xvf libav-10.1.tar.gz
$ cd libav-10.1/

先做些预备工作,然后开始configure:

$ sudo apt-get install libmp3lame-dev libvorbis-dev
$ ./configure –enable-shared –enable-debug –disable-static –enable-gpl –enable-libmp3lame –enable-libvorbis

同样,树莓派还是会非常困难的完成configure命令,特别是你同时也在编译SDL2,所以如果它用了一两分钟,不要着急

$ make

这个过程要长达8个小时。认真的说,我会开始这个过程后直接去睡觉。如果你希望同时开始所有的编译,你可能会同时开始Node.js的编译。

libav编译成功后:

$ sudo make install

我们终于完成了libgroove的依赖软件的安装,我们终于可以开始安装libgroove本身了。

libgroove,第二部分

这个时候,你已经等了很长时间了,树莓派也已经编译libav和SDL2成功,你也已经安装了它们。如果这些还没做完,你需要搞明白为什么,然后在接下来这个教程开始之前将其修复。

$ sudo ldconfig
$ cd ~/libgroove/build/
$ cmake .. -DCMAKE_BUILD_TYPE=Debug
Installation Summary
——————–
* Install Directory : /usr/local
* Build libgroove : yes
* Build libgrooveplayer : yes
* Build libgrooveloudness : yes
* Build libgroovefingerprinter : yes

Bundled Dependencies
——————–
* SDL2 : using system library
* libav : using system libraries
* libebur128 : using system library

System Dependencies
——————-
* C99 Compiler : OK
* threads : OK
* SDL2 : OK
* ebur128 : OK
* chromaprint : OK
* libavformat : OK
* libavcodec : OK
* libavfilter : OK
* libavutil : OK

这个输出比前面的好看多了。

$ make

这个make相对而言应该快多了。

$ sudo make install
$ sudo ldconfig

这个时候我们已经把必要的库安装好了:

$ ls /usr/local/lib/
libavcodec.so libebur128.a libgroove.so.4
libavcodec.so.55 libebur128.so libgroove.so.4.1.0
libavcodec.so.55.34.1 libebur128.so.1 libSDL2-2.0.so.0
libavdevice.so libebur128.so.1.0.1 libSDL2-2.0.so.0.2.1
libavdevice.so.54 libgroove.a libSDL2.a
libavdevice.so.54.0.0 libgroovefingerprinter.a libSDL2.la
libavfilter.so libgroovefingerprinter.so libSDL2main.a
libavfilter.so.4 libgroovefingerprinter.so.4 libSDL2.so
libavfilter.so.4.2.0 libgroovefingerprinter.so.4.1.0 libSDL2_test.a
libavformat.so libgrooveloudness.a libswscale.so
libavformat.so.55 libgrooveloudness.so libswscale.so.2
libavformat.so.55.12.0 libgrooveloudness.so.4 libswscale.so.2.1.2
libavresample.so libgrooveloudness.so.4.1.0 pkgconfig
libavresample.so.1 libgrooveplayer.a python2.7
libavresample.so.1.1.0 libgrooveplayer.so python3.2
libavutil.so libgrooveplayer.so.4 site_ruby
libavutil.so.53 libgrooveplayer.so.4.1.0
libavutil.so.53.3.0 libgroove.so

Node.js

我们现在需要Node.js。从它的下载页面(http://nodejs.org/download/)找到最新的stable源码

$ cd
$ wget http://nodejs.org/dist/v0.10.29/node-v0.10.29.tar.gz
$ tar xvf node-v0.10.29.tar.gz
$ cd node-v0.10.29/
$ ./configure
$ make

编译过程要持续数个小时。

安装完成后需要执行:

$ sudo make install

Groove Basin

现在是开始音乐播放服务器Groove Basin的时间了。

$ cd
$ git clone https://github.com/andrewrk/groovebasin
$ cd groovebasin/
$ npm run build

这个过程要持续数分钟,它会下载和编译Groove Basin依赖的软件。

我们建立音乐目录,如果没有的话:

$ mkdir ~/music/

把你所有的音乐都拷贝到这个目录下。

$ node lib/server.js

现在需要启动服务器了。如果你想要改变configure选项,使用Ctrl+C结束服务器然后编辑config.js

享用吧!请自由的关注GitHub上面的GrooveBasin主页报告bug report或者需要的特性,或者加入在irc.freenode.org上面的#libgroove 讨论获取故障帮助。

我们对pull request非常欢迎,特别是可以让groovebasin.com看起来更漂亮的Pull request。

将树莓派打造成音乐播放服务器,首发于极客范 – GeekFan.net

Adafruit的树莓派教程第十一课:DS18B20温度传感器

概览

树莓派操作系统Occidentalis以及2012年12月之后的Raspbian系统已经能够支持DS18B20单总线(1-wire)温度传感器。这种传感器由半导体包裹的头和三个引脚组成,它是一种精确地数字设备。

lesson11_1

这节课里,你将学习如何在树莓派上使用DS18B20来读取温度。

因为树莓派没有数模转换器(ADC, Analog to Digital Converter),因此它不能够直接读取像TMP36这样的模拟信号温度传感器,因此,DS18B20是比较合适的。

另外的代码库

如果你是一个Python爱好者,这有另外一种在树莓派上使用DS18B20的类库。

地址在这里:https://github.com/timofurrer/ds18b20(作者是Timo!)

你需要的

要完成这个项目,你需要下面的东西:

树莓派

lesson11_2

DS18B20数字温度传感器 + 延长线,也可以是湿度或者高温型号的。另外你需要一个4.7k或者10k欧姆的电阻。

lesson11_3

一小块面包板

lesson11_4

一把跳线

lesson11_5

扩展板

lesson11_6

硬件部分

下图展示了基本的DS18B20接法。

DS18B20单总线(1-wire)传感器可以以非并行连接接入,这一点几乎与其他市售的传感器都不同!所有传感器共享相同的针脚,所以你只需要一个4.7k的电阻就够了。

电阻被用于拉高数据输出线(data-line),并且保持数据输出的稳定。

要注意DS18B20的方向,弧形的一边在图中的左侧。如果你接反了,有可能会烧坏传感器。

尽管DS18B20+和TMP36都是温度传感器,但是它们完全不同,因此TMP36不适用于这篇教程!

lesson11_7

如果你是用的是防水版的DS18B20,那我们需要连接3个针脚,红,黑,黄,身下一个引脚不用连接。

如果你是用的是高温版本的DS18B20,把橙色引脚接入3.3V,白色接地,蓝色与数据针pin 4相连。

你同样需要一个4.7k~10k的电阻接在3.3v和数据针之间。

lesson11_8

lesson11_9

DS18B20

尽管DS18B20看上去就像一个普通的传感器,但它内部其实大有文章。

它的芯片包含了一个特别的单总线串行接口,逻辑控制部分以及一个温度传感器。

它的输出针输出数字消息以便Raspbian/Occidentalis能够在某一针上阅读。你可以在运行这个项目之前自己通过命令行或者SSH(参见第六课)先试验一下。

在终端窗口里输入下面的命令。当你执行到”devices”目录下时,目录名称开头的”28-”可能与你的不一样,所以cd到你看到的目录下吧。

sudo modprobe w1-gpio
sudo modprobe w1-therm
cd /sys/bus/w1/devices
ls
cd 28-xxxx (change this to match what serial number pops up)
cat w1_slave

lesson11_10

这个接口有点不太稳定,但如果幸运的话系统会告诉我们有一个可供读取的温度。它类似于一个文件,所以我们要做的就是读这个文件。

在返回消息的第一行末尾都会有一个YES或NO,如果是yes,那第二行紧接着就是温度,以1/1000摄氏度为单位,所以在上面的例子中,实际读取到的温度是20.687和26.125摄氏度。

如果你接入了多个传感器,那么你将看到有多个28-xxx的文件,已经插入一个传感器,然后检查一下新生成的文件名,然后为这个传感器做上标记。这样才能区分出哪个传感器对应哪个文件。

软件部分

下面的Python程序处理失败消息并且每秒返回华氏和摄氏温度。

import os
import glob
import time

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'

def read_temp_raw():
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines

def read_temp():
    lines = read_temp_raw()
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw()
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
        temp_f = temp_c * 9.0 / 5.0 + 32.0
        return temp_c, temp_f

while True:
	print(read_temp())	
	time.sleep(1)

在程序的开头运行了一下modprobe命令,来使接口运行。

紧接着的3行用于寻找哪些文件可以从中读取消息。

一个已知的问题是在Raspbian下读取温度时有时候会假死。如果你有同样的问题,使用下面的代码替换掉read_temp_raw方法。然后在程序开头加入一行”import subprocess”。

def read_temp_raw():
	catdata = subprocess.Popen(['cat',device_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	out,err = catdata.communicate()
	out_decode = out.decode('utf-8')
	lines = out_decode.split('\n')
	return lines

读取温度是通过两个方法进行的。read_temp_raw通过接口获取消息的前两行。read_temp把它包装了一层并且加入了失败消息检测并且重试直到第一行的末尾有一个YES。这个方法会返回两个值,第一个是摄氏温度,第二个是华氏温度。

你可以像下面这样把两个值分开

deg_c, deg_f = read_temp()

主方法只是一个循环,读取温度,打印出来,然后休息一秒。

要把这个程序传到树莓派上,你可以通过SSH在命令行里打开一个文本编辑器

nano thermometer.py

粘贴上面的代码,然后按一下Ctrl+X然后按一下Y保存。

lesson11_11

测试与配置

运行这个程序需要超级用户权限,所以在命令行里运行下面的命令

sudo python thermometer.py

如果一切ok,那你将会看到像下面一样的一系列输出

lesson11_12

试试把手指放在温度传感器上来给它升温。

加入更多的传感器

你可以以并行连接方式DS18B20把其他的DS18B20传感器接入到VCC,数据和地线针脚。只用一个4.7k电阻。你将会看到多个/sys/bus/w1/devices/28-nnnnn目录,每一个都有一个唯一的串口编号。目前的python程序只能读取一个传感器,所以你需要自己修改使它能够一次读取多个传感器。

Adafruit的树莓派教程第十一课:DS18B20温度传感器,首发于极客范 – GeekFan.net

树莓派和路由:将树莓派打造成一台路由器

如果你想要一个装在口袋里的网络分享设备,树莓派可以做成一个很不错的路由器.

本次制作所用到的设备要求:

  1. 本地网络
  2. 一台电脑
  3. 运行Raspbian的树莓派
  4. 无线USB路由器
  5. HDMI连接线(可选)
  6. 键盘(可选)
  7. 路由器(可选)
  8. 有HDMI输入的监视器(可选)

如果树莓派已经设置好可以独立运行了.你不需要屏幕键盘鼠标-就是另外一台可以用SSH通过网络远程登录的电脑

需要下载的

  1. Older hostapd (只有apt下不到驱动的时候)

需要的知识,技术,能力

1,可以熟练操作计算机系统

2,基本的计算机术语知识

3,敢于在终端里敲命令.如果有必要也要敢于调整他们适合自己的开发环境

4,熟悉网络核心概念

所用到资源

  1. http://magpi.techjeeper.com/The-MagPi-issue-11-en.pdf
  2. http://www.pi-point.co.uk/documentation/
  3. http://blog.sip2serve.com/post/48420162196/howto-setup-rtl8188cus-on-rpi-as-an-access-point
  4. https://docs.google.com/file/d/0B3nsVzbJuBHVOWRJRDJacVd0S2s/preview?pli=1
  5. http://sirlagz.net/2012/08/11/how-to-use-the-raspberry-pi-as-a-wireless-access-pointrouter-part-3/
  6. http://www.raspberrypi.org/phpBB3/viewtopic.php?t=39096&p=393810
  7. http://unix.stackexchange.com/questions/119209/hostapd-will-not-start-via-service-but-will-start-directly
  8. http://www.daveconroy.com/turn-your-raspberry-pi-into-a-wifi-hotspot-with-edimax-nano-usb-ew-7811un-rtl8188cus-chipset/

概念总览

  1. 用apt-get安装做需要的组件
  2. 验证无线软件狗收发功能
  3. 配置/etc/network/interfaces
  4. 给你想要设置的接入点创建配置文件/etc/hostapd/hostapd.conf
  5. 把hostapd指向步骤4所创建的配置文件/etc/hostapd/hostapd.conf
  6. 老版本替代/sbin/hostapd
  7. 配置DNS
  8. 配置IPv4转发,使其可以连接网络

准备树莓派

确定你的树莓派是最新版本的,可以安装所有最新的安装包

sudo apt-get update
sudo apt-get upgrade

安装所需要的组件

以下这些组件都是设置接入点做需要的:

  • rfkill: 一个无线工具
  • zd1211-firmware: 很多Wi-Fi收发器通用的固件
  • hostapd: 无线接入点的守护进程
  • hostap-utils: 补充工具
  • iw: 无线网络的配置工具
  • dnsmasq: DHCP 和 DNS 工具
  • bridge-utils:  用来将多个以太网设备连接到一起

用以下命令安装这些组件:

sudo apt-get install rfkill zd1211-firmware hostapd hostap-utils iw dnsmasq bridge-utils

 配置无线收发器

验证软件狗已经被树莓派识别

检查树莓派已经识别Wi-Fi软件狗:

lsusb

验证Wi-FI软件狗支持接入点模式

如果执行下面这条命令没有任何输出是关于AP mode,那么就是说你的软件狗不适合本项目。但是如果有东西的话那就继续进行下一步。

iwlist

倒霉的是我的软件狗坏了,而且还有产生了一个”

nl180211 not found

”的错误,不过还好了继续执行下面这条命令:

dmesg | grep rtl

如果结果是类似这样的

[    6.240292] usbcore: registered new interface driver rtl8192cu

可能这个还是能干活的,接下俩会修复这个问题的.

配置网络接口

先做一个

/etc/nework/interfaces

的备份,然后在文本编辑器里打开,

改成下面这个样子的:

# Automatically brings up interfaces with ifup -a
auto lo
auto br0

# Loopback
iface lo inet loopback

# Keep eth0 as dhcp so it can connect to an existing router
# (Optional--I used this since I was configuring via SSH)
iface eth0 inet dhcp

# Bridge interface
iface br0 inet dhcp
        bridge_fd 1
        bridge_hello 3
        bridge_maxage 10
        bridge_stp off
        bridge_ports eth0 wlan0

# Allow hotplug
allow-hotplug wlan0
allow-hotplug eth0
iface wlan0 inet manual
iface wlan0 inet manual

重启

wlan0

接口

ifdown wlan0
ifup wlan0

 配置hostapd

接下来,做一个

/etc/hostapd/hostap.conf

的备份然后在文本编辑器里打开做一些改动(如果这个文件不存在请忽略第一条命令)

sudo cp /etc/hostapd/hostap.conf /etc/hostapd/hostap.conf.orig
sudo vi /etc/hostapd/hostap.conf

修改这个文件使之包含以下内容,读者根据自己情况自行改动(比如国家代码,网络名等等)

如果

iwlist

命令执行结果有之前提到的

nl80211 not found

错误,创建一个内容如下的文件:

interface=wlan0
bridge=br0
driver=rtl871xdrv
country_code=US
ctrl_interface=wlan0
ctrl_interface_group=0
ssid=RPiAP
hw_mode=g
channel=1
wpa=3
wpa_passphrase=password
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
beacon_int=100
auth_algs=3
macaddr_acl=0
wmm_enabled=1
eap_reauth_period=360000000

如果

iw list

命令执行出错,文件

/etc/default/hostapd

也是需要备份的(如果此文件存在的话).

sudo cp /etc/default/hostapd /etc/default/hostapd.orig
sudo vi /etc/default/hostapd

然后添加如下内容(千万不要注释掉)

DAEMON_CONF=”/etc/hostapd/hostapd.conf”

安装一个不同版本的

/usr/sbin/hostapd

也是很有必要的,从这里下载, 根据以往经验最好在编辑之前做一个备份:

sudo cp /usr/sbin/hostapd /usr/sbin/hostapd.orig

删除原始文件, 因为接下来将会在下载章节将其替换掉.

cd /usr/sbin
sudo rm -f hostapd
sudo wget http://dl.dropbox.com/u/1663660/hostapd/hostapd

为新文件设置适当权限

sudo chown root:root hostapd
sudo chmod 755 hostapd

重启hostapd服务以激活设置

sudo service networking restart
sudo service hostapd restart

如果hostapd重启之后有问题就试一下如下命令查看结果看是否你是否能找出配置文件中的错误并将其修复.

sudo hostapd -d /etc/hostapd/hostapd.conf

如果你现在用另外一台设备扫描的话应该能够可以看到无线网络了.但是如果想要其他人连上的话还是需要一些设置的.特别是

dnsmasq

配置dnsmasq

老规矩,备份先,然后仔仔文本编辑器里打开

sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo vi /etc/dnsmasq.conf

将以下行的注释符去掉然后根据你自己的环境配置

domain-needed
interface=wlan0
dhcp-range=192.168.2.1,192.168.2.254,12h

重启

dnsmasq

使设置生效,

sudo service dnsmasq restart

用其他设备尝试连接本网络,但是还是不能连上因特网的.

设置因特网转发

设置IPv4转发

sudo echo 1 > /proc/sys/net/ipv4/ip_forward

如果上述命令提示拒绝访问,试试下面这个:

sysctl -w net.ipv4.ip_forward=1

设置NAT

sudo iptables -t nat -A POSTROUTING -j MASQUERADE

其他适配器和用法

我之所以选择Wi-Fi软件狗的主要原因是因为我可以连接我的cantenna,然后可以扩展我的信号到很远的距离.当然用一个无线适配器会非常的简单,但是现在我需要的是天线上的灵活性.

 

树莓派和路由:将树莓派打造成一台路由器,首发于极客范 – GeekFan.net

Adafruit的树莓派教程第十课:步进电机

概览

步进电机介于常规的直流电机(第九课)和伺服马达(第八课)之间。步进电机的优点在于它能够被精确定位,正向或反向一次性转动”一步”,并且也能够连续转动。

lesson10_1

这节课里,你将学到如何使用树莓派以及在第九课里已经用到的L239D马达控制芯片来控制一个步进电机。

这节课也将展示如何使用另外一种驱动芯片,ULN2803。

在这个项目里,你使用L239D或者ULN2803都是可以的。ULN2803更便宜一些,并且空余出来4个输出针脚你可以用来干点别的事,如果你两个芯片都没有,那还是选择ULN2803更好一些。

步进电机所需的电量很少并且所能承受的最大电流要小于直流电机和伺服马达。所以直接通过树莓派的5V输出并且保证电流是1A的情况下是可以直接驱动步进电机的。

你需要的:

5V步进电机

lesson10_2

L293D芯片

lesson10_3

ULN2803

lesson10_4

小块面包板

lesson10_5

树莓派

一把跳线

lesson10_6

硬件部分(L293D)

步进电机有5个引脚,所以L293D的两个半部都会用到。这意味着我们会在面包板上连接很多线。

步进电机的末端有5个接头。把跳线插入这些接头里这样就可以把电机连接在面包板上了。

lesson10_7

注意红色的引脚不连接任何线。

要通过引脚的颜色来区分而不是从它们伸出马达的位置。

<h4硬件部分(ULN2803)

如果你是用的是ULN2803,那步进电机的5个引脚都会被用到。

步进电机的末端有5个接头。把跳线插入这些接头里这样就可以把电机连接在面包板上了。

这个项目只适用于带有5个单级引脚的步进电机。

lesson10_8

尽管后面的代码里使用了GPIO的第18针,但只有在使用L293D芯片时才会用到它。

步进电机

步进电机使用锯齿状的转子和电磁配合推动转子一次转动”一步”。

lesson10_9

以正确的顺序给线圈通电,那么电机就会开始转动。转子的齿数与转动”一步”的角度精确对应。

我们现在使用的是8步步进电机,并且它有一个1:64的减速齿轮箱(reduction gearbox),所以它实际上转一圈需要 8*64=512步。

这节课里,我们不会使用红色的引脚。只有使用另外种类的不支持线圈电极反转的驱动芯片才会用到它。连接到两组线圈的中间意味着你就可以通过给左边或者右边的线圈通电来达到反转方向的目的而不用外接一个反转电流的电路。

因为我们使用的是支持电极反转的L293D芯片,所以我们就用不到红色的那个引脚了。可以通过这个芯片改变正负极来反转方向。

ULN2803

我们已经在第九课接触过了L293D芯片,而ULN2803也是一个非常有用的芯片。

lesson10_10

不像L293D有4个输出引脚可以反转电极,ULN2803有8个输出引脚可以把来自树莓派GPIO的输出信号放大转换成更大的电流。

与L293D不同的是,ULN2803只能输出一个方向的电流,所以这里我们要用到步进电机的红色引脚作为公用正极。并且每次只会用到线圈的一半,如粉色和橙色的部分,每次只有红色和粉色部分的线圈才会通电。

lesson10_11

软件部分

不过你用L293D还是ULN2803,软件部分都是一样的。

这个项目会用到Rpi.GPIO类库,如果你还没有装过,请参考第四课

要安装软件,你可以通过SSH连接到树莓派上然后通过下面的命令打开一个编辑器:

nano stepper.py

然后粘贴下面的代码,使用CTRL+X然后按一下Y保存。

lesson10_12

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

enable_pin = 18
coil_A_1_pin = 4
coil_A_2_pin = 17
coil_B_1_pin = 23
coil_B_2_pin = 24

GPIO.setup(enable_pin, GPIO.OUT)
GPIO.setup(coil_A_1_pin, GPIO.OUT)
GPIO.setup(coil_A_2_pin, GPIO.OUT)
GPIO.setup(coil_B_1_pin, GPIO.OUT)
GPIO.setup(coil_B_2_pin, GPIO.OUT)

GPIO.output(enable_pin, 1)

def forward(delay, steps):  
  for i in range(0, steps):
    setStep(1, 0, 1, 0)
    time.sleep(delay)
    setStep(0, 1, 1, 0)
    time.sleep(delay)
    setStep(0, 1, 0, 1)
    time.sleep(delay)
    setStep(1, 0, 0, 1)
    time.sleep(delay)

def backwards(delay, steps):  
  for i in range(0, steps):
    setStep(1, 0, 0, 1)
    time.sleep(delay)
    setStep(0, 1, 0, 1)
    time.sleep(delay)
    setStep(0, 1, 1, 0)
    time.sleep(delay)
    setStep(1, 0, 1, 0)
    time.sleep(delay)

def setStep(w1, w2, w3, w4):
  GPIO.output(coil_A_1_pin, w1)
  GPIO.output(coil_A_2_pin, w2)
  GPIO.output(coil_B_1_pin, w3)
  GPIO.output(coil_B_2_pin, w4)

while True:
  delay = raw_input("Delay between steps (milliseconds)?")
  steps = raw_input("How many steps forward? ")
  forward(int(delay) / 1000.0, int(steps))
  steps = raw_input("How many steps backwards? ")
  backwards(int(delay) / 1000.0, int(steps))

当步进电机不转动的时候,它也是处于激活状态的并且保持它的位置。这会耗电。如果你不需要步进电机保持它的位置,你可以调用setStep(0,0,0,0)来释放线圈。这样电机的转子就能自由转动并且不耗费电力了。

配置与测试

这个程序需要超级用户权限,所以要在ssh里受用下面的命令:

sudo python stepper.py

输入一个延时(5会是个合适的值)和转动的步数(512转一圈)。

lesson10_13

尝试减少延时来找到电机的最大速度吧。

Adafruit的树莓派教程第十课:步进电机,首发于极客范 – GeekFan.net

Adafruit的树莓派教程第九课:控制一个直流电机

概览

这节课我们来学习如何使用Python和L293D芯片控制直流电机的速度和转向。

lesson9_1

在第八课里,我们学习了如何使用小派产生脉冲来控制伺服马达的位置。这节课我们将使用脉冲和L293D马达控制芯片来控制一个直流电机的转速并交替变换它的旋转方向。

你需要的:

要完成这个项目,你需要下面一些东西。

1个树莓派
lesson9_2

1个树莓派扩展板
lesson9_3

一把公对公跳线
lesson9_4

1个小块面包板
lesson9_5

1个6V直流电机
lesson9_6

L293D马达控制芯片
lesson9_7

Adafruit Occidentalis 0.2及之后的操作系统
lesson9_8

4节5号或7号电池盒及电池
lesson8_8

PWM

PWM(Pulse Width Modulation,脉冲宽度调制)是一项用于控制电力的技术。在这里我们使用它来控制供给直流电机的电量及它的转速。

下面的图表展示了从树莓派的PWM针脚产生的脉冲信号。
lesson9_10

PWM针每1/500秒产生一次脉冲。脉冲的长度控制了直流电机所能获得的电量。没有脉冲电机就不会转动,一次短脉冲会使电机以很慢的速度转动。如果脉冲持续总长度一半的时间,那么它就会获得总电量一半的电量。

PWM核心模块

Adafruit与Sean Cross一起编写了一个核心模块被包含在了Occidentalis发行版里。更多的细节请参照这篇教程。如果你想在Raspbian或者其他发行版上使用这个模块,参考这里来把模块安装到你的环境里。

你已经在第八课里使用过了PWM与伺服马达核心模块,用于控制伺服马达。这一次,你将使用相同的模块来控制电机的转速。

这个模块使用文件类型的接口,你可以通过读写这些特定的文件来控制针脚输出进一步控制伺服电机的行为。这使得使用Python或者其他语言来编写该接口十分容易。

文件 – 描述
active – 1为激活,0为未激活。你可以通过读取它来查找输出针是否被激活,或者通过改写控制它的激活或未激活。
delayed – 如果设置为1,你对其他文件的改动不会起作用直到你使用上面的active来激活输出针。
mode – 改写文件来设置针脚是pwm,servo(伺服马达)还是audio(音频)。显然这里我们要设置为servo。注意这些针也会被小派的音频输出使用,所以你不能在使用声音的同时控制一个伺服马达。
frequency – 每秒产生的脉冲次数。
duty – 这个值应该介于0到100之间,代表了脉冲长度的百分比。数值越大,转速越快。

L293D

这是一个非常有用的芯片。它实际上可以独立控制两个电机。这节课我们将只使用芯片的一半针脚,在芯片右手边的大多数针脚用于控制第二个电机,但在树莓派上只有一个PWM输出针脚。

lesson9_11

L293D有两个+V的针脚(8和16)。+Vmotor(8)针为电机提供电力,+V(16)针作为芯片的逻辑针脚。我们将把第16针接到树莓派上然后把第8针接到电池盒上。

硬件部分

为什么我们要在这个项目里使用L293D芯片?有两个原因。第一个原因是小派似乎还没有强大到能够直接驱动一个电机并且这样做可能会损坏树莓派。

第二个原因是,在这篇教程里,我们即要控制电机的转速,也要控制电机的转向。要达到这一点,需要反转电机的电流方向,而L239D恰好就是被设计用来达到这一目的的,我们可以通过两个电机控制针脚实现。

lesson9_12

一小块面包板的大小很适合这篇教程。

软件部分

因为我们需要使用控制针脚(连接GPIO的第4针和第17针),所以我们也需要用到GPIO库。更多细节请参考第四课

有很多种方法能把下面的展示的代码弄到你的树莓派里。最简单的方法可能是使用SSH连接到小派上(参见第六课)然后使用下面的命令打开一个编辑器:

sudo nano motor.py

粘贴下面的代码,然后用Ctrl+X保存。

lesson9_13

代码在这:

import RPi.GPIO as io
io.setmode(io.BCM)

in1_pin = 4
in2_pin = 17

io.setup(in1_pin, io.OUT)
io.setup(in2_pin, io.OUT)

def set(property, value):
    try:
        f = open("/sys/class/rpi-pwm/pwm0/" + property, 'w')
        f.write(value)
        f.close()	
    except:
        print("Error writing to: " + property + " value: " + value)

set("delayed", "0")
set("mode", "pwm")
set("frequency", "500")
set("active", "1")

def clockwise():
    io.output(in1_pin, True)    
    io.output(in2_pin, False)

def counter_clockwise():
    io.output(in1_pin, False)
    io.output(in2_pin, True)

clockwise()

while True:
    cmd = raw_input("Command, f/r 0..9, E.g. f5 :")
    direction = cmd[0]
    if direction == "f":
        clockwise()
    else: 
        counter_clockwise()
    speed = int(cmd[1]) * 11
    set("duty", str(speed))

这个Python程序首先把两个GPIO针设置为输出针。然后定义了一个与第八课里面一样的为了使用方便的方法(“set”),用于写入PWM核心模块。后面我们将会用它设置PWM参数。

另外我们定义了两个方法,”clockwise”和”counter_clockwise”,它们通过控制输出针达到改变电机转向的目的。

如果两个输出针都置为高或者置为低,那么电机将会停止。如果一针为高一针为低那么电机将朝一个方向转动,如果两针的电平反转,那么电机的转向也将反转。程序循环等待用户输入一个字母(“f”或”r”)以及一个0到9之间的数字。字母设置了电机的转向数字设置了转速,数字将会乘以11然后变成一个0到99之间PWM库所期望的百分比值。

测试&配置

要运行这个程序,你需要超级用户权限,所以使用下面的命令吧:

sudo python motor.py

命令行将会提示你输入两个字符。试试下面的命令:

$sudo python motor.py
Command, f/r 0..9, E.g. f5 :f9
Command, f/r 0..9, E.g. f5 :r4
Command, f/r 0..9, E.g. f5 :

Adafruit的树莓派教程第九课:控制一个直流电机,首发于极客范 – GeekFan.net

Adafruit的树莓派教程第八课:使用伺服马达

概览

这节课我们来学习如何使用Python来控制一个伺服马达。

lesson8_1

伺服马达受不同长度的脉冲控制。这需要相当准确的定时。树莓派上有一针能通过硬件产生脉冲,而不需要依靠操作系统。Occidentalis系统有一个界面可以使用这一针来控制伺服马达。

你需要的:

  • 1个树莓派
    lesson8_2
  • 1个扩展板和1条26针的IDC电缆
    lesson8_3
  • 1把公对公的跳线
    lesson8_4
  • 1块小型面包板
    lesson8_5
  • 1个伺服马达
    lesson8_6
  • Adafruit Occidentalis 0.2或之后版本的操作系统发行版
    lesson8_7
  • 5号或7号电池座及4节电池
    lesson8_8

伺服马达

伺服马达的状态由脉冲的长度控制。伺服马达预期每20毫秒接受一次脉冲。如果脉冲的高电平持续1毫秒,那么伺服马达不会转动,如果是1.5毫秒,那它将会转过90度,如果高电平持续2毫秒,那它将会转动180度。

lesson8_9

伺服马达的终点位置可能不同,许多伺服马达只能转动大约170度。你也可以购买能”连续”旋转360度的伺服马达。

PWM与伺服马达核心模块(The PWM and Servo Kernel Module)

Adafruit与Sean Cross一起编写了一个核心模块被包含在了Occidentalis发行版里。更多的细节请参照这篇教程。如果你想在Raspbian或者其他发行版上使用这个模块,参考这里来把模块安装到你的环境里。

这个模块被称为PWM与伺服马达(PWM and Servo)因为在控制伺服马达的同时该模块可以产生PWM(Pulse Width Modulation,脉冲宽度调制)信号,(与额外电源配合)可被用于控制马达的功率或灯光亮度。这节课我们不会使用PWM。

PWM与伺服马达模块使用一种文件类型的接口,你可以通过读取和写入特殊的文件来控制输出针脚和伺服马达的行为。这使得使用Python或者其他语言来编写该接口十分容易。

用于驱动伺服马达的所涉及到的文件列在下方。所有文件可以在树莓派的/sys/class/rpi-pwm/pwm0/目录下找到。

文件 – 描述
active – 1为激活,0为未激活。你可以通过读取它来查找输出针是否被激活,或者通过改写控制它的激活或未激活。
delayed – 如果设置为1,你对其他文件的改动不会起作用直到你使用上面的active来激活输出针。
mode – 改写文件来设置针脚是pwm,servo(伺服马达)还是audio(音频)。显然这里我们要设置为servo。注意这些针也会被小派的音频输出使用,所以你不能在使用声音的同时控制一个伺服马达。
servo_max – 改写这个文件来设置伺服马达的最大角度。我们把它设置为180这样我们就可以很容易的把伺服马达置成0到180度之间的位置了。
servo – 改写这个文件将会设置伺服马达的脉冲长度到一个与servo_max有关的值。比如我们把它设置为90,servo_max的值为180,那伺服马达会保持在中间位置。

硬件

在小派上只有一个针脚能够产生这样的脉冲(GPIO 18针)。它将与伺服马达的控制针脚相连。伺服马达的电源由外接电池控制,因为使用小派的电源可能会在伺服马达开始转动的瞬间产生巨大的电流,导致小派崩溃。伺服马达需要4.8-6V的直流电来驱动马达,但是信号的逻辑电平(脉冲输出)可以是3.3V,所以可以直接把信号线直接连到GPIO的输出针上。

lesson8_10

小派扩展板用于连接树莓派和面包板,如果你之前没有使用过扩展板,你可以参考这个系列教程的第四节

伺服马达通常有一个三针的插座。红色和棕色用于供电(红色为正极)并且第三针黄色或橘黄色的用于控制信号。要把插座连接到面包板上,你需要使用公对公的跳线。

lesson8_11

软件

这个项目不需要安装任何Python库。

下面列出的程序使伺服马达前后摆动:

# Servo Control
import time
def set(property, value):
	try:
		f = open("/sys/class/rpi-pwm/pwm0/" + property, 'w')
		f.write(value)
		f.close()	
	except:
		print("Error writing to: " + property + " value: " + value)

def setServo(angle):
	set("servo", str(angle))

set("delayed", "0")
set("mode", "servo")
set("servo_max", "180")
set("active", "1")

delay_period = 0.01

while True:
	for angle in range(0, 180):
		setServo(angle)
		time.sleep(delay_period)
	for angle in range(0, 180):
		setServo(180 - angle)
		time.sleep(delay_period)

为了写文件方便,我写了一个工具方法叫做”set”。第一个参数是要被写入的文件名(属性名),第二个参数是要被写入的值。

在程序的开始部分写入了几个文件来关闭delay模式,设置mode为’servo’,设置伺服马达的最大角度为180度最后把输出针设置为激活状态。

一个叫做delay_period的变量用于存储伺服马达每一步的间隔秒数。

while循环会一直进行直到按下CTRL+C终止。在while循环中有两个相似的for循环,第一个从0到180度递增旋转角度,第二个刚好相反,从180到0度递减。

要安装个软件,使用SSH连接到小派上然后输入下面的命令:

nano servo.py

粘贴上面的代码然后使用CTRL+X然后按一下Y保存。

lesson8_12

然后在SSH窗口里输入下面的命令来使程序运行:

python servo.py

然后伺服马达就开始转动啦。

测试&配置

如果你想让马达转快一些,尝试改变delay_period到一个更小的值,例如0.001,如果想慢一些,把它增大到0.1.

如果你想控制多个伺服马达,像Adafruit I2C 16 channel servo / pwm controller里一样。你可以通过这篇教程来进行了解。

Adafruit的树莓派教程第八课:使用伺服马达,首发于极客范 – GeekFan.net