https ssl证书的工作原理及使用相关知识收集

SSL 与 数字证书 的基本概念和工作原理

前言

SSL是让人头大的东西,看起来很复杂,我学过信息安全课,但是对SSL仍然是模糊一片。对于数字证书也是一知半解,从来没有去认真研究过。只知道个大概,“反正就是对称加密和非对称加密”,详细的就不懂了。其实这些跟操作系统,计算机体系结构一样,是基础知识,即使你不是专门研究信息安全的,即使你平时用不到,这些东西也应该是必须了解的~ It’s not rocket science!

我这篇文章首先介绍有关信息安全的一些基本概念。然后分析数字证书的构成,用途以及SSL的工作原理。Enjoy!

一、为什么网络是不安全的?

计算机世界是基于网络的,根据目前网络的结构和实现,数据包在世界各地的路由器之间游荡,任何人都可以获得你的发送的数据包,从而获得你发送的数据。局域网内就更方便了,只要你开个Sniffer在那里监听,别人QQ聊天的信息一览无余啊~为什呢?我来简单解释一下计算机网络是如何传输数据的。

现实生活中,如果你请快递帮你寄东西,一般情况下,快递会把东西送到目的地,而不是其他地方。路由器就像是快递,在Internet上负责送数据。但和真实的快递不同的是,路由器会把你要发送的信息广播给离目的地更近的路由器,可能是一个路由器,也可能是多个路由器(别问我为啥,我不想深入了,有兴趣自己查资料)。这样你的信息就变成多份的了。复制虚拟的信息不值钱那~现实生活中的快递可不能复制你要寄的东西。一般情况下,只有一份数据会被目的计算机接收到,其他的拷贝在网络上游荡一段时间以后就被抛弃了。但是,这给黑客们有了很多可乘之机。他们在网络上监听很多垃圾信息,过滤掉没用的,留下他们感兴趣的,然后就可以偷窥别人隐私了。

正是因为网络有这样的问题,人们就发明了很多加密通信的手段,来保证自己的通信的内容不会被泄露。SSL和数字证书就是用来干这个的。

二、信息安全的基本概念

在解释SSL和数字证书之前,我觉得有必要解释一下几个有关信息安全的基本概念。

安全的定义

如果说两个人之间的通信是安全的,那么如何定义这个安全呢?

  1. 保密性(Confidentiality) 
    保密性应该很容易理解,就是只有你自己和你允许的人能看到相关的信息。这和物理文件的保密性是一样的。
  2. 完整性(Integrity) 
    所谓完整性就是你的信息没有被破坏或者篡改过。举个例子比如网络聊天,保证对方收到的信息就是你发出的信息也是信息安全的一部分。
  3. 可获得性(Availability) 
    可获得性是指你自己在需要的时候能够访问到信息或者保证对方能够收到你的信息。

通常,我们平时说的“安全”往往只包括第一点,保密性。其实后面两点也是很重要的,特别是在信息安全领域。如果没有完整性和可获得性,光保密又有什么用呢?回到我们的主题,SSL和数字证书主要关注的是前两点。至于可获得性就需要涉及到硬件,管理等等了。

认证与授权

现在的问题是,我们如何保证上面所定义的“安全”?通常,有以下两个方法:

  1. 认证(Authentication) 
    认证是证明你就是那个你所声称的那个人。举个例子,你说你是张三,然后去机场登机,机场工作人员怎么知道你就是张三呢?你必须出示你的身份证或者护照,这样就可以证明你就是那个你所声称的张三。在信息安全领域也一样,比如你想去google查看zhlmmc的邮件,然后google会问你要zhlmmc的密码,因为只有zhlmmc知道zhlmmc帐户的密码,如果你能说出那个密码,那么你就是zhlmmc,google就会把zhlmmc的邮件返回给你。有些文章把这个过程称为Identification。
  2. 授权(Authorization) 
    授权是指一个系统里面有很多用户,有些用户能做某些事情,有些用户不能做某些事情。比如Linux,很多用户可以同时通过认证而登录到Linux主机,但是只有root才能修改或删除系统文件,普通用户只能修改自己的home。

这里每一点都可能涉及很多不同的技术来保证过程的顺利进行。“授权”跟业务逻辑的牵扯比较大,SSL和数字证书更多的关注第一点。

三、加密与算法

加密是保护信息安全的常用手段之一。对信息的加密是需要加密算法的,如果加密算法被破解了,那么一切免谈。不过,基本上,要破解一个加密算法是非常非常困难的。至少,目前流行的加密算法还是安全的,所以我们也就不必考虑这个问题了。

散列(Hash)

经常用bt下载的人应该很熟悉这个。这就是MD5啊~虽然Hash不只是MD5,常见的还有SHA1。不过MD5最流行所以一般大家说的hash就是它了。值得一提的是,山东大学的王小云在2005年的时候发了一篇“ How to Break MD5 and Other Hash Functions”引起了信息安全界的轰动。虽然我没仔细研读过这篇paper,不过我相信按照paper里面的说法要破解MD5还是很费劲的,要不早就出乱子了。所以我们就不考虑这个问题了。那么究竟什么是MD5呢?我来简单解释一下。

Hash就是一个工具,能把任意大小的文档变成一个 固定大小(MD5是32个字符)的字符串。并且,这个过程是 不可逆的,也就是说,没有任何办法从那个字符串得到原来那个文档。还有很重要的一点是, 任意两个文档(哪怕极其相似)得到相同字符串的概率几乎等于0。现在你有一个10000字的文章,发给你的朋友,那你的朋友怎么判断他收到的文章一个标点符号都没有少呢?你在发送文章的同时把这个文章的Hash字符串也发过去,这样你的朋友收到文章以后,根据收到的文章重新计算一遍这个字符串,如果这个字符串和你发过去的一样,那就证明你朋友收到的文章是和你发送的一模一样。

对称加密(Symmetric Cryptography)

所谓加密就是把一段能看懂的东西通过某种变换变成看不懂的东西。当然这种变换是可逆的,否则加密有什么用啊!这里所说的“变换”就是加密算法。目前我们所说的加密算法基本上都是基于密钥的。加密算法不能单独工作,必须有密钥配合。就像现实生活中的锁,同一型号的锁的原理都一样,但是没把锁都有各自的钥匙,用来开锁和关锁。 加密的算法是公开的,但密钥是保密的。自己“发明”加密算法是很愚蠢的,除非你是密码学专家。历史上有很多使用自己发明的加密算法的笑话,往往你发明的算法都是自以为是,其实很容易破解的拉。而目前流行的加密算法都是经过时间和众人检验的,一般情况下,只要密钥不泄露,那就是安全的。有一点要说明的是,虽然我们平时一般说“加密算法”,但往往这个加密算法都包含解密算法的。 “对称加密”是指加密和解密的密钥是同一个。目前流行的对称加密算法有DES,AES,Blowfish等等。举个例子,你有一篇文章想要发给你朋友,但是你不想让别人看见这篇文章所以你选择AES加密。用的密钥是你和你朋友事先约定的,只有你们两个人知道。在发送之前,你用AES算法和约定好的密钥给文章加密,然后把加密过的文章发送给你的朋友。你朋友收到以后可以用AES算法和那个密钥解密而获得原始的那篇文章。 对称加密算法的优点是速度快,缺点是密钥管理不方便,要求共享密钥。

非对称加密(Asymmetric Cryptography)

如果你理解了上面讲的对称加密,那么这里的非对称加密就很简单了。从字面上理解就可以猜到, 加密和解密不是用的同一个密钥,其中一个称为公钥(public key),另一个称为私钥(private key)。公钥就是公开的,大家都知道,而私钥只有你自己知道。这两个密钥在数学上是有联系的,用公钥加密的内容只能由相应的私钥来解密,反过来,用私钥加密的内容只能由相应的公钥来解密。另外很重要的一点是, 不能从公钥推导出私钥,或者说很困难。常用的非对称加密算法有RSA,ECC等等。举个例子,你想要把一篇文章发送给你的朋友,但是不想让别人看到这篇文章。除了用上面讲的方法以外,你还可以用非对称加密来实现。在发送之前,你把文章用你朋友的公钥加密(公钥是公开的,每个人都知道),然后把加密过后的文章发送给你的朋友,你的朋友可以用他的私钥来解密。其他人获得了你传送的内容都是没有用的,因为只有你朋友有私钥可以解密。非对称加密算法的优点是密钥管理很方便,缺点是速度慢。

数字签名(Digital Signature)

我们先来看看现实生活中的签名是如何实现的。比如为信用卡账单签名,商家会打印一张消费单子给你,你看过以后觉得没有问题,于是在这张纸上签上自己的大名,表示你承认了这笔消费,并同意商家从你的信用卡账户扣钱。而商家可以对比你的签名和信用卡背后的签名是否一致来验证你是否冒用别人的信用卡(事实上很多商家不看的哦)。这个流程是基于一个假设的: 只有你自己能重现你的签名。虽然我们不能每次都签的一摸一样,但是通过笔迹鉴定,我们可以确定这个签名是否出自你手。分析一下,签名具有哪些特点呢?

  1. 不可伪造 - 通过笔记鉴定来保证。
  2. 不可移植,复制 - 复印,剪贴的签名当然无效咯!
  3. 不可否认 – 因为不可伪造,不可移植,不可复制,所以不可否认。

相似的,在虚拟世界里,我们有数字签名来帮助证明某个文档是你创建的,或者是你认可的。 数字签名所用的技术是散列和非对称加密。数字签名的假设是: 只有你自己有你的私钥。根据前面对散列的介绍,我们先为你要签名的信息生成一个Hash字串,Hash1,然后用你的私钥加密得到Encrypted(Hash1),这就是你对这个文档的数字签名。当别人需要验证某个文档是否是你签名的时候,只需要用你的公钥解密你的签名得到Hash1,并和该文档计算出来的Hash2对比,查看是否一致。如果一致则说明你确实对该文档签过名,否则就是没有。下面来分析一下,数字签名是如何保证上面所讲的签名的特点的。

  1. 不可伪造
    因为只有你有你自己的私钥,所以任何其他人都无法产生用你的私钥加密过的Hash1。
  2. 不可移植,复制
    你对文档A的签名不可能对文档B也有效,因为你对文档B的签名必然和对A的签名不一样,这是由Hash的唯一性保证的。拿你对A的签名去验证B是不可能通过的。
  3. 不可否认
    因为不可伪造,不可移植,不可复制,所以不可否认。

仔细想想数字签名和现实生活中的签名真的蛮像的,逻辑上是一样的。或许你在想,为什么要对Hash加密呢?我直接对文档用我的私钥加密不就完了嘛?对啊,效果是一样的,但是效率不一样哦~别忘了非对称算法是很慢的,加密一个100M的文件要算半天呢!

这里要顺便提一下消息认证码( Message Authentication Code)。 它和数字签名很相似,只不过它是用对称加密的而数字签名用的是非对称加密。

在现实生活中,各种加密手段往往是配合使用以达到最好的效果和效率。比如我将要介绍的SSL和数字证书,就是混合了各种的加密手段。

四、数字证书

上面讲了这么多都是前戏,现在该到主题了。前面提到的认证(Authentication)的时候说,现实生活中可以用身份证和护照来证明身份, 那么在虚拟世界里,数字证书就是身份证。和现实生活不同的是,并不是每个上网的用户都有数字证书的,往往只有当一个人需要证明自己的身份的时候才需要用到数字证书。那么什么时候需要证明自己的身份呢?普通用户一般是不需要的,网站并不关心是谁访问了网站,现在的网站只关心流量啊~反过来,网站就需要证明自己的身份了。比如你想要提交信用卡信息给预定航班的网站,那么你如何确定你正在访问的网站就是你所想要访问的那个呢?现在 钓鱼网站很多的。比如你想访问的是“www.ctrip.com”,但其实你访问的是“www.otrip.com”,所以在提交自己的信息之前你需要验证一下网站的身份,要求网站出示数字证书。一般正常的网站都会主动出示自己的数字证书。由于证书在网页浏览中最为常见,所以我下面举的例子都是基于浏览器的。

数字证书的构成

我们的身份证是由公安机关颁发的,并加有很多防伪技术,不能伪造(或者说很难)。同样的,数字证书也有专门的发证机关(Certificate Authority,简称CA,其实是一些商业公司啦)。比较常见的发证机关是VeriSign。数字证书的发证机关会对自己发放的证书加上自己的数字签名,以保证证书不能被伪造。那数字证书到底包含了些什么呢?

  • 持有者姓名(Common Name)
  • 发证机关(Issuer)
  • 有效日期(Validity)
  • 证书持有人的公钥(Subject’s Public Key info)
  • 扩展信息 (Extension)
  • 用发证机关对该证书的数字签名(Certificate Signature)

基本信息就这些了(这些信息会在后面的章节有所解释),为了更清晰的说明问题,来几张截图:


图1:数字证书的基本内容


图2:数字证书的结构


图3:数字证书详细内容

这几张截图都是我从Firefox里面拷贝出来的,这张证书已经过期了,不过不影响理解。从图2我们可以看到,Certificate(证书)和Signature(签名)是分开的,但其实这个Signature也是证书的一部分。可以这么理解,数字证书包含证书主体和数字签名。证书中的签名是对证书主体的签名。

如何验证数字证书?

好了,现在我们有了虚拟世界的身份证了,那如何使用呢?和现实生活中检查身份证一样,包含三个步骤:

1.    检查身份证防伪标记

数字证书的防伪标记就是发证机关的私钥加密的那段内容。如何验证?首先我们是默认拥有发证机关的公钥的。如果是浏览器的话,常见的发证机关的公钥是内置的。如下图所示:


图4:Firefox内置的发证机关的数字证书

虽然Firefox内置的是数字证书,但是有数字证书就有公钥,所以是一样的。当浏览器拿到一个数字证书,先看发证机关,然后找到相应的发证机关的证书,获得发证机关的公钥,用此公钥解密被加密的MD5,这样就获得了此证书的MD5值,我们称它为Hash1。然后浏览器用MD5算法对此证书重新计算一遍MD5,获得Hash2。然后比较Hash1和Hash2是否相等。如果相等就证明这张证书是由发证机关颁发的,并且没有被篡改过。回过头去看看上面讲Hash和MD5的部分,你应该能想明白为什么的。

2.    核对相貌

在现实生活中,你的身份证只有一张,你应该好好保管不被别人拿到。但难免钱包丢了,身份证跟着遭殃。所以我们在验证完身份证的真假之后我们要验证持证的人,和身份证上所声明的那个人是不是同一个,我们往往通过比较相貌来辨别。那在虚拟世界又是怎样的呢?你应该已经发现,任何人都可以拥有你的证书就像我们装的Firefox就有很多发证机关的证书。所以核对持有证书人的身份就很重要了。这就要依赖证书里面包含的公钥了。此公钥是这张证书所有者的公钥(注意,我这里指的是所有者,而不是持有者!),我们用此公钥加密一段信息发送给证书的持有者,如果持有者能发送回(可以是被私钥加密,也可以是明文,没有关系)被加密的这段信息的话就证明该持有者拥有该证书对应的私钥,也就是说,该持有者就是该证书的所有者。

3.    核对姓名

最后一步,也是最重要的一步。看清楚了,站在你面前的人的名字和登记在册的名字一样。举个例子,我拿着护照去机场登机,护照和人都没有问题,问题是我根本没有买机票。如果机场工作人员只核对了前面两步的话,我就可以登机了,岂不是很荒谬?同样的,在虚拟世界,比如那个“ctrip”的例子,你拿到了一个证书,并且验证没有问题,但是证书上的Common Name明明写的是“otrip”,你还继续吗?

如果这三个步骤都没有问题,你就可以确信正在和你通信的对方是可以信任的,是你想要联系的那个人。

数字证书的级联(Certificate Chain)

根据上述讨论,我们可以知道,所有数字证书都是基于另外一张默认为可信任(浏览器内置)的数字证书的。也就是说,我们必须用一张已知合法的数字证书去验证另外一张未知的数字证书。第二节提到的发证机关的数字证书就是默认为可信任的。事实上,发证机关的证书是自己签发给自己的,验证没有意义。因为这些证书是人工配置在我们电脑上的,所以默认为安全的。这些证书称为“根证书”。

由于申请证书的人数众多,发证机关忙不过来,需要一些代理来帮忙签发证书,有可能代理也需要代理来帮忙。这样就产生了证书的层级关系,如下图所示:


图5:级联的数字证书

这里的“www.paypal.com”是由二级代理“VeriSign Class 3 Extended Validation SSL SGC CA”签发的,而二级代理的证书又是由一级代理“VeriSign Class 3 Public Primary Certification Authority – G5”签发的,而一级代理的证书是由根证书机关“Buildin Object Token: Verisign Class 3 Public Primary Certification Authority”签发的。不必太关注这里的名字,名字而已,重要的是他们各自的位置。在验证这张证书的时候需要从下往上递归验证。先验证用户证书(最下面的证书,这里就是“www.paypal.com”),如果这样证书在浏览器的可信任列表里面那么验证到此结束,如果不是的话就要检查证书的防伪标记,这需要用到二级代理的证书,同样的,如果二级代理的证书在可信任列表里面,那么直接使用,否则就要检查二级代理证书的防伪标记,这需要用到一级代理的证书……直到根证书为止,如果根证书不在可信任列表里面,那么这张证书就没法验证了。这个过程的简单流程图是这样的:


图6:级联证书的验证流程

需要注意的是,这是一个递归过程,所以这里的返回只是返回到上层递归。对于我们这个例子中的级联证书的验证可能是这样的:


图7:级联证书验证流程示例

这个过程看起来没有什么问题。但是仔细一想,发现有一个大问题。任何一个拥有合法证书的人都可以给别人签发证书了,不就是在这个继承关系上面多加一层吗?黄粱大梦!事情没那么简单啦~能够签发证书的叫CA,不管是否是代理,它都是CA,只有CA的证书才能拥有下级,那如何判断一张证书是否是CA呢?还记得我们在第一节讲过的证书中包含的扩展信息吗?这里可以放很多东西,包括这张证书的合法用途,如下图所示:




图8:证书的扩展信息

这里我们很清楚的可以看到用户证书是不能作为CA来用的,白纸黑字写着“Is not a Certificate Authority”。而CA的证书也有不同的权限。“Maximum number of intermediate CAs”说明了这个CA的权限大小。如果这个数字是0(比如这里的二级代理的证书),说明这个CA只能签发用户证书,而不能再授权其他机构为CA。如果这个数字是1,说明这个CA可以再授权一层代理,以此类推。图中没有显示根证书的Extension,因为根证书没有Extension,没有表示没有限制。在验证级联证书的时候,浏览器会检查证书的Extension,如果某个证书超范围使用了,浏览器会发出警告的。级联证书为证书的签发带来了很大的方便和灵活性。事实上我们可以看到,任何一张用户证书都应该是级联的,至少拥有一个上级证书(根证书)。所以在我们前面的例子中的“ebiz.isir.cmu.edu”这张证书是很奇怪的,不是标准的证书。这张证书是无法验证的,只在学校内部网上使用,默认接收就行了(浏览器会把它当成根证书来处理)。

关于数字证书,我还有几点想要提一下:

  1. 数字证书本身不加密,加密的是数字证书的hash。数字证书加密了就很麻烦了,如何获知发证机关呢?不知道发证机关就不知道解密的公钥啊!还有,明文的数字证书可以显示数字证书的信息,即使不能验证数字证书的真伪,但是给了人为判断一个机会。
  2. 数字证书中的公钥可以是自己指定的,也可以是发证机关生成的。不同的发证机关可能有不同的要求。
  3. 申请证书的过程是安全的。如果申请证书的过程都不安全的话,后面的一切都免谈了。现实生活中,申请数字证书往往要求邮寄,或者电话,传真,甚至当面申请的。

五、SSL的基本原理

现在回到我们最原始的问题,由于Internet的架构问题,信息在网络上传输是很容易被别人获取的,那如何建立一个安全的传输网络呢?前面我们讨论了很多保证信息安全的技术,而SSL就是建立在这些技术的基础上的一套协议,用来保证通信的安全。SSL全称是 Secure Sockets Layer,它是一种间于传输层(比如TCP/ip)和应用层(比如HTTP)的协议。具体的SSL协议很复杂,我这里只讲一个大概。

最简单的方法来保证通信安全是用非对称加密。我们前面讲过数字证书的认证,如果双方都认证了对方的数字证书,那么每次传输信息的时候都用对方的公钥加密,这样就只有对方能解密,从而保证了信息的安全。但是对于日常应用(比如网页浏览)有两个问题:

  1. 非对称加密速度缓慢,消耗资源 
    如果客户端和服务器之间传输文件用非对称加密的话,速度一定慢的忍无可忍。
  2. 不可能要求每个用户都去申请数字证书 
    申请数字证书是一个相当麻烦的过程,要求每个上网的用户都拥有证书是不可能的事情。

SSL通过“握手协议”和“传输协议”来解决上述问题。握手协议是基于非对称加密的,而传输协议是基于对称加密的。根据不同的应用,SSL对证书的要求也是不一样的,可以是单方认证(比如HTTP, ftp),也可以是双方认证(比如网上银行)。通常情况下,服务器端的证书是一定要具备的,客户端的证书不是必须的。下面两张图片显示了SSL握手的过程。


图9:SSL握手,单方服务器认证


图10:SSL握手,双方认证

握手协议可以看成是客户端和服务器协商的一个过程,结果就是一个对称密钥,然后就进入了传输协议的部分。也许,你在想,“现在还不简单吗?用这个对称密钥加密传输数据呗!”。否,没那么简单。先来看一下结果,等会儿再解释原因。在通信双方协商出一个对称密钥以后,他们用这个密钥来加密传输的数据。同时为每个消息生成时间戳,用此密钥为消息和相应的时间戳生成消息认证码(MAC)。也就是说,每次发送的内容包括 Encrypt(message) + MAC(message + timestamp)

这么做有几个好处:

1. 防止消息的篡改

所谓消息篡改就是有第三者插在通信双方之间,篡改往来的消息。由于消息是加密的,第三者不能获得消息的内容,但是他可以闭着眼睛瞎改。如果没有MAC的话,接受者就无法判断此消息是否被篡改过。

2. 防止消息重放

消息的重放是只第三者记录下通信双方的每一次发送的消息,虽然他不能获得消息的内容。但是它可以通过重新发送客户端或者服务端的信息来把自己装成是客户端或者服务端。如果在MAC里面加上了时间戳,消息接收方验证时间戳就可以阻止消息的重放攻击。

SSL的基本思想是用非对称加密来建立链接(握手阶段),用对称加密来传输数据(传输阶段)。这样既保证了密钥分发的安全,也保证了通信的效率。

通过上面对SSL的分析,我们可以看到,SSL并不能阻止别人获得你传输的数据,但是由于你传输的数据都是加密过的,别人拿到了毫无用处,一样可以保护信息的安全。还有一点需要强调一下,SSL并不依赖于TCP,它可以建立在任何可靠的传输层协议(比如TCP)之上。也就是说SSL是不能建立在UDP之上的。这是显然的,如果传输都不可靠,偶尔丢两个包或者包的顺序换一换的话,怎么保证安全呢?

来源:http://www.linuxde.net/2012/03/8301.html

-----------------------

HTTPS证书颁发机构Startssl SSL申请图文详解

  一、什么是 SSL 证书,什么是 HTTPS 网站?

  SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socket layer(SSL)安全协议是由Netscape Communication公司设计开发。该安全协议主要用来提供对用户和服务器的认证;对传送的数据进行加密和隐藏;确保数据在传送中不被改变,即数据的完整性,现已成为该领域中全球化的标准。由于SSL技术已建立到所有主要的浏览器和WEB服务器程序中,因此,仅需安装服务器证书就可以激活该功能了)。即通过它可以激活SSL协议,实现数据信息在客户端和服务器之间的加密传输,可以防止数据信息的泄露。保证了双方传递信息的安全性,而且用户可以通过服务器证书验证他所访问的网站是否是真实可靠。

  二、什么网站需要 SSL 证书?

  就我遇到过的网站,配置了认证的证书的,大概有这么几类:

  1、购物交易类网站

  这个就不用说了,支付宝、Paypal等肯定会加密以保护你的密码安全。

  2、注册类站点

  有些大站点,注册会员或者登陆的时候,会专门通过SSL通道,来保护你的密码安全,比如:

  https://www.name.com/account/login.php

  https://idp.godaddy.com/login.aspx

  三、Startssl SSL申请详细步骤

  1,先要在Startssl上注册用户,注册界面如下,注册后需要等待审核通过。
  2、如果审核通过,你会在你注册的时候的邮箱内收到一封内容类似于下面的邮件,你按链接点过去,照提示一步一步就可以在你浏览器上安装一个证书了,这个证书用来做 Startssl 认证的,Startssl 只提供证书认证,所以如果你丢了证书,那只能重新注册用户了。
  3、当认证通过后,就可以看到下面的界面了,我们先做验证向导,这里需要我们有自己的域名,且有域名注册时的邮箱,这步的作用就是验证你是否是域名的拥有者,相应步骤如下。略
  4、下面再做https证书申请向导,相应步骤如下。记得一定要按提示保存好那个私钥文件,否则到后面证书文件得到了,私钥文件丢了,就没法在做认证了。
  5、下面就等待几个小时,去邮箱看看刚申请的域名https证书是否成功得到了,如果得到了,就去下载证书文件就是了,相应步骤如下。

  最后,Startssl SSL证书就算申请好了

--------------------

为你的安卓应用实现自签名的 SSL 证书

介绍

网络安全已成为大家最关心的问题. 如果你利用服务器存储客户资料, 那你应该考虑使用 SSL 加密客户跟服务器之间的通讯. 随着这几年手机应用迅速崛起. 黑客也开始向手机应用转移, 原因有下列3点:
手机系统各式各样, 缺乏统一的标准.
许多程序员缺乏手机应用开发经验.
更严重的是, 通过手机应用, 黑客可以得到手机用户的隐私数据, 如:日程安排, 联系人信息, 网页浏览历史记录, 个人资料, 社交数据, 短信或者手机用户所在的地理位置.
最为一个网络安全爱好者的我, 最近花了几个月的时间对50到60安卓应用进行安全分析, 结果发现这些应用存在许多安全漏洞.
下面我主要讲一讲, 怎样才能写出比较安全的安卓代码.

从最基本的开始讲.
阅读本文前, 最好先看下 Ranjan.D article 写的一篇跟安卓连接有关的文章:(http://www.codeproject.com/Articles/818734/Article-Android-Connectivity).
 下列代码用来打开一个 http 连接.

URL urlConnection = new URL("http://www.codeproject.com/");
 
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

不要在 http连接中打开:登陆页面, 或是传递用户名, 密码, 银行卡之类的重要个人资料. 这些重要个人数据应该通过 HTTPS 传输. (具体参看HTTPS).

HTTPS是什么?

HTTPS 其实就是个安全版的 http. HTTPS 能保证电子商务的交易安全. 如:网上银行.
像 IE 或者火狐浏览器, 如果出现下面的挂锁图标.

同时, 在浏览器的地址栏中以 https:// 开头, 这表示, 你的浏览器跟这个网站的数据往来都是安全的.
https 跟 http 的最大区别在于 https 多加了一个保障通讯安全的层.

像下列代码这样打开一个 https 连接, 可以保障这个连接的数据通讯安全.

URL urlConnection = new URL("https://www.codeproject.com/");
 
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
 
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
HTTPS 通过 SSL/TLS 传递数据.

SSL/TLS:

SSL (Secure Sockets Layer) 是一种在客户端跟服务器端建立一个加密连接的安全标准. 一般用来加密网络服务器跟浏览器, 或者是邮件服务器跟邮件客户端(如: Outlook)之间传输的数据.
SSL 能保障敏感信息(如:银行卡号, 社保卡号, 登陆凭证等)的传输安全. 一般情况下, 数据在浏览器跟服务器之间的传输使用的是明文格式, 这种方式存在资料被窃取的风险. 如果黑客能拦截浏览器跟服务器之间的通讯数据, 就能看到通讯的内容.

SSL/HTTPS and X.509 证书概述

你要是对 SSL 或 X.509 证书一无所知, 那我大概解释下. 对于那些打算用自签名证书(self-signed certificate)的人来说, 需要了解自签名证书跟花钱购买机构颁发的证书有什么区别. 
首先我们需要了解下 SSL 证书究竟是个什么东东? 其实它就包含俩部分: 1) 一个身份标识, 一个用来识别身份的东西, 有点类似警察叔叔通过护照或驾照查你的身份; 2) 一个公共密钥, 这个用来给数据加密, 而且只有证书的持有者才能解密. 简而言之, SSL 证书就俩个功能, 身份验证跟保障通讯过程中的数据安全.
另外还有一点很重要. 那就是一个证书可以给另外一个证书“签字”. 用 layman 的话说就是 Bob 用他自己的证书在别的证书上盖上 “同意” 两个红红的大字. 如果你信任 Bob (当然还有他的证书), 那么你也可以信任由他签发的证书. 在这个例子中, Bob 摇身一变, 成了证书颁发机构(Certificate Authority). 现在主流的浏览器都自带一大堆受信任证书颁发机构(trusted Certificate Authorities)(比如:Thawte, Verisign等).

最后我们讲一讲浏览器是怎么使用证书的. 笼统的讲, 当你打开下列连接的时候 “https://www.yoursite.com” :
服务器会给浏览器发一个证书.
浏览器会对比证书中的“common name”(有时也叫 “subject”) 跟服务器的域名是否一样. 例如, 一个从“www.yoursite.com” 网站发过来的证书就应该有一个内容是 “www.yoursite.com” 的 common name, 否则浏览器就会提示该证书有问题.
浏览器验证证书真伪, 有点像门卫通过证件上的全息图辨别你的证件是不是真的.  既然在现实生活中有人伪造别人的身份. 那么在网络世界也就有人造假, 比如用你的域名“www.yoursite.com” 来伪造一个安全证书.  浏览器在验证的时候, 会检查这个证书是否是它信任机构颁发的, 如果不是, 那么浏览器就会提示这个证书可能有问题. 当然, 用户可以选择无视警告, 继续使用.
一旦证书通过验证 (或是用户无视警告, 继续使用有问题的证书), 浏览器就开始利用证书中的公开密钥加密数据并传给服务器.

TLS (SSL)中的加密
一旦服务器发过来的证书通过验证, 浏览器就会利用证书中包含的公共密钥加密某个指定的共享密钥, 然后发给服务器. 这个加密过的共享密钥只能用服务器的私有密钥才能解密(非对称加密), 别人无法解密出其中的内容. 服务器把解密出来的共享密钥保存起来, 供本次连接会话专用. 从现在开始, 服务器跟浏览器之间的所有通讯信息都用这个共享密钥加密解密(对称加密).

理论部分就这么多, 下面我们来看几个例子.
在浏览器中打开网站 mail.live.com , 地址栏中会出现一个绿色图标, http 也会变成 https.
单击这个绿色图标, 然后点证书信息连接, 就能看到下列内容.

这是个 SSL 证书, 该证书是 Verisign 给 mail.live.cm 颁发的.
Verisign 是一个证书颁发机构, 它提示你的浏览器正在连接的网站是: mail.live.com, 需要跟这个网站的服务器建立一条安全连接进行通讯, 避免他人拦截或篡改浏览器跟服务器之间传递的数据.

MITM 攻击

MITM 攻击(MITMA)是指: 黑客拦截篡改网络中的通讯数据
被动 MITMA 是指黑客只能窃取通讯数据, 而在主动 MITMA 中, 黑客除了窃取数据, 还能篡改通讯数据. 黑客利用 MITMA 方式攻击手机要比攻击台式电脑容易的多. 这主要是因为使用手机的环境在不固定, 有些地方用手机连接上网并不安全, 尤其是那些对公众免费开放的无线网络热点.
证书颁发机构(CA)
·Symantec (which bought VeriSign's SSL interests and owns Thawte and Geotrust) 38.1% 市场份额
·Comodo SSL 29.1%
·Go Daddy 13.4%
·GlobalSign 10%
Jelly bean 版本的安卓系统中, 你可以在下列路径中找到证书颁发机构:
设置 -> 安全 -> 受信任的凭证.
Https 连接

URL url = new URL("https://www.example.com/");   
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();   
InputStream in = urlConnection.getInputStream();

如果你连接的服务器(www.example.com)传过来的证书是由机构颁发的, 这段代码就能正常运行.
但是如果你连的服务器用的是自己颁发的证书(self-singed certificate), 那就会出现错误.

什么是自签名证书( self-signed certicates)

自签名证书就是没有通过受信任的证书颁发机构, 自己给自己颁发的证书.
SSL 证书大致分三类:
由安卓认可的证书颁发机构(如: VeriSign), 或这些机构的下属机构颁发的证书.
没有得到安卓认可的证书颁发机构颁发的证书.
自己颁发的证书, 分临时性的(在开发阶段使用)或在发布的产品中永久性使用的两种.
只有第一种, 也就是那些被安卓系统认可的机构颁发的证书, 在使用过程中不会出现安全提示.

为什么有人喜欢用自签名证书 
免费. 购买受信任机构颁发的证书每年要交 100 到 500 美元不等的费用. 自签名证书不花一分钱.
自签名证书在手机应用中的普及率较高 (跟用电脑浏览网页不同, 手机的应用一般就固定连一台服务器.).
在开发阶段写的代码,  测试跟发布的时候也可以用.
最近一项调查表明, 810万个证书中, 只有 320万个是由受信任机构颁发的. 剩余490万证书中, 自签名的占48%, 未知机构颁发的占33%, 而不被信任的机构颁发的证书占19%.
无独有偶, 我的分析结果也表明, 起码有 60% 安卓应用使用自签证书.
个人以为, 在手机应用中使用自签名证书没什么不好, 既不需要花钱, 也不需要修改代码.(注:如果你用的是机构颁发的证书, 在产品发布阶段, 需要修改代码).

下面一般性的https请求代码

URL url = new URL("https://www.example.com/");   
HttpsURLConnection urlConnection = (HttpsURLConnection)
url.openConnection();   
InputStream in = urlConnection.getInputStream();
如果你使用上述的代代码去验证你的自己签署的证书,由于在android操作系统中自己签署的不能通过验证的,所以安卓应用软件将会抛出错误。因此你需要书写你自己的代码来检查你的自己签署的证书。
但是在这个领域中,安卓开发者犯了一个很大的错误,自己签署的证书在web开发中不是常见的,同时大多数安卓开发者来自于web开发者,所以开发者缺失在密码学的概念的知识。
在我分析中,我发现开发者仅仅是简单的复制、粘贴Stack Overflow和其他博客中允许你的应用默认信任所以证书的答案。即使大多说的答案表述仅仅在测试模式下可以使用,但是开发者简单地复制代码,将会导致应用软件在遭到中间件攻击和session黑客攻击是,表现的非常的脆弱!
例子:
http://stackoverflow.com/questions/2703161/how-to-ignore-ssl-certificate-errors-in-apache-httpclient-4-0
http://stackoverflow.com/questions/2012497/accepting-a-certificate-for-https-on-android?lq=1
http://www.caphal.com/android/using-self-signed-certificates-in-android/#toc_3
http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https

在使用自己签署的证书时一般性的错误

信任所以的证书
TrustManager的主要责任是去决定提出的认证证书应该是可信任的。如果证书是不可信任的,那么连接将会被终止。去认证远程的安全套接字识别,你需要用一个或者多个TrustManager(s)初始化SSLContext对象。

import org.apache.http.conn.ssl.SSLSocketFactory;
public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");
 
    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);
 
        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
 
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
 
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
 
        sslContext.init(null, new TrustManager[] { tm }, null);
   }
 
    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }
 
    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}
我发现,80到100个应用软件中,在20到25个应用中实现了上述的代码。

在上述的TrustManager接口中,可以实现信任所以的证书,不论是谁签署的或者即使他们发布的任何主题。这个接口将会允许接受ANY证书。接受任何的证书将会危害数据的完整性、安全性等等。
在上述的例子中,检查客户端可信任性,获得接受事件,检查服务器端可信任性是三点重要的功能。每一位开发者都应该留意这三点功能的实现上。但是却很少有开发者从不同的网站中搜索、负责上述的功能。

允许所有的主机名。
忘记检查证书是否在这个地址发布是有可能的。当证书接受了example.com的服务器,那么另外的一个域名也将被接受。

HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
 
DefaultHttpClient client = new DefaultHttpClient();
 
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
 
// Set verifier     
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
 
// Example send http request
final String url = "https://www.paypal.com”
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
 
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
上述的代码中,即使是错误的实现,也将会接受对任何域名的任何CA证书声明。

Mixed-Mode/No SSL.
应用软件开发者在相同的应用中使用最大安全、不安全的连接,或者不使用SSL将是免费的。这不是直接的SSL声明,但是和提到的没有向外的签署个有关,同时对于一般软件的使用者,检查是否使用一个安全的连接是不可能的。这将会为例如SSL剥离,或者像FireSheep这样的攻击开后门。
SSL剥离是另外的一种可以使MITMA登陆并抵制SSL连接方式。利用使用最大HTTP和HTTPS应用。SSL剥离依赖大量建立在点击链接、或者来自于没有SSL重定向保护的网站SSL连接。在SSL剥离中,Mallory用HTTPS://取代了没有保护的网站中http:// 链接中。因此,除非使用者注意到了链接被篡改了,Mallory可以完全地规避SSL保护。这样的攻击主要与浏览器应用、或者原生使用安卓WebView应用有关。
更多关于SSL剥离的信息:
http://security.stackexchange.com/questions/41988/how-does-sslstrip-work
http://www.thoughtcrime.org/software/sslstrip/
!
证书锁定
直接在代码中固定写死使用某个服务器的证书. 然后在应用中使用自己定义的信任存储(trust store)代替手机系统自带的那个, 去连接指定的服务器.
这样做的好处是, 我们既能使用自签名证书, 又不需要额外安装其他证书.
优势
安全性提升 - 采用这种方式, 应用不再依赖系统自带的信任存储(trust store). 使得破解这种应用变得复杂: 首先你要反编译, 修改完后, 还要重新编译.  关键是你不可能使用应用作者原先用的那个 keystore 文件重新颁发证书.
成本降低 - 证书锁定方式让我们可以在自己的服务器上使用免费的自签名证书,  调用自己写的 API. 虽说复杂了点, 可是像这种既不花钱, 还能提高应用安全的好事上哪找去?

缺点
适应性较差 - 一旦 SSL 证书出现变动, 应用也要跟着升级. 再发布到 Google Play. 然后祈祷用户能都升级到最新版本.
安卓的 SSLContext 自带的 TrustManager 无法让本文示例中提到的自签名证书通过验证. 解决的办法是自己定义一个 TrustManager 类. 然后用这个类去验证自签名证书. 
先把证书加载到 KeyStore, 然后用 KeyStore 生成一个 TrustManager 数组, 最后再用这个 TrustManager 数组创建 SSLContext.
本文的应用把服务器的证书直接存进应用的资源.(毕竟这个文件是所有用户都共用的, 而且也不会经常改动), 当然你可以把它存到别的地方.

实现的步骤

第1步: 创建自签名证书和.bks 文件

1) 
创建 BKS 或者 keystore, 需要用到下面这个文件,bcprov-jdk15on-146.jar, 版本很多, 我用的是这个:http://www.bouncycastle.org/download/bcprov-jdk15on-146.jar, 下载后, 把文件存到 C:\codeproject.
然后用 Keytool 生成 keystore 文件.(keytool 是 Java SDK 自带的文件, 跟javac 放在同一个目录下)在命令提示符窗口中输入 keytool 就能看到这个工具的各种选项说明. 或者输入下列路径运行.
"C:\Program Files (x86)\Java\jre7\bin>keytool".

2)
下面是用 keytool 生成 keysotre 文件的命令.  要是这个文件已经存在, 这一步可以忽略.
keytool -genkey -alias codeproject -keystore C:\codeproject\codeprojectssl.keystore -validity 365
这行命令创建一个别名为 code project 的密钥(key), 生成的文件名是 codeprojectssl.keystore. 执行文件生成过程中会要求输入密钥(key)跟keystore的密码诸如此类的东东. 这里需要注意下, 当要求你录入 Common name 的时候, 要填你的主机名. 本文例子用的是: codeproject.com
3)
keytool -export -alias codeproject -keystore C:\codeproject\codeprojectssl.keystore -file C:\codeproject\codeprojectsslcert.cer
这行命令将密钥(key)从 .keystore 文件导入 .cer 文件.

4) 
keytool -import -alias codeproject -file C:\codeproject\codeprojectsslcert.cer -keystore C:\codeproject\codeprojectssl.bks -storetype BKS -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath C:\codeproject\bcprov-jdk15on-146.jar
搞定! 现在, 全部 .bks 文件都生成了. 稍后将这些文件复制到安卓应用中. 连接那些使用自签名证书的服务器的时候会用到.
第2步

把 .keystore 文件复制到 /androidappdir/res/raw/
第3步

创建一个新类: MyHttpClient,  继承 DefaultHttpClient 类. 这个新类在验证SSL 证书的时候, 会自动加载我们自己创建的 keystore 文件, 而不是安卓自带的那个. 只要证书跟服务器匹配上了就没问题. 代码如下:

import java.io.InputStream;
import java.security.KeyStore;
 
import android.content.Context;
 
public class MyHttpClient extends DefaultHttpClient {
   
 private static Context context;
  
 public static void setContext(Context context) {
  MyHttpClient.context = context;
 }
 
 public MyHttpClient(HttpParams params) {
  super(params);
 }
 
 public MyHttpClient(ClientConnectionManager httpConnectionManager, HttpParams params) {
  super(httpConnectionManager, params);
 }
 
 @Override
    protected ClientConnectionManager createClientConnectionManager() {
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
         
        // 用我们自己定义的 SSLSocketFactory 在 ConnectionManager 中注册一个 443 端口  
        registry.register(new Scheme("https", newSslSocketFactory(), 443));
        return new SingleClientConnManager(getParams(), registry);
    }
  
    private SSLSocketFactory newSslSocketFactory() {
        try {
            // Get an instance of the Bouncy Castle KeyStore format
            KeyStore trusted = KeyStore.getInstance("BKS");
            // 从资源文件中读取你自己创建的那个包含证书的 keystore 文件
             
            InputStream in = MyHttpClient.context.getResources().openRawResource(R.raw.codeprojectssl); //这个参数改成你的 keystore 文件名
            try {
                // 用 keystore 的密码跟证书初始化 trusted                            
                trusted.load(in, "这里是你的 keystore 密码".toCharArray());
            } finally {
                in.close();
            }
            // Pass the keystore to the SSLSocketFactory. The factory is responsible
            // for the verification of the server certificate.
            SSLSocketFactory sf = new SSLSocketFactory(trusted);
            // Hostname verification from certificate
            // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
            sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); // 这个参数可以根据需要调整, 如果对主机名的验证不需要那么严谨, 可以将这个严谨程度调低些.
            return sf;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}
MyHttpClient 类的调用代码如下:

// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.google.com");
// 以 GET 方式读取服务器返回的数据
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();

-------------

Nginx配置SSL证书部署HTTPS网站

一、什么是 SSL 证书,什么是 HTTPS
SSL 证书是一种数字证书,它使用 Secure Socket Layer 协议在浏览器和 Web 服务器之间建立一条安全通道,从而实现:
1、数据信息在客户端和服务器之间的加密传输,保证双方传递信息的安全性,不可被第三方窃听;
2、用户可以通过服务器证书验证他所访问的网站是否真实可靠。
(via百度百科)

HTTPS 是以安全为目标的 HTTP 通道,即 HTTP 下加入 SSL 加密层。HTTPS 不同于 HTTP 的端口,HTTP默认端口为80,HTTPS默认端口为443.

二、什么网站需要使用SSL证书
1、购物交易类网站
不用多说,网上银行、支付宝、Paypal等肯定会全程加密以保护你的信息安全。

2、注册与登陆
一些大的网站,比如电子邮箱,注册会员或者登陆的时候,会专门通过SSL通道,保证密码安全不被窃取。

总之涉及到用户重要隐私及安全方面的都需要

三、自行颁发不受浏览器信任的SSL证书
为晒晒IQ网颁发证书。ssh登陆到服务器上,终端输入以下命令,使用openssl生成RSA密钥及证书。

# 生成一个RSA密钥 
$ openssl genrsa -des3 -out 33iq.key 1024
 
# 拷贝一个不需要输入密码的密钥文件
$ openssl rsa -in 33iq.key -out 33iq_nopass.key
 
# 生成一个证书请求
$ openssl req -new -key 33iq.key -out 33iq.csr
 
# 自己签发证书
$ openssl x509 -req -days 365 -in 33iq.csr -signkey 33iq.key -out 33iq.crt
第3个命令是生成证书请求,会提示输入省份、城市、域名信息等,重要的是,email一定要是你的域名后缀的。这样就有一个 csr 文件了,提交给 ssl 提供商的时候就是这个 csr 文件。当然我这里并没有向证书提供商申请,而是在第4步自己签发了证书。

使用openssl生成密钥和证书

编辑配置文件nginx.conf,给站点加上HTTPS协议

server {
    server_name YOUR_DOMAINNAME_HERE;
    listen 443;
    ssl on;
    ssl_certificate /usr/local/nginx/conf/33iq.crt;
    ssl_certificate_key /usr/local/nginx/conf/33iq_nopass.key;
    # 若ssl_certificate_key使用33iq.key,则每次启动Nginx服务器都要求输入key的密码。
}
重启Nginx后即可通过https访问网站了。

自行颁发的SSL证书能够实现加密传输功能,但浏览器并不信任,会出现以下提示:
不信任的安全证书

四、受浏览器信任的证书
要获取受浏览器信任的证书,则需要到证书提供商处申请。证书授证中心,又叫做CA机构,为每个使用公开密钥的用户发放一个数字证书。浏览器在默认情况下内置了一些CA机构的证书,使得这些机构颁发的证书受到信任。VeriSign即是一个著名的国外CA机构,工行、建行、招行、支付宝、财付通等网站均使用VeriSign的证书,而网易邮箱等非金融网站采用的是中国互联网信息中心CNNIC颁发的SSL证书。一般来说,一个证书的价格不菲,以VeriSign的证书为例,价格在每年8000元人民币左右。

据说也有免费的证书可以申请。和VeriSign一样,StartSSL也是一家CA机构,它的根证书很久之前就被一些具有开源背景的浏览器支持(Firefox浏览器、谷歌Chrome浏览器、苹果Safari浏览器等)。后来StartSSL竟然搞定了微软:在升级补丁中,微软更新了通过Windows根证书认证(Windows Root Certificate Program)的厂商清单,并首次将StartCom公司列入了该认证清单。现在,在Windows 7或安装了升级补丁的Windows Vista或Windows XP操作系统中,系统会完全信任由StartCom这类免费数字认证机构认证的数字证书,从而使StartSSL也得到了IE浏览器的支持。(来源及申请步骤)

五、只针对注册、登陆进行https加密处理
既然HTTPS能保证安全,为什么全世界大部分网站都仍旧在使用HTTP呢?使用HTTPS协议,对服务器来说是很大的负载开销。从性能上考虑,我们无法做到对于每个用户的每个访问请求都进行安全加密(当然,Google这种大神除外)。作为一个普通网站,我们所追求的只是在进行交易、密码登陆等操作时的安全。通过配置Nginx服务器,可以使用rewrite来做到这一点。

在https server下加入如下配置:

if ($uri !~* "/logging.php$")
{
    rewrite ^/(.*)$ http://$host/$1 redirect;
}
在http server下加入如下配置:

if ($uri ~* "/logging.php$")
{
    rewrite ^/(.*)$ https://$host/$1 redirect;
}
这样一来,用户会且只会在访问logging.php的情况下,才会通过https访问。

更新:有一些开发框架会根据 $_SERVER[‘HTTPS’] 这个 PHP 变量是否为 on 来判断当前的访问请求是否是使用 https。为此我们需要在 Nginx 配置文件中添加一句来设置这个变量。遇到 https 链接重定向后会自动跳到 http 问题的同学可以参考一下。

server {
    ...
    listen 443;
    location \.php$ {
        ...
        include fastcgi_params;
        fastcgi_param HTTPS on; # 多加这一句
    }
}
 
server {
    ...
    listen 80;
    location \.php$ {
        ...
        include fastcgi_params;
    }
}
来源:http://www.lovelucy.info/nginx-ssl-certificate-https-website.html

参考链接:
http://zou.lu/nginx-https-ssl-module
http://blog.s135.com/startssl/
http://www.baalchina.net/2008/08/nginx-https-rewrite/

----------------

SSL证书与Https应用部署小结

为了提高网站的安全性,一般会在比较敏感的部分页面采用https传输,比如注册、登录、控制台等。像Gmail、网银等全部采用https传输。

https/ssl 主要起到两个作用:网站认证、内容加密传输和数据一致性。经CA签发的证书才起到认证可信的作用,所有有效证书均可以起到加密传输的作用。
浏览器与SSL证书

上图是IE和Chrome上对https的不同表现。

Chrome 网站安全性指示器说明:http://support.google.com/chrome/bin/answer.py?hl=zh&answer=95617
SSL最主要应用是在浏览器和Web服务器之间,尽管不限于此。当然,安全本身是重要的内在属性。但在表面上看,部署SSL 就是为了让用户浏览器里看起来更安全一些,以增加用户的信任感。所以很多企业更把它当作门面,而签发机构也为此卖高价,尤其是国内的价格明显高于国外的。
实际上SSL证书也可以做客户端认证,用户拥有自己特有的证书,用它可以证明自己的身份,当然也就用不着用户名和密码了。但这种用的很少,一般web服务器也不支持。
内容加密传输更安全,如果只是为了加密,使用自签发的证书也可以,但浏览器无法验证证书,所以会给出一个非常吓人的警告,所以自签发证书不适合给外人使用,只适合内部使用,把这个证书 加入到自己的信任列表或忽略证书验证即可,以后就不会继续拦截了。
证书需要被少数一级或二级 CA 认证才有效。计算机安全中的信任就是一个信任链的关系,信任链最顶端的被称为根证书。
自签发的证书在技术上是完全一样的,仅用于加密传输是没问题的。但是不能被外人信任,所以一般仅用于内部使用。除了自签发不被信任,如果证书过期、已被吊销或者非证书所代表的域名也都是不被信任的,导致证书验证出错。
用于网站的证书需要被大众信任,所以不能自签发的证书,那就申请(购买)一个吧。

申请证书
1.证书类别
按证书包含域名数量分为:
  • 单域名:只针对这个域名有效,不能用在其它域名下。
  • 多域名:只针对列出的多个域名有效。
  • 通配符域名(wildcard):对任意子域名有小,显示的是 *.example.com。
注意:SSL所说的单个域名是一个完整的域名,一个子域名就算一个,而非一个顶级域名。
如果网站有很多子域名,只需要申请真正需要的域名证书。
按验证的类别分:
  • 域名认证(Domain Validation):认证你的域名所有权和网站,申请验证简单,几分钟即可。
  • 组织机构认证(Organization Validation):认证的域名和公司信息,需要提交公司资料认证。
  • 扩展认证(Extended Validation,简称EV):这种证书会在浏览器中出现“很明显”的绿色地址栏,给用户的可信度最高。有安全评估保证。
个人或小站点可用一类或二类,企业一般用二类认证,少数企业会用到EV认证。

2. 证书价格
看了看网上SSL证书的价格,便宜的一般都是10美元左右一个子域名/每年,按不同类别、不同品牌等价格在几十美元到几百美元一年。比如能显示绿色地址栏的EV证书和通配符证书贵一些。国内自己的或代理的,比国外贵不少,动辄几千元。其实就是由可信源认证了一下,类似于办证,用起来没什么差别,并非越贵越好。
3. 签发机构(“卖家”)

国外常见的SSL提供商有:Thawte,Go Daddy,VeriSign,RapidSSL,GeoTrust(QuickSSL),StartSSL,Comodo。

StartSSL、Go Daddy的比较便宜,GeoTrust、Comodo的价格适中,Thawte和VeriSign的价格较贵。
VeriSign现在归属赛门铁克,在国内是由天威诚信代理的。世界真小,天威诚信就在我很多年以前的东家(启明星辰)大楼里,地下一层是他们的机房,我还进去过一次。
4. 免费的StartSSL
唯一免费的是StartSSL,其它的一般只提供30免费试用。
但 StartSSL 提供的免费证书是一类的、仅对域名和email进行验证,不对组织做验证(也就是面向自然人的,非面向组织机构的),不过
仅作为域名验证和数据加密也够了,并且浏览器也认它,一般人也不会去看你的证书级别。适合个人和初创网站使用,以后有钱了再申请个收费的替换即可。

我很顺利地申请到了免费的StartSSL证书,分别用在两个子域上。
最后,证书签发给你后,最主要是保护好私钥证书,这个丢失或泄漏就完了。因为如果被别人利用也就毫无安全性了,需要向证书签发机构申请撤销证书并申请新的证书,这当然也是要收费的。
应用规划、配置和调整
并不是说有了SSL证书就没事了,还要考虑应用中的使用问题,需要规划、服务器配置、应用调整等多个环节。
SSL比 http 要消耗更多cpu资源(主要是在建立连接的阶段,之后还要对内容加密),所以对一般网站,只需要对部分地方采用https,大部分开放内容是没必要的,具体取决于你的业务要求。比如对于很多安全要求较低的网站,完全不用https也是可接受的。
某些页面是同时支持 http 和 https ,还是只支持 https、强制 https?
同时支持就是用户用什么协议访问都可以,那么用户的请求主要就是由页面本身的链接引导来的,因为一般用户不会自己特意去修改地址栏的。
一般我们的网站可以做成同时支持http和https,都可以访问。但是这就容易有后面说的混合内容或混合脚本的问题。
还可以规划为部分页面支持 https,一般公开页面不用https,只是将部分地方的链接改为 https 就可以了。专门期望以 https 访问的页面中,引用的绝对URL可以明确的使用 https链接。
是否强制 https ?对于安全性高的网站或网站中的部分页面,可以强制使用https访问, 即使用户在地址栏里手工把 https 改为 http, 也会被自动重定向回 https 上。比如可以通过配置web服务器 rewrite 规则将这些 http url 自动重定向到对应的 https url 上(这样维护比较简单),而不用改应用。
解决混合内容问题(http和https)
混合内容是指:在https的页面中混合了非https的资源请求,比如图片、css、js 等等。如果是混合了非 https 的 js 代码,则被称为混合脚本。
混合内容的危害:如果只是混合了不安全的图片和css,那么受中间人攻击篡改,一般只会影响页面的显示,危害相对小一点。如果是混合了不安全的 js 代码,则这个不安全的 js 可以完全访问和修改页面中的任何内容,这是非常危险的。
另请参看,Chrome对混合脚本危害的说明与提示:Trying to end mixed scripting vulnerabilities
所以,只有页面本身和所有引用的资源都是 https 的浏览器才认为是安全的,只要其中引用了非安全资源(即使图片),浏览器都会给出不安全的提示,特别是有 js 的情况。如果浏览器提示不安全,那样我们就达不到原来目的了。我们费了半天功夫去申请 SSL 证书,配置Web服务器,最后如果因为混合内容而前功尽弃就太糟了。咱继续努力吧,想办法让所有引用资源都是安全的。
理论上,混合了第三方的内容,即使是SSL的第三方内容也不是很好。因为用户信任的是你,而不是第三方,即使第三方也支持https,但你能保证第三方就绝对安全吗。不引用任何第三方才是绝对安全的,但这样太严格了,安全其实也是一个 tradeoff 的问题,需要考虑很多方面的平衡。还好,起码现在浏览器认为已经是安全的了。
引用第三方文件的问题(如 CDN 分发的文件)

简单地说,这个问题要么有第三方提供 https 支持,要么不用它(用自己本地的)。
一般我们会引用由 CDN 分发的文件,比如某个 js 库文件,而不用访问自己网站上的,这样借助 CDN 网络可以加快速度,这当然很好。
但是,如果我们在页面中使用绝对 URL 直接引用这个文件就无法自动使用 https 了!出现了混合协议内容,浏览器又该“变脸”了。
当SSL 遇上CDN 或 其它第三方文件就有点麻烦,因为很多CDN还不支持SSL。如果支持 https 的话就可以直接用 https 的绝对URL了,即使是同时支持http 和 https 的页面,这样做也不算太浪费,起码解决了问题。
因为CDN的云文件提供者,一般为每个cdn用户创建一个单独的子域名来使用,这样的话,CDN提供者要想支持 https 就必须支持所有可能的子域名,因此要求CDN提供方使用那种通配符子域名的证书。
相对 URL、绝对 URL 与 只缺协议的URL(Protocol Relative URL)
相对路径比较简单,自动匹配用户请求的 http 或 https 协议。
但是绝对 url 则不成,因为绝对 url 已经明确地写上了协议: http://www.example.com/jquery.js 。
这个问题还有一个办法解决,你一定没见过这种形式: //www.example.com/jquery.js
哈哈,一个缺少协议的URL(实际上还算是相对URL),这种形式可以在浏览器中被正确补充上合适的协议!很多人都用这种方法。
但是,这里有点小问题,IE7 和 IE8 处理这种缺少协议的URL的css 文件时,同一个css文件会下载两次,详见Steve的文章 。
JS 自动判断当前协议
现在我们经常用 js 来加载其它 js 文件或 其它别的文件,如果是请求是相对URL则没问题,如果是绝对URL怎么办?
其实 js 脚本可以这样:document.location.protocol 等于 'http:' 还是 'https:' 来判断。例如在 Google Analytics 的嵌入代码中:
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
应用程序中如何判断访问协议
对于动态页面,如 jsp、php等,也是可以动态判断当前是否使用了 https 协议的。所以应用可以根据动态判断,来生成不同的引用 URL。这样虽然有点麻烦,但也算是解决了自动识别协议的问题,当然相对路径总是不需要处理的。
比如在 jsp 中:
  • request.isSecure() 为true 表示当前为 https ,false表示 http 访问
  • request.getScheme() 返回字符串 https 或 http
注意,如果 tomcat 部署在其它web服务器代理的后面,需要正确配置好才能返回正确结果,见本文最后一部分。
同源策略的问题
最后提醒一点:http 和 https是不同源的!即使后面的内容都一样。所以 ajax 发请求的时候要使用正确协议的绝对URL才行。
相对URL的 ajax 请求没关系。

Nginx 配置
小结一下 Nginx 配置SSL注意的问题,详细安装配置内容请参考其它资料,如官方 SSL模块 和 https配置文档。
1. 首先检查一下是否已安装了 SSL模块,因为默认是不包含的。
用 nginx -V 命令检查一下。如果没有ssl模块则需要重新安装(建议升级到最新版本),注意安装时加上ssl 选项:
./configure --with-http_ssl_module
另外,nginx需要依赖 openssl 提供ssl支持,这个也要有。
2. nginx.conf 中的典型配置示例
listen     80;
listen    443 ssl;
ssl_certificate      cert.pem; #修改具体文件
ssl_certificate_key  ssl.key; #修改具体文件
ssl_session_cache    shared:SSL:10m;
ssl_session_timeout  10m;
ssl_protocols  SSLv2 SSLv3 TLSv1;
ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers   on;

上面第2-4项是关键。这些配置放在 server 块就可以对其中的所有 location 生效了,并且同时支持 http 和 https 。或者把 http 和 https 分开配置也很常见。
3. 合并证书配置文件
和Apache配置不同,Nginx需要将服务器证书和ca证书链合并到一个文件中,作为 ssl_certificate 配置的内容。
例如,按照证书链从下向上的顺序,我有三个证书:
  1. ssl.crt(自己域名的服务器证书)
  2. sub.class1.server.ca.pem(startssl 的一类证书)
  3. ca.pem(startssl 的根证书)
把它们的内容按顺序连接到的一个文件中,每个内容另起一行,中间没有空行或空格。
4. 避免启动时输入密码
配好之后,启动nginx 要你输入密钥的密码。这是因为 ssl_certificate_key 配置对应的文件(也就是 startssl 给你的私钥文件)内容是加密的,需要输入你创建这个时设置的密码才能解密。这样私钥虽然很安全,但是每次重启服务都要输入一次密码也太麻烦了。其实,只要证书改为解密了的内容,就可以避免每次输入密码。用如下命令即可:
openssl rsa -in ssl.key -out newssl.key  输入密码,就生成了解密后的私钥内容,使用这个就OK了。
但是就像前面说的,一定要在服务器上保护好它,例如:
chmod 400 ssl.key (仅root可读)
5. 优化SSL配置
SSL 很消耗 CPU 资源,尤其是在建立连接的握手阶段。一是通过开启 keepalive 可以重用连接。二是可以重用和共享ssl session,见上面ssl_session相关配置。
独立Tomcat+SSL
Tomcat 是很常见的 Java应用服务器,当然也可以作为独立的 Web服务器,所有用户请求直接访问 tomcat。
如果 Tomcat 作为独立的Web服务器,那么就需要配置Tomcat就可以了,文档参考这里 和 这个。主要是配置存放证书的 Keystore 和 连接器Connector。
Java的keystore
keystore 是 Java 中专用并内置的一个类似于 openssl 的工具,一个 keystore 文件就是一个“保险箱”(database),专门存放证书和密钥,和相关的管理功能:生成自签发的证书、密钥、导入导出等。可以通过 keytool 命令或 Java api 交互。

利用keytool 命令将你的证书导入进去。
Tomcat中Connector
tomcat中有三种 Connector 实现:block、nio 和 APR。前两者使用Java SSL(这需要 keystore 的配置 ),APR使用OpenSSL(不需要用keystore,直接指定证书),配置略有不同。
Nginx+Tomcat+SSL
实际上,大规模的网站都有很多台Web服务器和应用服务器组成,用户的请求可能是经由 Varnish、HAProxy、Nginx之后才到应用服务器,中间有好几层。而中小规模的典型部署常见的是 Nginx+Tomcat 这种两层配置,而Tomcat 会多于一台,Nginx 作为静态文件处理和负载均衡。
如果Nginx作为前端代理的话,则Tomcat根本不需要自己处理 https,全是Nginx处理的。用户首先和Nginx建立连接,完成SSL握手,而后Nginx 作为代理以 http 协议将请求转给 tomcat 处理,Nginx再把 tomcat 的输出通过SSL 加密发回给用户,这中间是透明的,Tomcat只是在处理 http 请求而已。因此,这种情况下不需要配置 Tomcat 的SSL,只需要配置 Nginx 的SSL 和 Proxy。
在代理模式下,Tomcat 如何识别用户的直接请求(URL、IP、https还是http )?
在透明代理下,如果不做任何配置Tomcat 认为所有的请求都是 Nginx 发出来的,这样会导致如下的错误结果:
  • request.getScheme()  //总是 http,而不是实际的http或https
  • request.isSecure()  //总是false(因为总是http)
  • request.getRemoteAddr()  //总是 nginx 请求的 IP,而不是用户的IP
  • request.getRequestURL()  //总是 nginx 请求的URL 而不是用户实际请求的 URL
  • response.sendRedirect( 相对url )  //总是重定向到 http 上 (因为认为当前是 http 请求)
如果程序中把这些当实际用户请求做处理就有问题了。解决方法很简单,只需要分别配置一下 Nginx 和 Tomcat 就好了,而不用改程序。

配置 Nginx 的转发选项:
proxy_set_header       Host $host;
proxy_set_header  X-Real-IP  $remote_addr;
proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto  $scheme;

配置Tomcat server.xml 的 Engine 模块下配置一个 Value:
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For"protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
配置双方的 X-Forwarded-Proto 就是为了正确地识别实际用户发出的协议是 http 还是 https。X-Forwarded-For 是为了获得实际用户的 IP。
这样以上5项测试就都变为正确的结果了,就像用户在直接访问 Tomcat 一样。
来源: http://han.guokai.blog.163.com/blog/static/136718271201211631456811/
-----------------

配置HttpListener侦听SSL连接详解

摘要:具体来说,要让HttpListener能够接受https请求,需要进行如下的配置......

借助http.sys和.NET 2.0中新增的System.Net.HttpListener类,程序员无需借助IIS就能实现自己的Web服务器,而且代码非常简洁。对此,网上已经发布了不少介绍性的文章,例如:《在没有IIS的条件下运行ASMX》(英语原文:“Run ASMX Without IIS”)、VS2005 Beta1, WSE2.0, http.sys and the HTTPListener: Look Ma, NO IIS以及Using Http.Sys to receive messages with WSE 2.0。

下面是HttpListener的一个最小的完整例子(需要VS.NET 2005 Beta 2):

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Threading;
using System.IO;

namespace MiniHttpsSrv
{
    class Program : IDisposable
   {
        static void Main(string[] args)
        {
            MiniHttpsSrv.Program server = new Program();
            server.Run();
        }

HttpListener listener = null;

public void Run()
        {
            this.listener = new HttpListener();
            listener.Prefixes.Add("http://+:8000/");
            listener.Prefixes.Add("https://+:8001/");
            listener.Start();
            while(true)
            {
                HttpListenerContext context = listener.GetContext();
                ThreadPool.QueueUserWorkItem(new WaitCallback(Program.OnGetContext), context);
            }
        }

public static void OnGetContext(object objContext)
        {
            try
            {
                HttpListenerContext context = (HttpListenerContext)objContext;
                Console.WriteLine("(" + Thread.CurrentThread.ManagedThreadId + ")" 
                    + DateTime.Now.ToShortTimeString() + " - " 
                    + context.Request.Url);
                context.Response.ContentType = "text/html";
                StreamWriter writer = new StreamWriter(context.Response.OutputStream);
                writer.WriteLine("<html><body><b>It's now " + DateTime.Now + 
                    "</b><br/><h1>Hey, I have got your request to <i><u>" + 
                    context.Request.Url + "</u></i> </h1></body></html>");
                writer.Flush();
                context.Response.Close();
            }
            catch (System.Net.HttpListenerException exception)
            {
                Console.WriteLine(exception.Message + "\r\n" + exception.StackTrace);
            }
        }

IDisposable Members
    }   
}
从上面的代码可以看到,HttpListener也能够支持HTTPS:

listener.Prefixes.Add("https://+:8001/");
但是要让这行代码工作真正工作起来,需要事先对http.sys进行配置。如何配置,网上也有几篇文章谈及,例如Configure System.Net.HttpListener to listen for SSL以及Simple Secure Indigo (HTTPS),但说得还不够细致。具体来说,要让HttpListener能够接受https请求,需要进行如下的配置:

前提条件:IIS 6已经安装。下面需要利用IIS 6的mmc(既inetmgr.exe)来帮助倒入证书和察看证书的thumbprint。
 
按照《按部就班——图解配置IIS5的SSL安全访问》所述步骤,在IIS 6上配置好服务器端证书。这篇Blog极其详细,虽然说的是IIS 5以及Windows 2000上的证书服务,但IIS 6和Windows 2003上的证书服务大同小异,只有界面上的少许差别。配置完成后,可以在inetmgr.exe中到"View Certificate..."察看证书的细节了: 
 
(这一步可以跳过)用winhttpcertcfg.exe检查确认证书已经被正确的安装了。在命令行运行“winhttpcertcfg.exe -l -c LOCAL_MACHINE\My -s atc-zhengzy”(这里atc-zhengzy是证书的Friendly name),将会看到:
  
运行httpcfg.exe(Windows XP SP2上的httpcfg.exe可以在Microsoft网站下载)将上一步安装好的证书加到http.sys的端口配置中:在命令行运行“httpcfg set ssl -i 0.0.0.0:8001 -c MY -h cd8c7c1958441e53eb4f9f6ba59b271ffb1aa59”,其中-h后面所跟的字符串就是第二步中看到的证书的Thumbprint,-i后面的端口要和代码中HttpListener所监听的https端口一致。如果返回结果“HttpSetServiceConfiguration completed with 0”,表明配置成功。
 
(这步可以跳过)检查确认第四步运行成功。在命令行运行“httpcfg query ssl”,应该看到的结果是:略
  
现在就可以运行前面例子代码实现的MiniHttpsSrv了,同时,IIS 6可以停掉,也可以继续运行,不会影响MiniHttpsSrv在8000和8001端口的服务。
 
测试:IE里面输入https://localhost:8001/blahblah或者http://localhost:8000/blahblah都可以看到echo back的结果:
  
另外,.NET 2.0里面还新增了System.Net.Security.SslStream类,用来实现一个SSL的服务器也很简单,可以在运行时直接从.cer文件中装载证书。

证书及端口的配置也可参考下面的

获取证书的指纹

使用证书 MMC 管理单元查找用于客户端身份验证的 X.509 证书。  有关详细信息,请参见 如何:使用 MMC 管理单元查看证书.  
访问证书的指纹。  有关详细信息,请参见 如何:检索证书的指纹.  
将证书指纹复制到文本编辑器,如 Notepad。
移除十六进制字符之间的所有空格。  完成此操作的一种方法是使用文本编辑器的“查找和替换”功能,将每个空格替换为空字符。

将 SSL 证书绑定至端口号

在 Windows Server 2003 或 Windows XP 中,对安全套接字层 (SSL) 存储区使用 HttpCfg.exe 工具的“set”命令将证书绑定至端口号。  该工具使用指纹识别证书,如下面的示例所示。  
httpcfg set ssl -i 0.0.0.0:8012 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6
-i 开关的语法为 IP:port,指示该工具将证书设置为计算机的端口 8012。  另外,也可将端口号前面的四个零替换为计算机的实际 IP 地址。  
-h 开关指定证书的指纹。
在 Windows Vista 中使用 Netsh.exe 工具,如下面的示例所示。
netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF} 
certhash 参数指定证书的指纹。
ipport 参数指定 IP 地址和端口,功能类似于前述 Httpcfg.exe 工具的 -i 开关。
appid 参数为可用于标识所属应用程序的 GUID。

将 SSL 证书绑定至端口号并支持客户端证书

在 Windows Server 2003 或 Windows XP 中,若要支持在传输层使用 X.509 证书进行身份验证的客户端,请按照前面的步骤进行操作,但要向 HttpCfg.exe 另外传递一个命令行参数,如下面的示例所示。
httpcfg set ssl -i 0.0.0.0:8012 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6 -f 2
-f 开关的语法为 n,其中 n 是介于 1 到 7 之间的一个数字。  值为 2 可在传输层启用客户端证书,如上面的示例所示。  值为 3 可启用客户端证书并将这些证书映射至 Windows 帐户。  请参见“HttpCfg.exe 帮助”以获取其他值的行为。  
在 Windows Vista 中,若要支持在传输层使用 X.509 证书进行身份验证的客户端,请按照前面的步骤进行操作,但要另外提供一个参数,如下面的示例所示。
netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF} clientcertnegotiation=enable

删除端口号的 SSL 证书

使用 HttpCfg.exe 或 Netsh.exe 工具查看计算机上的端口和所有绑定的指纹。  若要将信息输出到磁盘,请使用重定向字符“>”,如下面的示例所示。  
httpcfg query ssl>myMachinePorts.txt
在 Windows Server 2003 和 Windows XP 中,使用 HttpCfg.exe 工具以及 delete 和 ssl 关键字。  使用 -i 开关指定 IP:port 号,使用 -h 开关指定指纹。  
httpcfg delete ssl -i 0.0.0.0:8005 -h 0000000000003ed9cd0c315bbb6dc1c08da5e6
在 Windows Vista 中使用 Netsh.exe 工具,如下面的示例所示。
Netsh http delete sslcert ipport=0.0.0.0:8005

相关链接:

https://msdn.microsoft.com/zh-cn/library/ms733791.aspx
------------

HTTPS的七个误解(译文)

开发网页的时候,往往需要观察HTTP通信。

我使用的工具主要有两个,在Firefox中是Firebug,在IE中是Fiddler。但是,一直听别人说,付费软件HttpWatch是这方面最好的工具。

前几天,HttpWatch的官方网志刊登了一篇好文章,澄清了一些HTTPS协议容易产生误解的地方。学习之后,我增长了不少网页加密通信的知识。

我觉得这篇文章很实用,值得留作参考,就翻译了出来。

==============================================

HTTPS的七个误解

原文网址:http://blog.httpwatch.com/2011/01/28/top-7-myths-about-https/

译者:阮一峰

误解七:HTTPS无法缓存

许多人以为,出于安全考虑,浏览器不会在本地保存HTTPS缓存。实际上,只要在HTTP头中使用特定命令,HTTPS是可以缓存的。

微软的IE项目经理Eric Lawrence写道:

"说来也许令人震惊,只要HTTP头允许这样做,所有版本的IE都缓存HTTPS内容。比如,如果头命令是Cache-Control: max-age=600,那么这个网页就将被IE缓存10分钟。IE的缓存策略,与是否使用HTTPS协议无关。(其他浏览器在这方面的行为不一致,取决于你使用的版本,所以这里不加以讨论。)"

Firefox默认只在内存中缓存HTTPS。但是,只要头命令中有Cache-Control: Public,缓存就会被写到硬盘上。下面的图片显示,Firefox的硬盘缓存中有HTTPS内容,头命令正是Cache-Control:Public。

误解六:SSL证书很贵

如果你在网上搜一下,就会发现很多便宜的SSL证书,大概10美元一年,这和一个.com域名的年费差不多。而且事实上,还能找到免费的SSL证书。

在效力上,便宜的证书当然会比大机构颁发的证书差一点,但是几乎所有的主流浏览器都接受这些证书。

误解五:HTTPS站点必须有独享的IP地址

由于IPv4将要分配完毕,所以很多人关心这个问题。每个IP地址只能安装一张SSL证书,这是毫无疑问的。但是,如果你使用子域名通配符SSL证书(wildcard SSL certificate,价格大约是每年125美元),就能在一个IP地址上部署多个HTTPS子域名。比如,https://www.httpwatch.com和https://store.httpwatch.com,就共享同一个IP地址。

另外,UCC(统一通信证书,Unified Communications Certificate)支持一张证书同时匹配多个站点,可以是完全不同的域名。SNI(服务器名称指示,Server Name Indication)允许一个IP地址上多个域名安装多张证书。服务器端,Apache和Nginx支持该技术,IIS不支持;客户端,IE 7+、Firefox 2.0+、Chrome 6+、Safari 2.1+和Opera 8.0+支持。

误解四:转移服务器时要购买新证书

部署SSL证书,需要这样几步:

  1. 在你的服务器上,生成一个CSR文件(SSL证书请求文件,SSL Certificate Signing Request)。

  2. 使用CSR文件,购买SSL证书。

  3. 安装SSL证书。

这些步骤都经过精心设计,保证传输的安全,防止有人截取或非法获得证书。结果就是,你在第二步得到的证书不能用在另一台服务器上。如果你需要这样做,就必须以其他格式输出证书。

比如,IIS的做法是生成一个可以转移的.pfx文件,并加以密码保护。

将这个文件传入其他服务器,将可以继续使用原来的SSL证书了。

误解三:HTTPS太慢

使用HTTPS不会使你的网站变得更快(实际上有可能,请看下文),但是有一些技巧可以大大减少额外开销。

首先,只要压缩文本内容,就会降低解码耗用的CPU资源。不过,对于当代CPU来说,这点开销不值一提。

其次,建立HTTPS连接,要求额外的TCP往返,因此会新增一些发送和接收的字节。但是,从下图可以看到,新增的字节是很少的。

第一次打开网页的时候,HTTPS协议会比HTTP协议慢一点,这是因为读取和验证SSL证书的时间。下面是一张HTTP网页打开时间的瀑布图。

同一张网页使用HTTPS协议之后,打开时间变长了。

建立连接的部分,大约慢了10%。但是,一旦有效的HTTPS连接建立起来,再刷新网页,两种协议几乎没有区别。先是HTTP协议的刷新表现:

然后是HTTPS协议:

某些用户可能发现,HTTPS比HTTP更快一点。这会发生在一些大公司的内部局域网,因为通常情况下,公司的网关会截取并分析所有的网络通信。但是,当它遇到HTTPS连接时,它就只能直接放行,因为HTTPS无法被解读。正是因为少了这个解读的过程,所以HTTPS变得比较快。

误解二:有了HTTPS,Cookie和查询字符串就安全了

虽然无法直接从HTTPS数据中读取Cookie和查询字符串,但是你仍然需要使它们的值变得难以预测。

比如,曾经有一家英国银行,直接使用顺序排列的数值表示session id:

黑客可以先注册一个账户,找到这个cookie,看到这个值的表示方法。然后,改动cookie,从而劫持其他人的session id。至于查询字符串,也可以通过类似方式泄漏。

误解一:只有注册登录页,才需要HTTPS

这种想法很普遍。人们觉得,HTTPS可以保护用户的密码,此外就不需要了。Firefox浏览器新插件Firesheep,证明了这种想法是错的。我们可以看到,在Twitter和Facebook上,劫持其他人的session是非常容易的。

咖啡馆的免费WiFi,就是一个很理想的劫持环境,因为两个原因:

  1. 这种WiFi通常不会加密,所以很容易监控所有流量。

  2. WiFi通常使用NAT进行外网和内网的地址转换,所有内网客户端都共享一个外网地址。这意味着,被劫持的session,看上去很像来自原来的登录者。

以Twitter为例,它的登录页使用了HTTPS,但是登录以后,其他页面就变成了HTTP。这时,它的cookie里的session值就暴露了。

也就是说,这些cookie是在HTTPS环境下建立的,但是却在HTTP环境下传输。如果有人劫持到这些cookie,那他就能以你的身份在Twitter上发言了。

---------------------

RSA加密算法

RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。
 
        解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文。
 
        以甲要把信息发给乙为例,首先确定角色:甲为加密者,乙为解密者。首先由乙随机确定一个KEY,称之为密匙,将这个KEY始终保存在机器B中而不发出来;然后,由这个 KEY计算出另一个KEY,称之为公匙。这个公钥的特性是几乎不可能通过它自身计算出生成它的私钥。接下来通过网络把这个公钥传给甲,甲收到公钥后,利用公钥对信息加密,并把密文通过网络发送到乙,最后乙利用已知的私钥,就对密文进行解码了。以上就是RSA算法的工作流程。
 
        算法实现过程为:
 
        1. 随意选择两个大的质数p和q,p不等于q,计算N=pq。
        2. 根据欧拉函数,不大于N且与N互质的整数個数為(p-1)(q-1)。
        3. 选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)。
        4. 用以下这个公式计算d:d× e ≡ 1 (mod (p-1)(q-1))。
        5. 将p和q的记录销毁。
 
        以上内容中,(N,e)是公钥,(N,d)是私钥。
 
        下面讲解RSA算法的应用。
 
        RSA的公钥和私钥是由KeyPairGenerator生成的,获取KeyPairGenerator的实例后还需要设置其密钥位数。设置密钥位数越高,加密过程越安全,一般使用1024位。如下代码:
 
java代码:

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
// 密钥位数
keyPairGen.initialize(1024);
 
        公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。如下代码:
 
java代码:

// 动态生成密钥对,这是当前最耗时的操作,一般要2s以上。
KeyPair keyPair = keyPairGen.generateKeyPair();
// 公钥
PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
byte[] publicKeyData = publicKey.getEncoded();
byte[] privateKeyData = publicKey.getEncoded();
        公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。通过byte[]可以再度将公钥或私钥还原出来。具体代码如下:
 
java代码:

// 通过公钥byte[]将公钥还原,适用于RSA算法
public static PublicKey getPublicKey(byte[] keyBytes) throws
NoSuchAlgorithmException,InvalidKeySpecException {
   X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
   KeyFactory keyFactory = KeyFactory.getInstance("RSA");
   PublicKey publicKey = keyFactory.generatePublic(keySpec);
   return publicKey;
}
// 通过私钥byte[]将公钥还原,适用于RSA算法
public static PrivateKey getPrivateKey(byte[] keyBytes) throws
NoSuchAlgorithmException,InvalidKeySpecException {
   PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
   KeyFactory keyFactory = KeyFactory.getInstance("RSA");
   PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
   return privateKey;
}
        在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。共同的N值可以通过getModulus()获取。执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。这三者返回类型都是BigInteger。代码如下:
 
java代码:

// 打印公钥信息
public static void printPublicKeyInfo(PublicKey key){
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
Log.d(MainActivity.TAG, "RSAPublicKey:");
Log.d(MainActivity.TAG, "Modulus.length=" +
rsaPublicKey.getModulus().bitLength());
Log.d(MainActivity.TAG, "Modulus=" +
rsaPublicKey.getModulus().toString());
Log.d(MainActivity.TAG, "PublicExponent.length=" +
rsaPublicKey.getPublicExponent().bitLength());
Log.d(MainActivity.TAG, "PublicExponent=" +
rsaPublicKey.getPublicExponent().toString());
}
 
// 打印私钥信息
public static void printPublicKeyInfo(PrivateKey key){
RSAPrivateKey rsaPublicKey = (RSAPrivateKey) privateKey;
Log.d(MainActivity.TAG, "RSAPrivateKey:");
Log.d(MainActivity.TAG, "Modulus.length=" +
rsaPrivateKey.getModulus().bitLength());
Log.d(MainActivity.TAG, "Modulus=" +
rsaPrivateKey.getModulus().toString());
Log.d(MainActivity.TAG, "PublicExponent.length=" +
rsaPrivateKey.getPrivateExponent().bitLength());
Log.d(MainActivity.TAG, "PublicExponent=" +
rsaPrivateKey.getPrivateExponent().toString());
}
 
        由于程序中动态生成KeyPair对明文加密后生成的密文是不可测的,所以在实际开发中通常在生成一个KeyPair后将公钥和私钥的N、e、d这三个特征值记录下来,在真实的开发中使用这三个特征值再去将PublicKey和PrivateKey还原出来。还原方法如下:
 
java代码:

// 使用N、e值还原公钥
public static PublicKey getPublicKey(String modulus, String
publicExponent)
       throws NoSuchAlgorithmException, InvalidKeySpecException {
   BigInteger bigIntModulus = new BigInteger(modulus);
   BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
   RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,
bigIntPrivateExponent);
   KeyFactory keyFactory = KeyFactory.getInstance("RSA");
   PublicKey publicKey = keyFactory.generatePublic(keySpec);
   return publicKey;
}
 
// 使用N、d值还原公钥
public static PrivateKey getPrivateKey(String modulus, String
privateExponent)
       throws NoSuchAlgorithmException, InvalidKeySpecException {
   BigInteger bigIntModulus = new BigInteger(modulus);
   BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
   RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,
bigIntPrivateExponent);
   KeyFactory keyFactory = KeyFactory.getInstance("RSA");
   PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
   return privateKey;
}
 
        公钥和私钥都具备后,就可以使用加解密的工具类javax.crypto.Cipher对明文和密文进行处理了。与所有的引擎类一样,可以通过调用Cipher类中的getInstance(String transformation)静态工厂方法得到Cipher对象。该方法中的参数描述了由指定输入产生输出所进行的操作或操作集合,可以是下列两种形式之一:“algorithm/mode/padding”或“algorithm”。例如下面的例子就是有效的transformation形式:"DES/CBC/PKCS5Padding"或"DES"。如果没有指定模式或填充方式,就使用特定提供者指定的默认模式或默认填充方式。
 
        Cipher的加密和解密方式所调用的方法和过程都一样,只是传参不同的区别。如下代码:
 
java代码:

// 编码前设定编码方式及密钥
cipher.init(mode, key);
// 传入编码数据并返回编码结果
byte[] dataResult = cipher.doFinal(input);
 
        Cipher.init(mode, key)方法中MODE指加密或解密模式,值为Cipher.ENCRYPT_MODE或Cipher.DECRYPT_MODE,参数key在加密时传入PublicKey,在解密时以PrivateKey传入。Cipher.doFinal(byte[] data)则是将待编码数据传入后并返回编码结果。为了将编码结果转为可读字符串,通常最后还使用BASE 64算法对最终的byte[]数据编码后显示给开发者。

--- end ---

https ssl证书的工作原理及使用相关知识收集相关推荐

  1. 什么是 SSL 证书及其工作原理

    什么是 SSL 证书? 了解 SSL 的用途.SSL 和 TLS 之间的区别.它们的工作方式以及何时应该使用它们. 什么是 SSL 证书? SSL(安全套接字层)是 TLS(传输层安全性)的通用名称, ...

  2. SSL证书的工作原理是怎么样的?

    SSL安全套接字层,是一种网络安全协议,用于加密浏览器和服务器之间传输的数据信息.如果你的网站涉及敏感信息,如用户名.密码.银行卡号.手机号码等,则需要使用SSL证书,防止信息被第三方窃取和篡改.SS ...

  3. 摄像头工作原理及isp相关知识

    转载地址:https://blog.csdn.net/wangliang888888/article/details/103695002 本文转自http://bbs.elecfans.com/jis ...

  4. SSL证书如何工作?

    网络安全已成为所有互联网用户的重中之重的问题.迄今为止SSL证书是防护网站安全的最好及最简单的解决方案,对传输数据进行加密防止数据被盗或被篡改. "SSL"代表安全套接字层,安全套 ...

  5. SSL/TLS 的工作原理

    HTTPS 之所以能达到较高的安全性要求,就是结合了 SSL/TLS 和 TCP 协议,对通信数据进行加密,解决了 HTTP 数据透明的问题.接下来重点介绍一下 SSL/TLS 的工作原理. SSL ...

  6. WebService系列之Axis Https(SSL)证书校验错误处理方法

    WebService系列之Axis Https(SSL)证书校验错误处理方法 最近在用Axis调用https的接口,抛出异常: javax.net.ssl.SSLHandshakeException: ...

  7. python sanic 设置ssl证书_配置自签https ssl证书

    由于人们越来越重视网络安全,所以很多平台及系统都要求使用https方式接入.而且一些开源服务框架在调用时也只接受https请求,这将导致平时开发/测试时需要用到ssl证书的地方越来越多. 在2016年 ...

  8. 第52章 HTTPS SSL证书与Data Protection(数据安全)

    HTTPS SSL证书 在使用Visual Studio .Net(Core)进行Web开发时,当前第一调试Web程序时会为Visual Studio中的Web项调试所使用的IIS Express提供 ...

  9. 深入浅出解读http和https及ACME协议工作原理(另附域名证书申请教程)

    文章目录 名词说明 前言 HTTPS的加密传输过程 HTTP.HTTPS 对称加密.非对称加密 私钥文件.SSL证书(包含公钥) HTTPS网址访问流程 传统人工的SSL证书管理方式 ACME协议是如 ...

最新文章

  1. 输入几个数字,用逗号隔开系列例题
  2. 【html+css练习】小白使用html+css模拟音乐播放器构造了网页音乐播放器--1
  3. Akka入门(一)Akka简介与为什么使用Akka
  4. Eigen入门之密集矩阵 9 - 别名混乱Aliasing
  5. Acwing 1081. 度的数量(以及本人对数位dp的浅薄理解)
  6. intellij ide_UltraESB的首选IDE – IntelliJ IDEA
  7. [渝粤教育] 三江学院 软件测试 参考 资料
  8. codeforces 1030A-C语言解题报告
  9. 计算机操作系统模拟试题,最新考研计算机-操作系统模拟试题.doc
  10. ListT to DataTable
  11. 2021年美赛B题——解题参考
  12. 图解TCPIP---第二章
  13. 为什么越来越多的人从开发转测试?
  14. 电商营业执照能入驻跨境电商虾皮shopee平台吗?
  15. html css 怎么画星形,CSS画各种图形(五角星、吃豆人、太极图等)
  16. ubuntu 20 安装 velodyne_simulator
  17. MarkdownPad2安装教程
  18. 参观计算机实验室后的感想,参观实验室心得体会.doc
  19. 一篇文章讲清什么是零知识证明
  20. linux hd4000显卡驱动,如何在Linux上为Intel HD 4000获取OpenGL 4

热门文章

  1. Oracle密码策略设置指引
  2. 车联网的2020:商业落地、技术支柱、生态溢出
  3. rabbitmq 安装问题
  4. java.sql.SQLException: Unsupported character encoding 'utf8mb4'.
  5. 《Code Reading》读书笔记
  6. 拒绝「技术栈」选择恐惧症
  7. AlexNet分类学习
  8. Vue3使用G6基础
  9. 笔记本电脑如何使用双屏幕
  10. android pad课件制作软件,用iPad制作幻灯片哪个软件方便使用