Dual Thrust交易策略

介绍

Dual Thrust系统是 Michael Chalek 在80 年代开发的 Dual Thrust。在自动化交易排名中,目前为止,仍然排名第二左右。Dual Thrust系统具有简单易用、适用度广的特点,其思路简单、参数很少,配合不同的参数、止盈止损和仓位管理,可以为投资者带来长期稳定的收益,被投资者广泛应用于股票、货币、贵金属、债券、能源及股指期货市场等。
在Dual Thrust交易系统中,对于震荡区间的定义非常关键,这也是该交易系统的核心和精髓。Dual Thrust系统使用Range = Max(HH-LC,HC-LL)来描述震荡区间的大小。其中HH是N日High的最高价,LC是N日Close的最低价,HC是N日Close的最高价,LL是N日Low的最低价。
它的逻辑原型是较为常见的日内交易策略之一开盘区间突破策略,以今日开盘价加减一定比例的昨日振幅,确定上下轨。日内突破上轨时平空做多,突破下轨时平多做空。

开盘区间突破策略基本原理

1. 在今天的收盘,计算两个值:最高价-收盘价,和收盘价-最低价。然后取这两个值较大的那个,乘以k值0.7。把结果称为触发值。
2. 在明天的开盘,记录开盘价,然后在价格超过(开盘+触发值)时马上买入,或者价格低于(开盘-触发值)时马上卖空。
3. 没有明确止损。这个系统是反转系统,也就是说,如果在价格超过(开盘+触发值)时手头有一口空单,则买入两口。同理,如果在价格低于(开盘-触发值)时手上有一口多单,则卖出两口。

首先计算:
(1)N日High的最高价HH, N日Close的最低价LC;
(2)N日Close的最高价HC,N日Low的最低价LL;
(3)Range = Max(HH-LC,HC-LL)
(4)BuyLine = Open + K1*Range
(5)SellLine = Open + K2*Range
构造系统:
(1)当价格向上突破上轨时,如果当时持有空仓,则先平仓,再开多仓;如果没有仓位,则直接开多仓;
(2)当价格向下突破下轨时,如果当时持有多仓,则先平仓,再开空仓;如果没有仓位,则直接开空仓;

Dual Thrust在开盘区间突破策略上进行了相关改进:

1、在范围(range)的设置上,引入前N日的四个价位,使得一定时期内的范围相对稳定,可以适用于日间的趋势跟踪;
2、Dual Thrust对于多头和空头的触发条件,考虑了非对称的幅度,做多和做空参考的Range可以选择不同的周期数,也可以通过参数K1和K2来确定。当K1<K2时,多头相对容易被触发,当K1>K2时,空头相对容易被触发。
因此,在使用该策略时,一方面可以参考历史数据测试的最优参数,另一方面,则可以根据自己对后势的判断,或从其他大周期的技术指标入手,阶段性地动态调整K1和K2的值。
就是一个典型的观望、等待信号、进场、套利、离场的套路,却效果卓著。

海龟交易法则

我说过很多次,你可以把我的交易法则登在报纸上,但没人会遵守它们。关键是统一性和纪律性。几乎每一个人都可以列出一串法则,而且不比我们的那些法则差多少。但他们不能给别人信心,而唯有对法则充满信心,你才会坚持这些法则,即使遭遇逆境。
—— 理查德·丹尼斯,摘自杰克·D·施瓦格(Jack D. Schwager)的《金融怪杰》(Market Wizards)

如果你有一个有效的交易系统,而且能坚定不移地遵守它,你的行动就会更具统一性,尽管连续的损失或巨大的赢利也会激起内心的思想斗争。一个千锤百炼的机械性交易系统能赋予你信心、统一性和纪律性,这就是许多顶尖交易者的成功要诀。
—— (美)费思.海龟交易法则(珍藏版)

市场:买卖什么?

海龟们只选流动性最高的市场。

头寸规模:买卖多少?

波动性:N的含义

海龟们用一个特殊的概念来衡量一个市场的潜在波动性,理查德·丹尼斯和比尔·埃克哈特称之为N。N就是真实波动幅度的20日指数移动平均值,现在更常见的名称是真实波动幅度均值(或ATR)。从理论上说,N代表着一个市场在一天内的平均波动幅度,包括开盘跳空的情况在内。N的单位是点数,也就是这个市场的价格点数。
每一天的真实波动幅度是用下列关系式计算的:

真实波动幅度=Max(H–L,H–PDC,PDC–L)

其中:
H=当日最高价
L=当日最低价
PDC=前一日收盘价
N的计算公式如下:

   19 X PDN + TR
N=----------------
        20

其中:
PDN=前一日的N值
TR=当日的真实波动幅度
由于公式中需要前一日的N值,你在首次计算N的时候不能用这个公式,只能计算真实波动幅度的20日简单平均值。

美元波动幅度

决定头寸规模的第一个步骤就是计算绝对波动幅度,而绝对波动幅度是根据市场的价格波动性(N值)算出的。这听起来复杂,实际上很简单。
绝对波动幅度的计算公式就是:

绝对波动幅度=N×每一点数所代表的美元

波幅调整后的头寸单位

海龟们把头寸分为一个个单位,我们称之为头寸单位。头寸单位的大小要根据市场的波动性进行调整,目的是让一个N相当于账户净值的1%。
因此,一个特定市场或产品的头寸规模单位可以用下列公式算出:

                  帐户的1%
头寸规模单位=------------------
             市场的绝对波动幅度

或者:

                     帐户的1%
头寸规模单位=------------------------
             N X 每一点数所代表的美元

由于期货合约是不能拆分的,当计算出来的结果不是整数时,我们舍去小数,只取整数数值。

头寸规模的重要性

前面说过,分散化旨在将风险分散到多种不同工具中,同时通过提高成功交易的概率来提高赢利水平。恰当的分散化要求交易者在多种不同工具上投入类似甚至相同的赌注。
海龟系统用市场波动性来衡量每一个市场的风险水平。然后,我们会根据这个风险准绳来逐步建立风险量(或波幅)相同的头寸。这增强了分散化的效果,提高了赢利交易弥补亏损交易的概率。
请注意,如果你没有足够的资金,这样的分散化是很难实现的。对小账户来说,调整的精确性太低,这会大大降低分散化的效果。

风险与头寸单位

由于海龟们用头寸单位来衡量头寸的大小,而这样的头寸单位要根据波动性风险进行调整,头寸单位实际上就成了单个头寸和整个头寸组合的一个风险衡量指标。
海龟资金管理法则在4个不同层面上限制了我们的交易量。从本质上说,这些法则控制了交易者的总体风险水平。无论是在没完没了的亏损时期还是翻天覆地的价格动荡中,这些限制都能把损失最小化。
单个市场:每一个市场中的头寸单位不得超过4个。
高度关联的多个市场:在紧密关联的市场中,我们在某一个方向上的头寸单位不得超过6个(也就是说,空头单位最多6个,多头单位也最多6个)。高度关联的市场组合包括:民用燃料油与原油,黄金和白银,所有外汇,像短期国债和欧洲美元这样的利率类期货等。
松散关联的多个市场:对松散关联的市场来说,我们在某一个方向上的头寸单位不得超过10个。松散关联的市场包括黄金与铜,白银与铜,以及海龟们因为法定头寸限制而无法交易的许多谷类组合。
单个方向(多头或空头):任何一个方向上的总头寸单位都不得超过12个。因此,一个海龟从理论上说可以同时持有12个空头单位和12个多头单位。
海龟们用“满仓”这个词来表示他们已经达到了某个层面上的头寸规模上限。因此,日元满仓是指已经持有4个单位的日元合约,完全满仓是指某个方向上的头寸单位已经达到12个,诸如此类。

调整交易规模

有时候,市场会连续多个月没有趋势出现。在这种情况下,你的账户净值有可能遭受巨大的损失。
而在一场场大捷之后,你可能想扩大账户规模,进而扩大头寸规模。
海龟们的账户并不是那种在初始净值的基础上逐笔结算的普通账户。我们拿到的是名义账户,大小是指定的,初始净值为零。例如,当我们在1983年2月刚刚开始实战时,许多海龟拿到的是一个100万美元的名义账户。账户规模每年年初调整一次。上调还是下调要看里奇对交易者的评价。调整幅度一般与这个账户上一年度的盈亏状况紧密相关。
每当我们损失了初始账户的10%时,里奇都会把我们的账户规模缩减20%。这样,如果我们的100万美元初始账户损失了10%,也就是10万美元,我们的账户规模将会下调到80万美元,直到账户净值恢复到年初水平。如果我们又一次损失了10%(80万美元的10%,也就是8万美元,这样总损失达到了18万美元),我们就得把账户再压缩20%,这样就只剩下了64万美元的名义账户。
根据盈亏状况调整账户规模可能还有更好的方法。以上只是海龟们的方法。

入市:什么时候买卖?

入市策略

交易者大多从入市信号的角度来评判一个特定的交易系统。他们相信,入市策略是一个交易系统最重要的一个环节。
所以他们可能想不到,海龟们使用的是一个以理查德·唐奇安的通道突破系统为基础的非常简单的入市系统。
海龟们使用两个有所差异但也彼此相关的入市系统,我们称为系统1和系统2。我们可以自由决定如何在这两个系统之间分配资金。有的海龟只用系统2,有的在两个系统上各投入50%的资金,还有的采用其他组合。这两个系统分别是:
系统1:以20日突破为基础的短期系统
系统2:以55日突破为基础的长期系统

突破

突破是指价格超越了过去一定时期内的最高点或最低点。所以,20日突破就是指价格超越了过去20天内的最高或最低点。
海龟们总是在突破发生时立即入市交易,不会等到当日收盘或次日开盘时。在跳空开盘的情况下,假如开盘价已经跳过了突破价,海龟们就在开盘时入市。

系统1入市法则

只要价格超越20日最高或最低点一个最小单位,海龟们就马上行动。如果价格超越了20日高点,海龟们就买入1个头寸单位,开始做多。如果价格跌破了20日低点,海龟们就卖出1个头寸单位,开始做空。
但是,假如上一次突破是一次赢利性突破(也就是可以带来一次赢利的交易),那么系统1的当前入市信号将被忽略。注意:对这一法则来说,上一次突破就是指市场的上一次实际突破,不管交易者当时采取了突破交易还是根据这一法则而忽略了那次突破。那么什么是亏损型的突破呢?如果突破日之后的价格在头寸有机会退出获利(根据10日突破退出法则)之前发生了2N幅度的不利变动,这就被视为一次亏损性的突破。
对这一法则来说,上一次突破的方向并不重要。因此,无论上一次突破是向上突破还是向下突破,只要是亏损型突破,那么目前的新突破(无论是向上还是向下突破)就会被视为有效的入市信号。
不过,如果一次突破因为这条法则而被忽略,那么交易者将在55日突破点入市,这是为了避免错过重大趋势。这个55日突破点被视为一个保障性突破点。
在任何时候,如果一个交易者处于离场等待的状态,那么总有某个价位能引发空头入市信号,也总有某个更高的价位能引发多头入市信号。如果上一次突破是亏损性的,那么新突破点(也就是20日突破点)将更接近于当前价格;如果上一次突破是赢利性的,那么新突破点可能离当前价远得多,因为那有可能是个55日突破点。

系统2入市法则

只要价格超越55日最高或最低点一个最小单位,我们就入市。如果价格超越了55日高点,海龟们就买入1个头寸单位,开始做多。如果价格跌破了55日低点,海龟们就卖出1个头寸单位,开始做空。
对系统2来说,所有突破都被视为有效信号,无论上一次突破是亏损性还是赢利性的。

逐步建仓

海龟们首先在突破点建立1个单位的头寸,然后按1/2*N的价格间隔一步一步扩大头寸。这个1/2*N的间隔以上一份定单的实际成交价格为基础。所以,如果最初的突破交易发生了1/2*N的成交价偏差,那么新定单的价格将与突破点相差1N,也就是最初1/2*N的偏差加上1/2*N的标准间隔。
这个过程将继续下去,一直到头寸规模达到上限。如果市场足够活跃,我们有可能在一天内加满4个头寸单位。
请看下面的例子:

黄金
N=2.50
55日突破价=310.00
第一个单位:310.00
第二个单位:310.00+1/2×2.5=311.25
第三个单位:311.25+1/2×2.5=312.50
第四个单位:312.50+1/2×2.5=313.75
原油
N=1.20
55日突破价=28.30
第一个单位:28.30
第二个单位:28.30+1/2×1.20=28.90
第三个单位:28.90+1/2×1.20=29.50
第四个单位:29.50+1/2×1.20=30.10

统一性里

奇要求海龟们坚定不移地遵守入市信号,因为一整年的大部分利润很有可能就来自于两三次大的赢利交易。哪怕你只忽略或错过了一个信号,这一年的回报率也可能大打折扣。表现最好的海龟们都是入市法则的坚定信徒。
表现最差的海龟和那些被淘汰出海龟计划的人都不能始终如一地坚持法则。

止损:什么时候放弃一个亏损的头寸?

止损

交易行业里有这么一句话:“有老交易者,也有不怕死的交易者,但是没有不怕死的老交易者。”不用止损点的交易者十有八九会破产。海龟们一定会用止损点。
面对一个亏损的头寸,你可以坚守阵地,寄希望于失而复得;也可以割肉退出,承认这次交易不成功。对大多数人来说,前者远比后者要容易。
我可以明明白白地告诉你:遵守系统法则的命令退出亏损的头寸是一个生死攸关的要点。不会甩掉损失的交易者在长期内都不会成功。包括巴林银行和长期资本管理基金的灾难在内,几乎所有失去控制的致命交易行为都与不能防微杜渐地及时控制损失有关。
要控制损失,最重要的一件事就是在入市之前就确定退出的标准。一旦价格到达了你的止损标准,你必须退出——坚定不移,无一例外。犹豫和动摇终将酿成灾难。

海龟止损点

海龟们会使用止损点,但这并不意味着我们真的会向经纪人下止损单(stop order)。
由于海龟们手中的头寸非常庞大,我们不愿意下止损单,因为这有可能暴露我们的头寸状况或交易策略。我们会事先确定一个特定的止损价位,当市场达到这个价位,我们将通过限价定单或市价定单来退出我们的头寸。
这些止损价位就是雷打不动的退出点。只要市场到达了止损价位,我们就毫不迟疑地坚决退出。

止损标准

海龟们根据头寸风险来设定止损标准。任何一笔交易的风险程度都不得超过2%。
由于1N的价格变动代表着账户净值的1%,在2%的风险限制下,价格变动的上限就是2N。海龟们止损标准就是2N:对多头头寸来说,止损价比入市价低2N;对空头头寸来说,止损价比入市价高2N。
为了把整体头寸风险控制在最低水平,如果我们(按1/2*N的价格间隔)后续补充了头寸单位,那么之前头寸单位的止损点将相应地调整1/2*N。一般来说,这意味着整个头寸的止损点将与最新添加的头寸单位相距2N的距离。不过,如果头寸补充的价格间隔因为市场变化过快或开盘跳空等情况而大于1/2*N,止损标准也会有所变化。
下面是一个例子:

原油:
N=1.2055
日突破价=28.30
           入市价  止损价
第一个单位  28.30   25.90
           入市价  止损价
第一个单位  28.30   26.50
第二个单位  28.90   26.50
           入市价  止损价
第一个单位  28.30   27.10
第二个单位  28.90   27.10
第三个单位  29.50   27.10
           入市价  止损价
第一个单位  28.30   27.70
第二个单位  28.90   27.70
第三个单位  29.50   27.70
第四个单位  30.10   27.70
假如第四个单位因为市场跳空高开在每股30.80美元成交,那么结果将变为:
           入市价  止损价
第一个单位  28.30   27.70
第二个单位  28.90   27.70
第三个单位  29.50   27.70
第四个单位  30.80   28.40

备选止损策略:双重损失

海龟们也学习了另外一种叫作双重损失(the whipsaw)的止损策略。这种策略可以实现更高的利润率,但更难执行,因为它所制造的损失要比一般策略多得多,胜负比率会大大降低。
在双重损失策略下,每一笔交易的风险上限不是2%,而是0.5%。也就是说,价格波动的上限是1/2*N。在一个头寸单位止损退出后,交易者将在价格恢复到最初的入市价时重新建立这个单位。有几个海龟很成功地运用了这种策略。
双重损失策略还有一个好处:它不需要随着新头寸单位的补充而调整之前单位的止损点,因为我们最多只能有4个单位,总风险水平不可能超过2%。
比如,如果采用双重损失止损策略,上述原油交易将变成下面的样子:

原油:
N=1.2055
日突破价=28.30
           入市价  止损价
第一个单位  28.30   27.70
           入市价  止损价
第一个单位  28.30   27.70
第二个单位  28.90   28.30
           入市价  止损价
第一个单位  28.30   27.70
第二个单位  28.90   28.30
第三个单位  29.50   28.90
           入市价  止损价
第一个单位  28.30   27.70
第二个单位  28.90   28.30
第三个单位  29.50   28.90
第四个单位  30.10   29.50

海龟止损策略的优势

由于海龟止损点以N为基础,它们与市场的波动性息息相关。更具波动性的市场有更大的止损范围,但每个头寸单位的合约数量也相对较少。这便统一了所有交易的风险水平,加强了分散化的效果和风险管理的稳健性。

退出:什么时候退出一个赢利的头寸?

退出

交易行业里还有一句老话:“落袋为安的人永远也不会破产。”但海龟们不会同意这种论调。趋势跟踪者们最常犯的错误之一就是过早地退出赢利的头寸,也就是过早地“落袋为安”。价格永远也不会直上直下,没有波动。因此,要想抓住一次趋势,你必须允许价格偶尔向不利的方向变动。在趋势的初期,这往往意味着10%~30%的利润在你眼前化为乌有,反而转为小小的损失。在趋势的中期,你或许会眼睁睁地看着80%~100%的利润跌去三四成。在这些情况下,放掉包袱、“锁定利润”的诱惑是很强大的。
海龟们知道,赢利的时机问题足以决定你的胜败。
海龟系统在突破点入市,但大多数突破点都不会引发趋势。这意味着海龟们的大多数交易都是亏损的。如果少数赢利的交易赚不到足够多的钱来弥补这些损失,海龟们会是输家。每一个有效的交易系统都有自己的最佳退出点。
考虑一下海龟交易系统:如果你总是在1N的利润水平下退出赢利的交易,却在2N的止损点退出亏损的交易,你的赢利次数必须是亏损次数的两倍才能做到盈亏平衡。
交易系统的各个成分之间有着复杂的关系。因此,如果你不考虑入市点、资金管理和其他因素,你就没法去考虑正确的退出策略。
赢利头寸的退出策略是最重要的问题之一,但也是最不受重视的问题之一。然而,它完全可以决定一笔交易的成败得失。

海龟退出策略

系统1采用10日突破退出法则:对多头头寸来说,在价格跌破过去10日最低点时退出;对空头头寸来说,在价格超过10日最高点时退出。总之,如果价格发生了不利于头寸的10日突破,所有头寸单位都要退出。
系统2则采用20日突破退出法则:对多头来说是20日向下突破,对空头来说是20日向上突破。只要价格发生了不利于头寸的20日突破,所有头寸单位都会退出。
就像入市策略一样,海龟们一般不会通过止损单而退出,而是会紧密观察市场的动向,在价格达到退出突破点时马上下单退出。

退出不易

对大多数交易者来说,海龟系统的退出策略可能是整个系统中最难忍受的一个环节。你必须等待市场创下10日或20日新低才能退出,这往往意味着目睹20%、40%甚至100%的巨额利润瞬间蒸发。
所以,交易者总有一种提早退出的强烈冲动。你需要极强的纪律性才能坚守阵地,忍受利润的蒸发,直到抓住真正的大趋势。在大的赢利交易中遵守纪律和法则的能力就是经验丰富的成功交易者们的标志。

战术:怎么买卖?

战术

著名建筑师密斯·凡德罗(Mies van der Rohe)在谈到建筑设计时曾说过这么一句话:“细节就是上帝。”对交易系统来说,同样如此。在使用海龟交易法则的过程中,有些重要的细节对你的赢利水平有举足轻重的影响。

下单

前面说过,理查德·丹尼斯和比尔·埃克哈特建议海龟们不要使用止损单,而是随时观察市场动向,在价格到达止损价位的时候再行动。他们还告诉我们,限价定单总的来说要强于市价定单。相比起市价定单,限价定单更容易以更有利的价格成交,成交价偏差也要小一些。
任何时候的任何市场都有买入价和卖出价这两个报价。买入价就是买者们愿意接受的买价,卖出价就是卖者们愿意接受的卖价。只要买入价超过了卖出价,交易就会发生。如果市场的成交量足够大,市价定单总能在买入价位或卖出价位成交,不过大定单的成交价有时候也会稍差一些。
一般来说,市场总会发生一定幅度的相对随机性波动,这有时候被称为反弹(bounce)。之所以使用限价定单,就是为了把价格定在反弹区域的底端,而不是简简单单地接受当前的市价。一个小的限价定单不会触动市场,即使定单较大,它对市场的触动也小于市价定单。
确定限价定单的最佳定价是需要一定技巧的。不过,只要多做练习,你完全能学会用接近市价的限价定单获得比市价定单更好的成交价。

急变市场

有时候,市场变化速度太快,顷刻之间就会跳过你的定单价。如果你用的是限价单,你根本没机会成交。在这类急变市场中,每份合约的价值可能在短短几分钟之内涨跌数千美元之多。
在这种情况下,海龟们的原则是保持冷静,等市场稳定下来再做打算。但大多数新手都很难做到这一点。他们会惊慌失措,手忙脚乱地发出市价单。他们十有八九是在最差的时机下单的,到头来一算,他们的成交价是一天内最差的价格,不是最高点就是最低点。
在一个急变市场中,流动性会暂时固定。如果市场露出急变的迹象,卖者会停手观望,等待价格继续上涨,而且在飙升趋势停止之前不会再卖。这样一来,卖出价会急剧上升,而且买卖价差会有所扩大。
随着卖者不断抬高要价,买者们也被迫抬高出价,于是价格的上涨越来越快,最终引来更多的卖者。随着卖者越来越多,价格会平稳下来,往往还会快速逆转,大幅回调。
到头来,市价定单的成交点通常就是上行趋势的最高点,也就是市场开始止升企稳的时候。
在这类情况下,海龟们会一直等到市场出现逆转迹象(至少是暂时逆转)的时候再行动,这时候的成交价通常要比市价定单下的成交价好得多。如果市场趋于稳定后的价格已经超过了我们最初的止损价,我们会退出市场,但不会惊慌失措。

同步入市信号

在很多时候,市场非常平稳,波澜不惊,所以海龟们除了监控手头的头寸之外基本上无事可做,有可能在很长一段时间内没有任何动作。有的时候也会有点忙碌,几个小时内陆陆续续地出现多个信号,我们会按部就班地行动,直到达到相应市场的头寸上限。
但也有的时候,似乎所有的事情都在同一时间发生,我们个个忙得昏天黑地,在一两天之内就从两手空空变成了满仓。而且相互关联的市场上常常会同时发出信号,令疯狂的节奏变得更加疯狂。
如果各个市场一开盘就跳空越过了入市信号,那就更不用说了。你可能在同一天内看到原油、民用燃料油和无铅汽油市场的跳空开盘入市信号。对期货合约来说,同一个市场的多个不同月份的合约同时出现信号也是司空见惯的事。在这种情况下,你必须高效、快速地行动,而且不能惊慌,不能乱下市价定单,否则你的成交价必然会大大恶化。

买强卖弱

如果多个信号在同一时间出现,我们会在同一类市场中选择最强势的市场买入,选择最弱势的市场卖空。
另外,我们在同一时间只会选择一个月份的合约,而且只会建立一个头寸单位。比如,我们不会同时买入2月份、3月份和4月份的民用燃料油合约,而是会选择最强势而且有足够高的成交量和流动性的合约。
这一点极其重要。在同一类相互关联的市场中,最好的多头交易都存在于最强势的市场中(这些市场的表现几乎必然强于较弱的同类市场)。同样,最好的空头交易都存在于最弱势的市场中。
海龟们用多种不同的衡量标准来判断市场的强弱。最简单也最常用的一种方法就是察看图表,根据视觉判断来选出“看起来”更强(或更弱)的市场。
有些海龟的衡量标准是N:他们会比较一下各个市场自发生突破之后已经变化了多少个N,然后在变动幅度最大(以N来衡量)的市场中买入。还有一些海龟把不同市场的变化标准化了:他们用当前价减去3个月之前的价格,然后再除以N值。结果值最高的就是最强的市场,最低的就是最弱的市场。
这些方法都很有效。总而言之,要点在于在最强的市场上做多,在最弱的市场上做空。

合约滚动

当一期合约到期时,你在转向后期新合约之前需要注意两个因素。
首先,在很多时候,近期的合约虽然有很好的趋势,但较远期的合约并没有表现出同样的势头。除非新合约的趋势同样符合你的要求,否则不要向新合约滚动。
其次,你必须赶在现有合约的成交量和未平仓量(open interest)大幅萎缩之前滚向新合约。什么叫“大幅萎缩”要看头寸单位有多大。一般来说,海龟们会在合约到期之前几个星期将现有头寸滚向后期新合约,除非现有合约的表现远好于后期的新合约。

摘录于:(美)费思. 海龟交易法则(珍藏版) Kindle 版本.

nginx ssl设置详解

SSL 协议

SSLv2是不安全的,绝对不能用,SSLv3 能不用则不用,正常情况下用不到的,推荐使用 TLSv1 TLSv1.1 TLSv1.2,附配置代码:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

加密算法

RC4不要用,再就是 OpenSSL 记得更新到最新版,可以避免很多麻烦。别的也没什么了,附代码:

ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

ssl_prefer_server_ciphers on;

ECDHE+AESGCM 加密是首选的。它们是 TLS 1.2 加密算法,现在还没有广泛支持。当然也没有破解的方案。
PFS 加密套件好一些,首选 ECDHE,然后是 DHE
AES 128 要好于 AES 256AES 256 会造成更大的性能消耗,但是带来的安全提升是有限的。反之还能承受更大压力。
在向后兼容的加密套件里面,AES 要优于 3DES。在 TLS 1.1及其以上,减轻了针对 AES 的野兽攻击(BEAST)的威胁,而在 TLS 1.0上则难以实现该攻击。在非向后兼容的加密套件里面,不支持 3DES
RC4 整个不支持了。3DES 用来向后兼容。
强制丢弃的算法
aNULL 包含了非验证的 Diffie-Hellman 密钥交换,这会受到中间人(MITM)攻击
eNULL 包含了无加密的算法(明文)
EXPORT 是老旧的弱加密算法,是被美国法律标示为可出口的
RC4 包含使用了已弃用的 ARCFOUR 的加密算法
DES 包含使用了弃用的数据加密标准(DES)的加密算法
SSLv2 包含了定义在旧版本 SSL 标准中的所有算法,现已弃用
MD5 包含了使用已弃用的 MD5 的所有算法
但是 ECC 证书的部署不大一样,加密套件和 RSA 不一样,用错之后会影响向前安全性(Forward secrecy)。
加密套件应该这么改:

ssl_ciphers "EECDH+CHACHA20 EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";

而根据https://cipherli.st/的推荐,可以进一步改为:

ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

前向安全性(Forward Secrecy)

首先 Nginx 配置上如下代码:

ssl_dhparam /your/path/to/dhparam.pem;

pem 文件是这样生成的:

openssl dhparam -out dhparam.pem 4096

然后会显示:

This is going to take a long time  
.......+...........................+............................+............................+............++*++*++*

这真的会”take a long time”.但根据每台机器的性能不同而花费的时间不同.

dhparam 算法是在 2^4096 个数字中找出两个质数,所以需要的时间挺长。….. 意思是有可能的质数,+ 是正在测试的质数,* 是已经找到的质数。

前向安全性(Forward Secrecy)的概念很简单:客户端和服务器协商一个永不重用的密钥,并在会话结束时销毁它。服务器上的 RSA 私钥用于客户端和服务器之间的 Diffie-Hellman 密钥交换签名。从 Diffie-Hellman 握手中获取的预主密钥会用于之后的编码。因为预主密钥是特定于客户端和服务器之间建立的某个连接,并且只用在一个限定的时间内,所以称作短暂模式(Ephemeral)。
如果使用前向安全机制,攻击者取得了一个服务器的私钥,他是不能解码之前的通讯信息的。这个私钥仅用于 Diffie Hellman 握手签名,并不会泄露预主密钥。Diffie Hellman 算法会确保预主密钥绝不会离开客户端和服务器,而且不能被中间人攻击所拦截。
所有版本的 nginx 都依赖于 OpenSSL 给 Diffie-Hellman 的输入参数。如果不特别声明,将使用 OpenSSL 的默认设置,1024 位密钥。这绝壁是不安全的,因为我们正在使用 2048 位证书,所以要有一个更强大的 DH

HTTP 严格传输安全(HSTS)(HTTP Strict Transport Security)

HTTP严格传输安全(英语:HTTP Strict Transport Security,缩写:HSTS)是一套由互联网工程任务组发布的互联网安全策略机制。网站可以选择使用HSTS策略,来让浏览器强制使用HTTPS与网站进行通信,以减少会话劫持风险。
HSTS的作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。服务器开启HSTS的方法是,当客户端通过HTTPS发出请求时,在服务器返回的超文本传输协议响应头中包含Strict-Transport-Security字段。非加密传输时设置的HSTS字段无效。

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

includeSubDomains是可选的,用来指定是否作用于子域名。支持HSTS的浏览器遇到这个响应头,会把当前网站加入HSTS列表,然后在max-age指定的秒数内,当前网站所有请求都会被重定向为https。即使用户主动输入http://或者不输入协议部分,都将重定向到https://地址。

X-Frame-Options 响应头

X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在 <frame>, <iframe> 或者 <object> 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。
X-Frame-Options 有三个值:
DENY:表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
SAMEORIGIN:表示该页面可以在相同域名页面的 frame 中展示。
ALLOW-FROM uri:表示该页面可以在指定来源的 frame 中展示。
换一句话说,如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载。另一方面,如果设置为 SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。

X-Content-Type-Options 响应头

互联网上的资源有各种类型,通常浏览器会根据响应头的Content-Type字段来分辨它们的类型。例如:”text/html”代表html文档,”image/png”是PNG图片,”text/css”是CSS样式文档。然而,有些资源的Content-Type是错的或者未定义。这时,某些浏览器会启用MIME-sniffing来猜测该资源的类型,解析内容并执行。
例如,我们即使给一个html文档指定Content-Type为”text/plain”,在IE8-中这个文档依然会被当做html来解析。利用浏览器的这个特性,攻击者甚至可以让原本应该解析为图片的请求被解析为JavaScript。通过下面这个响应头可以禁用浏览器的类型猜测行为:

add_header X-Content-Type-Options nosniff;

这个响应头的值只能是nosniff,可用于IE8+和Chrome。

配置 OCSP 装订

ssl_stapling on;  
ssl_stapling_verify on;  
ssl_trusted_certificate /you/path/to/domain.chain.pem;  
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;

domain.chain.pem 里面是域名证书到 ROOT 证书的一个链。
连接到一个服务器时,客户端应该使用证书吊销列表(CRL)或在线证书状态协议(OCSP)记录来校验服务器证书的有效性。CRL 存在一个问题,它已经增长的太快,永远也下载不完。
OCSP 更轻量一些,只需发一个请求。但是副作用是访问一个站点时必须对第三方 OCSP 响应服务器发起 OCSP 请求,这就增加了延迟带来的潜在隐患。事实上,CA 所运营的 OCSP 响应服务器非常不可靠,浏览器如果不能及时收到答复,就会静默失败。攻击者通过 DDoS 攻击一个 OCSP 响应服务器可以禁用其校验功能,这样就降低了安全性。
解决方法是允许服务器在 TLS 握手中发送缓存的 OCSP 记录,以绕开 OCSP 响应服务器。这个机制减少了客户端和 OCSP 响应服务器之间的通讯,称作 OCSP 装订。
客户端会在它的 CLIENT HELLO 中告知其支持 status_request TLS 扩展,服务器仅在客户端请求它的时候才发送缓存的 OCSP 响应。
大多数服务器最长会缓存 OCSP 48 小时。服务器会按照常规的间隔连接到 CA 的 OCSP 响应服务器来获取刷新的 OCSP 记录。OCSP 响应服务器的位置可以从签名的证书中 Authority Information Access 字段中获得。

nginx里边SSL的完整配置

    ssl on;
    #文件位置
    ssl_certificate /path/to/pem;
    ssl_certificate_key /path/to/key;
    ssl_dhparam /path/to/dhparams.pem;
    #会话进程设置
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_session_timeout 5m;
    #加密套件设置
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_prefer_server_ciphers on;
    ssl_ecdh_curve secp384r1;
    #OCSP配置
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 216.69.185.17 208.109.255.17 valid=300s;
    resolver_timeout 5s;
    #HTTP安全配置
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

文章拼凑来源:
https://cipherli.st/
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/X-Frame-Options
https://okwoo.com/open-the-hsts-http-strict-transport-security-the-importance-of
https://www.pupboss.com/nginx-add-ssl/
https://imququ.com/post/web-security-and-response-header.html

用acme-tiny自动更新Let’s Encrypt HTTPS证书

Let’s Encrypt 证书不但免费,还非常简单,虽然每次只有 90 天的有效期,但可以通过脚本定期更新,配好之后一劳永逸。

ACME 全称是 Automated Certificate Management Environment,直译过来是自动化证书管理环境的意思,Let’s Encrypt 的证书签发过程使用的就是 ACME 协议。

acme-tiny是用python写的自动申请/更新Let’s Encrypt HTTPS的工具。

以下是记录Let’s Encrypt HTTPS证书申请部署的全部过程。

1.生成RSA私钥:

	    (umask 077;openssl genrsa 2048 > private.key)
	    (umask 077;openssl genrsa 4096 > private.key)

2.生成CSR请求文件:

        1).RSA 私钥(兼容性好)
	(umask 077; openssl genrsa 2048 > yoursite.key)
	(umask 077; openssl genrsa 4096 > yoursite.key)
        2).ECC 私钥(部分老旧操作系统、浏览器不支持。优点是证书体积小)
	(umask 077;openssl ecparam -genkey -name secp256r1 | openssl ec -out yoursite_ec.key)
	(umask 077;openssl ecparam -genkey -name secp384r1 | openssl ec -out yoursite_ec.key)

然后就可以生成 CSR 文件了。在 CSR 中推荐至少把域名带 www 和不带 www 的两种情况都加进去,其它子域可以根据需要添加,部分系统的openssl.cnf文件所有位置可能有所不同:

	openssl req -new -sha256 -key yoursite.key -subj "/" -reqexts SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:yoursite.com,DNS:www.yoursite.com")) > yoursite.csr

3.配置自动认证目录:

	mkdir -pv /your/wwwroot/challenges

然后配置一个 HTTP 服务,以 Nginx 为例:

	server {
	    server_name yoursite.com www.yoursite.com;
	    location ^~ /.well-known/acme-challenge/ {
	        alias /your/wwwroot/challenges/;
	        try_files $uri =404;
	    }
	    location / {
	        rewrite ^/(.*)$ https://yoursite.com/$1 permanent;
	    }
	}

以上配置优先查找challenges目录下的文件,如果找不到就重定向到 HTTPS 地址。这个验证服务以后更新证书还要用到,建议一直保留。

4.脚本自动获取证书:
1).脚本下载与证书获取:

		wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py
		python acme_tiny.py --account-key ./private.key --csr ./yoursite.csr --acme-dir /your/wwwroot/challenges/ > ./signed.crt

2).Let’s Encrypt的”中间证书”与”网站证书”合在一起:

		wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
		cat signed.crt intermediate.pem > chained.pem

3).Let’s Encrypt的”根证书”和”中间证书”合在一起:

		wget -O - https://letsencrypt.org/certs/isrgrootx1.pem > root.pem
		cat intermediate.pem root.pem > full_chained.pem

5.网站nginx使用的证书

	ssl_certificate     /path/to/chained.pem;
	ssl_certificate_key /path/to/yoursite.key;

6.自动更新证书脚本
Let’s Encrypt 签发的证书只有 90 天有效期,推荐使用脚本定期更新。脚本范例如下:

cd /path/to/nginx/ssl
python acme_tiny.py --account-key ./private.key --csr ./yyfilmtechcom.csr --acme-dir /your/wwwroot/challenges/ > ./signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem
wget -O - https://letsencrypt.org/certs/isrgrootx1.pem > root.pem
cat intermediate.pem root.pem > full_chained.pem
service nginx reload

把脚本放进crontab,每个月定时执行一次:

0 0 1 * * sh /path/to/renew.sh >/dev/null 2>&1

原谅地址:https://imququ.com/post/letsencrypt-certificate.html#toc-0
参考地址:https://github.com/diafygi/acme-tiny

基于OpenSSL自建CA和颁发SSL证书

关于SSL/TLS介绍见文章 SSL/TLS原理详解
关于证书授权中心CA以及数字证书等概念,请移步 OpenSSL 与 SSL 数字证书概念
openssl是一个开源程序的套件、这个套件有三个部分组成:一是libcryto,这是一个具有通用功能的加密库,里面实现了众多的加密库;二是libssl,这个是实现ssl机制的,它是用于实现TLS/SSL的功能;三是openssl,是个多功能命令行工具,它可以实现加密解密,甚至还可以当CA来用,可以让你创建证书、吊销证书。
默认情况ubuntu和CentOS上都已安装好openssl。CentOS 6.x 上有关ssl证书的目录结构:

/etc/pki/CA/
            newcerts    存放CA签署(颁发)过的数字证书(证书备份目录)
            private     用于存放CA的私钥
            crl         吊销的证书

/etc/pki/tls/
             cert.pem    软链接到certs/ca-bundle.crt
             certs/      该服务器上的证书存放目录,可以房子自己的证书和内置证书
                   ca-bundle.crt    内置信任的证书
             private    证书密钥存放目录
             openssl.cnf    openssl的CA主配置文件

1. 颁发证书
1.1 修改CA的一些配置文件
CA要给别人颁发证书,首先自己得有一个作为根证书,我们得在一切工作之前修改好CA的配置文件、序列号、索引等等。

vim /etc/pki/tls/openssl.cnf:
...
[ CA_default ]

dir             = /etc/pki/CA           # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/cacert.pem       # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/cakey.pem # The private key
RANDFILE        = $dir/private/.rand    # private random number file
...
default_days    = 3650                  # how long to certify for
...
# For the CA policy
[ policy_match ]
countryName             = match
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
...
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = CN
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = GD
...
[ req_distinguished_name ] 部分主要是颁证时一些默认的值,可以不动

一定要注意[ policy_match ]中的设定的匹配规则,是有可能因为证书使用的工具不一样,导致即使设置了csr中看起来有相同的countryName,stateOrProvinceName等,但在最终生成证书时依然报错:

Using configuration from /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
The stateOrProvinceName field needed to be the same in the
CA certificate (GuangDong) and the request (GuangDong)

在CA目录下创建两个初始文件:

# touch index.txt serial
# echo 01 > serial

1.2 生成根密钥

# cd /etc/pki/CA/
# openssl genrsa -out private/cakey.pem 2048

为了安全起见,修改cakey.pem私钥文件权限为600或400,也可以使用子shell生成( umask 077; openssl genrsa -out private/cakey.pem 2048 ),下面不再重复。
1.3 生成根证书
使用req命令生成自签证书:

# openssl req -new -x509 -key private/cakey.pem -out cacert.pem

会提示输入一些内容,因为是私有的,所以可以随便输入(之前修改的openssl.cnf会在这里呈现),最好记住能与后面保持一致。上面的自签证书cacert.pem应该生成在/etc/pki/CA下。
以上都是在CA服务器上做的操作,而且只需进行一次,现在转到nginx服务器上执行:

# cd /etc/nginx/ssl
# openssl genrsa -out nginx.key 2048

这里测试的时候CA中心与要申请证书的服务器是同一个。
1.4 为我们的nginx web服务器生成ssl密钥
以上都是在CA服务器上做的操作,而且只需进行一次,现在转到nginx服务器上执行:

# cd /etc/nginx/ssl
# openssl genrsa -out nginx.key 2048

这里测试的时候CA中心与要申请证书的服务器是同一个。
1.5 为nginx生成证书签署请求

# openssl req -new -key nginx.key -out nginx.csr
...
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:GD
Locality Name (eg, city) []:SZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:COMPANY
Organizational Unit Name (eg, section) []:IT_SECTION
Common Name (e.g. server FQDN or YOUR name) []:your.domain.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
同样会提示输入一些内容,其它随便,除了<code>Commone Name</code>一定要是你要授予证书的服务器域名或主机名,<code>challenge password</code>不填。
<strong>1.6 私有CA根据请求来签署证书</strong>
接下来要把上一步生成的证书请求csr文件,发到CA服务器上,在CA上执行:

# openssl ca -in nginx.csr -out nginx.crt
另外在极少数情况下,上面的命令生成的证书不能识别,试试下面的命令:
# openssl x509 -req -in server.csr -CA /etc/pki/CA/cacert.pem -CAkey /etc/pki/CA/private/cakey.pem -CAcreateserial -out server.crt

上面签发过程其实默认使用了-cert cacert.pem -keyfile cakey.pem,这两个文件就是前两步生成的位于/etc/pki/CA下的根密钥和根证书。将生成的crt证书发回nginx服务器使用。
到此我们已经拥有了建立ssl安全连接所需要的所有文件,并且服务器的crt和key都位于配置的目录下,剩下的是如何使用证书的问题。

2. 使用ssl证书

原文链接地址: http://seanlook.com/2015/01/18/openssl-self-sign-ca/

OpenSSL 与 SSL 数字证书概念

首先简单区分一下HTTPS、SSL、OpenSSL三者的关系:
SSL是在客户端和服务器之间建立一条SSL安全通道的安全协议,而OpenSSL是TLS/SSL协议的开源实现,提供开发库和命令行程序。常说的HTTPS是HTTP的加密版,底层使用的加密协议是SSL。
1. PKI、CA与证书
PKI 就是 Public Key Infrastructure 的缩写,翻译过来就是公开密钥基础设施。它是利用公开密钥技术所构建的,解决网络安全问题的,普遍适用的一种基础设施;是一种遵循既定标准的密钥管理平台,它能够为所有网络应用提供加密和数字签名等密码服务及所必需的密钥和证书管理体系。
PKI既不是一个协议,也不是一个软件,它是一个标准,在这个标准之下发展出的为了实现安全基础服务目的的技术统称为PKI。可以说CA(认证中心)是PKI的核心,而数字证书是PKI的最基本元素,还有如apache等服务器、浏览器等客户端、银行等应用,都是pki的组件。这篇文章可以帮助理解:PKI/CA 技术的介绍 。
1.1 CA
为保证用户之间在网上传递信息的安全性、真实性、可靠性、完整性和不可抵赖性CA 机构,又称为证书认证中心 (Certificate Authority) 中心,是一个负责发放和管理数字证书的第三方权威机构,它负责管理PKI结构下的所有用户(包括各种应用程序)的证书,把用户的公钥和用户的其他信息捆绑在一起,在网上验证用户的身份。CA机构的数字签名使得攻击者不能伪造和篡改证书。
认证中心主要有以下5个功能:
1) 证书的颁发:接收、验证用户(包括下级认证中心和最终用户)的数字证书的申请。可以受理或拒绝
2) 证书的更新:认证中心可以定期更新所有用户的证书,或者根据用户的请求来更新用户的证书
3) 证书的查询:查询当前用户证书申请处理过程;查询用户证书的颁发信息,这类查询由目录服务器ldap来完成
4) 证书的作废:由于用户私钥泄密等原因,需要向认证中心提出证书作废的请求;证书已经过了有效期,认证中心自动将该证书作废。认证中心通过维护证书作废列表 (Certificate Revocation List,CRL) 来完成上述功能。
5) 证书的归档:证书具有一定的有效期,证书过了有效期之后就将作废,但是我们不能将作废的证书简单地丢弃,因为有时我们可能需要验证以前的某个交易过程中产生的数字签名,这时我们就需要查询作废的证书。
1.2 Certificate
1.2.1 X.509标准
“SSL证书”这个词是一个相对较大的概念,整个PKI体系中有很多SSL证书格式标准。PKI的标准规定了PKI的设计、实施和运营,规定了PKI各种角色的”游戏规则”,提供数据语法和语义的共同约定。x.509是PKI中最重要的标准,它定义了公钥证书的基本结构,可以说PKI是在X.509标准基础上发展起来的:
 SSL公钥证书
 证书废除列表CRL(Certificate revocation lists 证书黑名单)
参考 http://en.wikipedia.org/wiki/X.509
1.2.2 ssl公钥证书格式

1. 证书版本号(VERSION)
版本号指明X.509证书的格式版本,现在的值可以为:
    1) 0: V1
    2) 1: V2
    3) 2: V3
也为将来的版本进行了预定义

2. 证书序列号(SERIAL NUMBER)
序列号指定由CA分配给证书的唯一的"数字型标识符"。当证书被取消时,实际上是将此证书的序列号放入由CA签发的CRL中,
这也是序列号唯一的原因。

3. 签名算法标识符(SIGNATURE ALGORITHM)
签名算法标识用来指定由CA签发证书时所使用的"签名算法"。算法标识符用来指定CA签发证书时所使用的:
    1) 公开密钥算法
    2) HASH算法
EXAMPLE: SHA256WITHRSAENCRYPTION
须向国际知名标准组织(如ISO)注册

4. 签发机构名(ISSUER)
此域用来标识签发证书的CA的X.500 DN(DN-DISTINGUISHED NAME)名字。包括:
    1) 国家(C)
    2) 省市(ST)
    3) 地区(L)
    4) 组织机构(O)
    5) 单位部门(OU)
    6) 通用名(CN)
    7) 邮箱地址

5. 有效期(VALIDITY)
指定证书的有效期,包括:
    1) 证书开始生效的日期时间
    2) 证书失效的日期和时间
每次使用证书时,需要检查证书是否在有效期内。

6. 证书用户名(SUBJECT)
指定证书持有者的X.500唯一名字。包括:
    1) 国家(C)
    2) 省市(ST)
    3) 地区(L)
    4) 组织机构(O)
    5) 单位部门(OU)
    6) 通用名(CN)
    7) 邮箱地址

7. 证书持有者公开密钥信息(SUBJECT PUBLIC KEY INFO)
证书持有者公开密钥信息域包含两个重要信息:
    1) 证书持有者的公开密钥的值
    2) 公开密钥使用的算法标识符。此标识符包含公开密钥算法和HASH算法。
8. 扩展项(EXTENSION)
X.509 V3证书是在V2的基础上一标准形式或普通形式增加了扩展项,以使证书能够附带额外信息。标准扩展是指
由X.509 V3版本定义的对V2版本增加的具有广泛应用前景的扩展项,任何人都可以向一些权威机构,如ISO,来
注册一些其他扩展,如果这些扩展项应用广泛,也许以后会成为标准扩展项。

9. 签发者唯一标识符(ISSUER UNIQUE IDENTIFIER)
签发者唯一标识符在第2版加入证书定义中。此域用在当同一个X.500名字用于多个认证机构时,用一比特字符串
来唯一标识签发者的X.500名字。可选。

10. 证书持有者唯一标识符(SUBJECT UNIQUE IDENTIFIER)
持有证书者唯一标识符在第2版的标准中加入X.509证书定义。此域用在当同一个X.500名字用于多个证书持有者时,
用一比特字符串来唯一标识证书持有者的X.500名字。可选。

11. 签名算法(SIGNATURE ALGORITHM)
证书签发机构对证书上述内容的签名算法
EXAMPLE: SHA256WITHRSAENCRYPTION

12. 签名值(ISSUER'S SIGNATURE)
证书签发机构对证书上述内容的签名值

example:

CERTIFICATE:
    DATA:
        VERSION: 3 (0X2)
        SERIAL NUMBER: 9 (0X9)
    SIGNATURE ALGORITHM: SHA256WITHRSAENCRYPTION
        ISSUER: C=CN, ST=GUANGDONG, L=SHENZHEN, O=COMPANY TECHNOLOGIES CO., LTD, OU=IT_SECTION, CN=registry.example.com.net/emailAddress=zhouxiao@example.com.net
        VALIDITY
            NOT BEFORE: FEB 11 06:04:56 2015 GMT
            NOT AFTER : FEB  8 06:04:56 2025 GMT
        SUBJECT: C=CN, ST=GUANGDONG, L=SHENZHEN, O=TP-LINK CO.,LTD., OU=NETWORK MANAGEMENT, CN=172.31.1.210
        SUBJECT PUBLIC KEY INFO:
            PUBLIC KEY ALGORITHM: RSAENCRYPTION
                PUBLIC-KEY: (2048 BIT)
                MODULUS:
                    00:A4:B0:DD:EB:C1:CF:5D:47:61:A6:EA:EF:8B:AA:
                    4B:F0:B4:2C:D8:96:C7:7C:AC:FA:C7:35:88:53:D0:
                    ...
                    8A:76:DC:8F:8C:44:C8:0B:3C:36:88:5F:01:F0:44:
                    4E:81:E6:7A:2B:FF:BA:DA:33:A5:27:11:C6:F0:08:
                    6E:F3
                EXPONENT: 65537 (0X10001)
        X509V3 EXTENSIONS:
            X509V3 BASIC CONSTRAINTS: 
                CA:FALSE
            NETSCAPE COMMENT: 
                OPENSSL GENERATED CERTIFICATE
            X509V3 SUBJECT KEY IDENTIFIER: 
                07:C6:87:B7:C1:1E:28:E8:96:3F:EB:40:1E:82:41:45:CA:81:B6:3D
            X509V3 AUTHORITY KEY IDENTIFIER: 
                KEYID:A4:C2:14:6A:39:D1:95:1E:BD:DF:3B:92:4A:5C:12:42:1B:BC:53:B8

    SIGNATURE ALGORITHM: SHA256WITHRSAENCRYPTION
         0C:C6:81:70:CD:0A:2D:94:4F:CB:A4:1D:EF:9E:8E:E4:73:AE:
         50:62:A8:9C:64:EF:56:0F:41:FE:6B:B4:D3:07:37:39:2C:ED:
         ...
         6F:62:61:B8:03:D7:97:31:AB:05:44:20:07:65:8B:AD:E2:CC:
         AD:65:73:F6:82:0F:9E:65:D0:AE:B7:1E:FD:9F:C1:D7:41:6C:
         0F:06:95:EE
-----BEGIN CERTIFICATE-----
MIIEMDCCAXIGAWIBAGIBCTANBGKQHKIG9W0BAQSFADCBTTELMAKGA1UEBHMCQ04X
EJAQBGNVBAGMCUD1YW5NRG9UZZERMA8GA1UEBWWIU2HLBLPOZW4XJJAKBGNVBAOM
...
UJWWRAR6PPZUSO95WUS93HSNML2ZFZ63DS4LCW9IYBGD15CXQWVEIADLI63IZK1L
C/ACD55L0K63HV2FWDDBBA8GLE4=
-----END CERTIFICATE-----

2. 附:数据加密的基础知识
 对称密钥加密
对称密钥加密(一个密钥),也叫做共享密钥加密或机密密钥加密,使用发件人和收件人共同拥有的单个密钥。这种密钥既用于加密,也用于解密,叫做机密密钥。对称密钥加密是加密大量数据的一种行之有效的方法。
对称密钥加密有许多种算法如DES,RC4,IDEA等,但所有这些算法都有一个共同的目的:以可还原的方式将明文 (未加密的数据转换为暗文。暗文使用加密密钥编码,对于没有解密密钥的任何人来说它都是没有意义的。由于对称密钥加密在加密和解密时使用相同的密钥,所以这种加密过程的安全性取决于是否有未经授权的人获得了对称密钥。
衡量对称算法优劣的主要尺度是其密钥的长度。密钥越长,在找到解密数据所需的正确密钥之前必须测试的密钥数量就越多。需要测试的密钥越多,破解这种算法就越困难。
 公钥加密
公钥加密使用两个密钥:一个公钥和一个私钥,这两个密钥在数学上是相关的。为了与对称密钥加密相对照,公钥加密有时也叫做不对称密钥加密。在公钥加密中,公钥可在通信双方之间公开传递,或在公用储备库中发布,但相关的私钥是保密的。只有使用私钥才能解密用公钥加密的数据。使用私钥加密的数据只能用公钥解密。下图中,发件人拥有收件人的公钥,并用它加密了一封邮件,但只有收件人掌握解密该邮件的有关私钥。

公钥算法的主要局限在于,这种加密形式的速度相对较低。实际上,通常仅在关键时刻才使用公钥算法,如在实体之间交换对称密钥时,或者在签署一封邮件的散列时(散列是通过应用一种单向数学函数获得的一个定长结果,对于数据而言,叫做散列算法)。将公钥加密与其它加密形式(如对称密钥加密)结合使用,可以优化性能,如数字签名和密钥交换。
常用公钥算法:
RSA:适用于数字签名和密钥交换。 是目前应用最广泛的公钥加密算法,特别适用于通过 Internet 传送的数据,RSA算法以它的三位发明者的名字命名。
DSA:仅适用于数字签名。 数字签名算法 (Digital Signature Algorithm, DSA) 由美国国家安全署 (United States National Security Agency, NSA) 发明,已作为数字签名的标准。DSA 算法的安全性取决于自计算离散算法的困难。这种算法,不适用于数据加密。
Diffie-Hellman:仅适用于密钥交换。 Diffie-Hellman 是发明的第一个公钥算法,以其发明者 Whitfield Diffie 和 Martin Hellman 的名字命名。Diffie-Hellman 算法的安全性取决于在一个有限字段中计算离散算法的困难。
单向散列算法:
散列,也称为散列值或消息摘要 ,是一种与基于密钥(对称密钥或公钥)的加密不同的数据转换类型。散列就是通过把一个叫做散列算法的单向数学函数应用于数据,将任意长度的一块数据转换为一个定长的、不可逆转的数字,其长度通常在128~256位之间。所产生的散列值的长度应足够长,因此使找到两块具有相同散列值的数据的机会很少。如发件人生成邮件的散列值并加密它,然后将它与邮件本身一起发送。而收件人同时解密邮件和散列值,并由接收到的邮件产生另外一个散列值,然后将两个散列值进行比较。如果两者相同,邮件极有可能在传输期间没有发生任何改变。
下面是几个常用的散列函数:
MD5:是RSA数据安全公司开发的一种单向散列算法,MD5被广泛使用,可以用来把不同长度的数据块进行暗码运算成一个128位的数值。
SHA-1:与 DSA 公钥算法相似,安全散列算法1(SHA-1)也是由 NSA 设计的,并由 NIST 将其收录到 FIPS 中,作为散列数据的标准。它可产生一个 160 位的散列值。SHA-1 是流行的用于创建数字签名的单向散列算法。
MAC(Message Authentication Code):消息认证代码,是一种使用密钥的单向函数,可以用它们在系统上或用户之间认证文件或消息,常见的是HMAC(用于消息认证的密钥散列算法)。
CRC(Cyclic Redundancy Check):循环冗余校验码,CRC校验由于实现简单,检错能力强,被广泛使用在各种数据校验应用中。占用系统资源少,用软硬件均能实现,是进行数据传输差错检测地一种很好的手段(CRC 并不是严格意义上的散列算法,但它的作用与散列算法大致相同,所以归于此类)。
数字签名:结合使用公钥与散列算法
数字签名是邮件、文件或其它数字编码信息的发件人将他们的身份与信息绑定在一起(即为信息提供签名)的方法。对信息进行数字签名的过程,需要将信息与由发件人掌握的秘密信息一起转换(使用私钥)为叫做签名的标记。数字签名用于公钥环境(任何人都可以拥有)中,它通过验证发件人确实是他或她所声明的那个人,并确认收到的邮件与发送的邮件完全相同。
散列算法处理数据的速度比公钥算法快得多。散列数据还缩短了要签名的数据的长度,因而加快了签名过程。
密钥交换:结合使用对称密钥与公钥
对称密钥算法非常适合于快速并安全地加密数据。但其缺点是,发件人和收件人必须在交换数据之前先交换机密密钥。结合使用加密数据的对称密钥算法与交换机密密钥的公钥算法可产生一种既快速又灵活的解决方案。
3.参考
openSSL命令、PKI、CA、SSL证书原理
X.509 wikipeida
PKI 基础知识
数字证书及CA的扫盲介绍

原文链接地址: http://seanlook.com/2015/01/15/openssl-certificate-encryption/

SSL/TLS原理详解

1.SSL/TLS概览

  •     1.1整体结构

SSL是一个介于HTTP协议与TCP之间的一个可选层,其位置大致如下:

SSL:(Secure Socket Layer,安全套接字层),为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取。当前版本为3.0。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。
SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。 SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。
TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。
TLS 1.0是IETF(Internet Engineering Task Force,Internet工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本,可以理解为SSL 3.1,它是写入了 RFC 的。该协议由两层组成: TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)。较低的层为 TLS 记录协议,位于某个可靠的传输协议(例如 TCP)上面。
SSL/TLS协议提供的服务主要有:
a)认证用户和服务器,确保数据发送到正确的客户机和服务器;
b)加密数据以防止数据中途被窃取;
c)维护数据的完整性,确保数据在传输过程中不被改变。

  •     1.2TLS与SSL的差异

1)版本号:TLS记录格式与SSL记录格式相同,但版本号的值不同,TLS的版本1.0使用的版本号为SSLv3.1。
2)报文鉴别码:SSLv3.0和TLS的MAC算法及MAC计算的范围不同。TLS使用了RFC-2104定义的HMAC算法。SSLv3.0使用了相似的算法,两者差别在于SSLv3.0中,填充字节与密钥之间采用的是连接运算,而HMAC算法采用的是异或运算。但是两者的安全程度是相同的。
3)伪随机函数:TLS使用了称为PRF的伪随机函数来将密钥扩展成数据块,是更安全的方式。
4)报警代码:TLS支持几乎所有的SSLv3.0报警代码,而且TLS还补充定义了很多报警代码,如解密失败(decryption_failed)、记录溢出(record_overflow)、未知CA(unknown_ca)、拒绝访问(access_denied)等。
5)密文族和客户证书:SSLv3.0和TLS存在少量差别,即TLS不支持Fortezza密钥交换、加密算法和客户证书。
6)certificate_verify和finished消息:SSLv3.0和TLS在用certificate_verify和finished消息计算MD5和SHA-1散列码时,计算的输入有少许差别,但安全性相当。
7)加密计算:TLS与SSLv3.0在计算主密值(master secret)时采用的方式不同。
8)填充:用户数据加密之前需要增加的填充字节。在SSL中,填充后的数据长度要达到密文块长度的最小整数倍。而在TLS中,填充后的数据长度可以是密文块长度的任意整数倍(但填充的最大长度为255字节),这种方式可以防止基于对报文长度进行分析的攻击。
TLS的主要增强内容
TLS的主要目标是使SSL更安全,并使协议的规范更精确和完善。TLS 在SSL v3.0 的基础上,提供了以下增强内容:
a)更安全的MAC算法
b)更严密的警报
c)“灰色区域”规范的更明确的定义
d)TLS对于安全性的改进
TLS对于安全性的改进
a)对于消息认证使用密钥散列法:TLS 使用“消息认证代码的密钥散列法”(HMAC),当记录在开放的网络(如因特网)上传送时,该代码确保记录不会被变更。SSLv3.0还提供键控消息认证,但HMAC比SSLv3.0使用的(消息认证代码)MAC 功能更安全。
b)增强的伪随机功能(PRF):PRF生成密钥数据。在TLS中,HMAC定义PRF。PRF使用两种散列算法保证其安全性。如果任一算法暴露了,只要第二种算法未暴露,则数据仍然是安全的。
c)改进的已完成消息验证:TLS和SSLv3.0都对两个端点提供已完成的消息,该消息认证交换的消息没有被变更。然而,TLS将此已完成消息基于PRF和HMAC值之上,这也比SSLv3.0更安全。
d)一致证书处理:与SSLv3.0不同,TLS试图指定必须在TLS之间实现交换的证书类型。
e)特定警报消息:TLS提供更多的特定和附加警报,以指示任一会话端点检测到的问题。TLS还对何时应该发送某些警报进行记录。

    2.密钥协商过程——TLS握手
SSL协议分为两部分:Handshake Protocol和Record Protocol。其中Handshake Protocol用来协商密钥,协议的大部分内容就是通信双方如何利用它来安全的协商出一份密钥。 Record Protocol则定义了传输的格式。
由于非对称加密的速度比较慢,所以它一般用于密钥交换,双方通过公钥算法协商出一份密钥,然后通过对称加密来通信,当然,为了保证数据的完整性,在加密前要先经过HMAC的处理。
SSL缺省只进行server端的认证,客户端的认证是可选的。以下是其流程图(摘自TLS协议)。

2.1 客户端发出请求(ClientHello)
由于客户端(如浏览器)对一些加解密算法的支持程度不一样,但是在TLS协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。在TLS握手阶段,客户端首先要告知服务端,自己支持哪些加密算法,所以客户端需要将本地支持的加密套件(Cipher Suite)的列表传送给服务端。除此之外,客户端还要产生一个随机数,这个随机数一方面需要在客户端保存,另一方面需要传送给服务端,客户端的随机数需要跟服务端产生的随机数结合起来产生后面要讲到的 Master Secret 。
综上,在这一步,客户端主要向服务器提供以下信息:
1) 支持的协议版本,比如TLS 1.0版
2) 一个客户端生成的随机数,稍后用于生成”对话密钥”
3) 支持的加密方法,比如RSA公钥加密
4) 支持的压缩方法
2.2 服务器回应(SeverHello)
上图中,从Server Hello到Server Done,有些服务端的实现是每条单独发送,有服务端实现是合并到一起发送。Sever Hello和Server Done都是只有头没有内容的数据。
服务端在接收到客户端的Client Hello之后,服务端需要将自己的证书发送给客户端。这个证书是对于服务端的一种认证。例如,客户端收到了一个来自于称自己是www.alipay.com的数据,但是如何证明对方是合法的alipay支付宝呢?这就是证书的作用,支付宝的证书可以证明它是alipay,而不是财付通。证书是需要申请,并由专门的数字证书认证机构(CA)通过非常严格的审核之后颁发的电子证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被串改。另外,证书还有个有效期。
在服务端向客户端发送的证书中没有提供足够的信息(证书公钥)的时候,还可以向客户端发送一个 Server Key Exchange,
此外,对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。服务端可以向客户端发出 Cerficate Request 消息,要求客户端发送证书对客户端的合法性进行验证。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。
跟客户端一样,服务端也需要产生一个随机数发送给客户端。客户端和服务端都需要使用这两个随机数来产生Master Secret。
最后服务端会发送一个Server Hello Done消息给客户端,表示Server Hello消息结束了。
综上,在这一步,服务器的回应包含以下内容:
1) 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信
2) 一个服务器生成的随机数,稍后用于生成”对话密钥”
3) 确认使用的加密方法,比如RSA公钥加密
4) 服务器证书
2.3 客户端回应(Certificate Verify)
Client Key Exchange
如果服务端需要对客户端进行验证,在客户端收到服务端的 Server Hello 消息之后,首先需要向服务端发送客户端的证书,让服务端来验证客户端的合法性。
Certificate Verify
接着,客户端需要对服务端的证书进行检查,如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥。然后,向服务器发送下面三项信息:
1) 一个随机数。该随机数用服务器公钥加密,防止被窃听
2) 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送
3) 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验
上面第一项的随机数,是整个握手阶段出现的第三个随机数,它是客户端使用一些加密算法(例如:RSA, Diffie-Hellman)产生一个48个字节的Key,这个Key叫 PreMaster Secret,很多材料上也被称作 PreMaster Key。
ChangeCipherSpec
ChangeCipherSpec是一个独立的协议,体现在数据包中就是一个字节的数据,用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,准备使用之前协商好的加密套件加密数据并传输了。
在ChangecipherSpec传输完毕之后,客户端会使用之前协商好的加密套件和Session Secret加密一段 Finish 的数据传送给服务端,此数据是为了在正式传输应用数据之前对刚刚握手建立起来的加解密通道进行验证。
2.4 服务器的最后回应(Server Finish)
服务端在接收到客户端传过来的 PreMaster 加密数据之后,使用私钥对这段加密数据进行解密,并对数据进行验证,也会使用跟客户端同样的方式生成 Session Secret,一切准备好之后,会给客户端发送一个 ChangeCipherSpec,告知客户端已经切换到协商过的加密套件状态,准备使用加密套件和 Session Secret加密数据了。之后,服务端也会使用 Session Secret 加密一段 Finish 消息发送给客户端,以验证之前通过握手建立起来的加解密通道是否成功。
根据之前的握手信息,如果客户端和服务端都能对Finish信息进行正常加解密且消息正确的被验证,则说明握手通道已经建立成功,接下来,双方可以使用上面产生的Session Secret对数据进行加密传输了。
2.5 几个secret
Secret Keys
上面的分析和讲解主要是为了突出握手的过程,所以PreMaster secret,Master secret,session secret都是一代而过,但是对于Https,SSL/TLS深入的理解和掌握,这些Secret Keys是非常重要的部分。所以,准备把这些Secret Keys抽出来单独分析和讲解。
我们先来看看这些Secret Keys的生成过程以及作用流程图:

PreMaster secret
PreMaster Secret是在客户端使用RSA或者Diffie-Hellman等加密算法生成的。它将用来跟服务端和客户端在Hello阶段产生的随机数结合在一起生成 Master Secret。在客户端使用服务端的公钥对PreMaster Secret进行加密之后传送给服务端,服务端将使用私钥进行解密得到PreMaster secret。也就是说服务端和客户端都有一份相同的PreMaster secret和随机数。
PreMaster secret前两个字节是TLS的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在Client Hello阶段,客户端会发送一份加密套件列表和当前支持的SSL/TLS的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能串改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对数据进行破解。所以,服务端需要对密文中解密出来对的PreMaster版本号跟之前Client Hello阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。
关于PreMaster Secret(Key)的计算请参考 Https SSL/TLS PreMaster/Master Secret(Key)计算。
Master secret
上面已经提到,由于服务端和客户端都有一份相同的PreMaster secret和随机数,这个随机数将作为后面产生Master secret的种子,结合PreMaster secret,客户端和服务端将计算出同样的Master secret。
Master secret是有系列的hash值组成的,它将作为数据加解密相关的secret的 Key Material 的一部分。Key Material最终解析出来的数据如下:

其中,write MAC key,就是session secret或者说是session key。Client write MAC key是客户端发数据的session secret,Server write MAC secret是服务端发送数据的session key。MAC(Message Authentication Code),是一个数字签名,用来验证数据的完整性,可以检测到数据是否被串改。
关于Session Secret(Key)的计算请参考 Https SSL/TLS Session Secret(Key)计算
    2.6 应用数据传输
在所有的握手阶段都完成之后,就可以开始传送应用数据了。应用数据在传输之前,首先要附加上MAC secret,然后再对这个数据包使用write encryption key进行加密。在服务端收到密文之后,使用Client write encryption key进行解密,客户端收到服务端的数据之后使用Server write encryption key进行解密,然后使用各自的write MAC key对数据的完整性包括是否被串改进行验证。
    2.7 总结
SSL客户端(也是TCP的客户端)在TCP链接建立之后,发出一个ClientHello来发起握手,这个消息里面包含了自己可实现的算法列表和其它一些需要的消息,SSL的服务器端会回应一个ServerHello,这里面确定了这次通信所需要的算法,然后发过去自己的证书(里面包含了身份和自己的公钥)。Client在收到这个消息后会生成一个秘密消息,用SSL服务器的公钥加密后传过去,SSL服务器端用自己的私钥解密后,会话密钥协商成功,双方可以用同一份会话密钥来通信了。
3. 附:密钥协商的形象化比喻
如果上面的说明不够清晰,这里我们用个形象的比喻,我们假设A与B通信,A是SSL客户端,B是SSL服务器端,加密后的消息放在方括号[]里,以突出明文消息的区别。双方的处理动作的说明用圆括号()括起。
A:我想和你安全的通话,我这里的对称加密算法有DES,RC5,密钥交换算法有RSA和DH,摘要算法有MD5和SHA。

B:我们用DES-RSA-SHA这对组合好了。
这是我的证书,里面有我的名字和公钥,你拿去验证一下我的身份(把证书发给A)。
目前没有别的可说的了。

A:(查看证书上B的名字是否无误,并通过手头早已有的CA的证书验证了B的证书的真实性,如果其中一项有误,发出警告并断开连接,这一步保证了B的公钥的真实性)
(产生一份秘密消息,这份秘密消息处理后将用作加密密钥,加密初始化向量(IV)和hmac的密钥。将这份秘密消息-协议中称为per_master_secret-用B的公钥加密,封装成称作ClientKeyExchange的消息。由于用了B的公钥,保证了第三方无法窃听)
我生成了一份秘密消息,并用你的公钥加密了,给你(把ClientKeyExchange发给B)
注意,下面我就要用加密的办法给你发消息了!
(将秘密消息进行处理,生成加密密钥,加密初始化向量和hmac的密钥)
[我说完了]

B:(用自己的私钥将ClientKeyExchange中的秘密消息解密出来,然后将秘密消息进行处理,生成加密密钥,加密初始化向量和hmac的密钥,这时双方已经安全的协商出一套加密办法了)
注意,我也要开始用加密的办法给你发消息了!
[我说完了]

A: [我的秘密是…]

B: [其它人不会听到的…]
4. SSL安全性
SecurityPortal在2000年底有一份文章《The End of SSL and SSH?》激起了很多的讨论, 目前也有一些成熟的工具如dsniff(http://www.monkey.org/~dugsong/dsniff/)可以通过man in the middle攻击来截获https的消息。
从上面的原理可知,SSL的结构是严谨的,问题一般出现在实际不严谨的应用中。常见的攻击就是middle in the middle攻击,它是指在A和B通信的同时,有第三方C处于信道的中间,可以完全听到A与B通信的消息,并可拦截,替换和添加这些消息。
1) SSL可以允许多种密钥交换算法,而有些算法,如DH,没有证书的概念,这样A便无法验证B的公钥和身份的真实性,从而C可以轻易的冒充,用自己的密钥与双方通信,从而窃听到别人谈话的内容。
而为了防止middle in the middle攻击,应该采用有证书的密钥交换算法。
2) 有了证书以后,如果C用自己的证书替换掉原有的证书之后,A的浏览器会弹出一个警告框进行警告,但又有多少人会注意这个警告呢?
3) 由于美国密码出口的限制,IE,netscape等浏览器所支持的加密强度是很弱的,如果只采用浏览器自带的加密功能的话,理论上存在被破解可能。
5. 代理
下面探讨一下SSL的代理是怎样工作的
当在浏览器里设置了https的代理,而且里输入了https://www.example.com之后,浏览器会与proxy建立tcp链接,然后向其发出这么一段消息:

CONNECT SERVER.EXAMPLE.COM:443 HTTP/1.1
HOST: SERVER.EXAMPLE.COM:443

然后proxy会向webserver端建立tcp连接,之后,这个代理便完全成了个内容转发装置。浏览器与web server会建立一个安全通道,因此这个安全通道是端到端的,尽管所有的信息流过了proxy,但其内容proxy是无法解密和改动的(当然要由证书的支持,否则这个地方便是个man in the middle攻击的好场所,见上面的安全部分)。
CA证书以及如何使用OpenSSL自签署,见文章OpenSSL自签署证书 。
6. 参考
Https(SSL/TLS)原理详解
SSL与TLS的区别以及介绍
SSL/TLS协议运行机制的概述
SSL/TLS/WTLS原理
Transport Layer Security (TLS)
传输层安全协议
Survival guides – TLS/SSL and SSL (X.509) Certificates

原文链接地址:https://segmentfault.com/a/1190000002554673

CA认证原理

1.什么是CA
认证中心(CA─Certificate Authority)作为权威的、可信赖的、公正的第三方机构,专门负责发放并管理所有参与网上交易的实体所需的数字证书。它作为一个权威机构,对密钥进行有效地管理,颁发证书证明密钥的有效性,并将公开密钥同某一个实体(消费者、商户、银行)联系在一起。
随着认证中心(或称CA中心)的出现,使得开放网络的安全问题得以迎刃而解。利用数字证书、PKI、对称加密算法、数字签名、数字信封等加密技术,可以建立起安全程度极高的加解密和身份认证系统,确保电子交易有效、安全地进行,从而使信息除发送方和接收方外,不被其他方知悉(保密性);保证传输过程中不被篡改(完整性和一致性);发送方确信接收方不是假冒的(身份的真实性和不可伪装性);发送方不能否认自己的发送行为(不可抵赖性)。
2.CA的架构
CA认证的主要工具是CA中心为网上作业主体颁发的数字证书。CA架构包括PKI结构、高强度抗攻击的公开加解密算法、数字签名技术、身份认证技术、运行安全管理技术、可靠的信任责任体系等等。从业务流程涉及的角色看, 包括认证机构、数字证书库和黑名单库、密钥托管处理系统、证书目录服务、证书审批和作废处理系统。从CA的层次结构来看, 可以分为认证中心(根CA)、密钥管理中心(KM)、认证下级中心(子CA)、证书审批中心(RA中心)、证书审批受理点(RAT)等。 CA中心一般要发布认证体系声明书,向服务的对象郑重声明CA的政策、保证安全的措施、服务的范围、服务的质量、承担的责任、操作流程等条款。
根据PKI的结构, 身份认证的实体需要有一对密钥, 分别为私钥和公钥。 其中的私钥是保密的, 公钥是公开的。从原理上讲, 不能从公钥推导出私钥,穷举法来求私钥则由于目前的技术、运算工具和时间的限制而不可能。每个实体的密钥总是成对出现,即一个公钥必定对应一个私钥。公钥加密的信息必须由对应的私钥才能解密,同样,私钥做出的签名, 也只有配对的公钥才能解密。 公钥有时用来传输对称密钥,这就是数字信封技术。 密钥的管理政策是把公钥和实体绑定, 由CA中心把实体的信息和实体的公钥制作成数字证书, 证书的尾部必须有CA中心的数字签名。 由于CA中心的数字签名是不可伪造的, 因此实体的数字证书不可伪造。CA中心对实体的物理身份资格审查通过后,才对申请者颁发数字证书, 将实体的身份与数字证书对应起来。由于实体都信任提供第三方服务的CA中心, 因此, 实体可以信任由CA中心颁发数字证书的其他实体, 放心地在网上进行作业和交易。
3.CA的职责
CA中心主要职责是颁发和管理数字证书。 其中心任务是颁发数字证书,并履行用户身份认证的责任。CA中心在安全责任分散、运行安全管理、系统安全、物理安全、数据库安全、人员安全、密钥管理等方面, 需要十分严格的政策和规程,要有完善的安全机制。另外要有完善的安全审计、运行监控、容灾备份、事故快速反应等实施措施, 对身份认证、访问控制、防病毒防攻击等方面也要有强大的工具支撑。CA中心的证书审批业务部门则负责对证书申请者进行资格审查, 并决定是否同意给该申请者发放证书,并承担因审核错误引起的、为不满足资格的证书申请者发放证书所引起的一切后果, 因此, 它应是能够承担这些责任的机构担任;证书操作部门(Certificate Processor,简称CP)负责为已授权的申请者制作、发放和管理证书, 并承担因操作运营错误所产生的一切后果, 包括失密和为没有授权者发放证书等, 它可以由审核业务部门自己担任, 也可委托给第三方担任。
4.RA
RA(Registration Authority),数字证书注册审批机构。RA系统是CA的证书发放、管理的延伸。它负责证书申请者的信息录入、审核以及证书发放等工作;同时,对发放的证书完成相应的管理功能。发放的数字证书可以存放于IC卡、硬盘或软盘等介质中。RA系统是整个CA中心得以正常运营不可缺少的一部分。
5.数字证书
数字安全证书就是标志网络用户身份信息的一系列数据,用来在网络通讯中识别通讯各方的身份,即要在Internet上解决”我是谁”的问题,就如同现实中我们每一个人都要拥有一张证明个人身份的身份证或驾驶执照一样,以表明我们的身份或某种资格。
在网上电子交易中, 商户需要确认持卡人是信用卡或借记卡的合法持有者,同时持卡人也必须能够鉴别商户是否是合法商户,是否被授权接受某种品牌的信用卡或借记卡支付。为处理这些关键问题,必须有一个大家都信赖的机构来发放数字安全证书。数字安全证书就是参与网上交易活动的各方(如持卡人、商家、支付网关) 身份的代表,每次交易时,都要通过数字安全证书对各方的身份进行验证。数字安全证书是由权威公正的第三方机构即CA中心签发的,它在证书申请被认证中心批准后,通过登记服务机构将证书发放给申请者。
数字安全证书是一个经证书授权中心数字签名的包含公开密钥拥有者信息以及公开密钥的文件。最简单的证书包含一个公开密钥、名称以及证书授权中心的数字签名。一般情况下证书中还包括密钥的有效时间,发证机关(证书授权中心)的名称,该证书的序列号等信息,证书的格式遵循ITUT X.509国际标准。
一个标准的X.509数字安全证书包含以下一些内容:
证书的版本信息;
证书的序列号,每个证书都有一个唯一的证书序列号;
证书所使用的签名算法;
证书的发行机构名称,命名规则一般采用X.500格式;
证书的有效期,现在通用的证书一般采用UTC时间格式;
证书所有人的名称,命名规则一般采用X.500格式;
证书所有人的公开密钥;
证书发行者对证书的签名。

Nginx 路由杂谈 – Rewrite 指令与重定向

在书写 nginx 路由规则的时候, 得保证规则配置的规范, 否则维护起来成本很高。 本文简要地讨论了在 rewrite 模块的基础实现的简单路由规则,并解释了常用指令的使用细节。

rewrite 与 location

首先,这是一个不完整 nginx 虚拟主机配置:

server {

    root /service/http;

    index index.php;


    rewrite ^/api/(.*)+ /index.php?app=api&amp;method=$1 break;

    rewrite ^/index.php/(.*)+ /old_api_warning.html break;


    location / {

        return 200 "index";

    }


    location = /index.php {

        return 200 "index.php";

    }

}

上面的例子中, 指定的类型可以分为两种。

  • server,root, index, location 是 ngx_http_core_module 提供的指令
  • 而 rewrite 则是 ngx_http_rewrite_module 提供的指令之一, 同类的还有常用的 if

简单地概括, nginx 的处理配置流程如下

  1. 进行 rewrite 规则匹配,根据命中规则改写 location。
  2. 如果没有被其他指令中断并退出, 则进入 location 匹配。
  3. 执行匹配成功的 location 区块中的指令。

而对于 rewrite 系列指令和 location 指令的安排, 在书写配置的时候, 应该先定义好 location , 因为 location 是和 nginx 和后端服务沟通的桥梁。 再根据 location 的需要, 使用 rewrite 将各种各样用户输入的 url 正确地映射到 对应 locaton , 由 location 中的 proxy 指令转发给后端。

比如一个常规的 php 站点,有以下类似的 location 配置。

# 静态资源

location /assets {

    root /service/http/assets/;

}

# 入口 php 脚本 位置

location /index.php {

    root /service/http/phpsrc/webroot/;

# ... 若干 fast-cgi 代理规则

}

#注意, 这份配置省略了不必要的指令,能够满足大部分的 php 应用的需要。

有时候,为了优化 url 的展示,或者兼容旧应用的 url 规则, 只是这么简单的两条 location 配置自然是不够用的。这时候我们可以通过 rewrite 规则进行弥补。

rewrite /index.html$ /app/page-default; //兼容旧 url

rewrite /app/page-(.*) /index.php?app=api&page=$1 break;

请注意这两条 rewrite 规则区别的在最后一个 flag 参数 break,可用的 flag 参数还有 `permanent`, `redirect`, `last` 等, 后面分析它们之间的差别。

多出来的 break 参数作用会使得 rewirte 指令的跳转方式发生变化:

  • 没有 flag 的 rewrite 指令完成 location 改写之后,继续往下寻找其他 rewrite 规则,看看有没有符合要求的。如果没有,那么进入 location 匹配。
  • 带 break,跳过其他所有 rewrite 规则,进入 location 匹配

这里简单总结一下:

  • 如果某一条 rewrite 规则命中直接转发给后端应用,那么应该加上一个 break 标记。
  • 如果 rewrite 规则起补充作用,还需要其他规则配合完成,那么不带第三个的 flag 参数。

以上说的 rewrite 规则属于 nginx 的内部重定向规则, 也就是说, 用户外部看到的 url 依然是他输入的 url , 而转给后端应用的 $uri , 则已经是 nginx 改写之后的结果。

如果需要进行显式地外部重定向, 需要借助 redirect , permanent 这两个 flag 进行 302 和 301 重定向. 它的行为和 break 类似, 区别在于 nginx 会中断流程, 通过 http 请求告诉用户端进行重定向, 也就是这次请求不需要进过后端服务, 由 nginx 全职负责。

rewrite /error.html$ /error2.html redirect;

break 和 last 区别

这两个 flag 都会中断当前 rewrite 流程, 不再继续匹配后续的 rewrite 指令。

wiki 上是这么写的

stops processing the current set of ngx_http_rewrite_module directives and starts a search for a new location matching the changed URI

如果是在 server 的顶级部分, 那么它们的作用是相同, 跳过剩下的 rewrite 指定, 进入 location 匹配。 如果 rewrite 是在 server 区块顶级 if 内部, 和直接放在 server 下级的 rewrite 行为是一致的。

server {

    rewrite /error1.html /error.html break;

    rewrite /error2.html /error.html last;

&nbsp;

    if ( $arg_version = "1.1" ) {

        rewrite /error3.html /error.html break;

    }

&nbsp;

    location = error.html {

    }

}

以上的 rewrite 的跳转行为是相同的, 进入 location 匹配流程。

而两者的区别, 在于当 rewrite 指令存在于 location 区块中时, 见例子

location = index.php {

    if ( $arg_q  = "" ) {

      rewrite /index.php /error.html last;

    }

}
location = error.html {

    if ( $arg_test ~= "" ) {

        rewrite /error.html /error-test.html break;

    }

}

第一个 location , 如果 q 参数为空, 那么将展示错误页面。

第二个 location , 如果 test 参数不为空, 通过 rewrite 规则,使用另外一个 error-test.html, 但 location 不变

注意, 这里并没有一个 `location = error2.html` 的匹配规则

从这个 case 的结果, 可以明显得区分两个指令之间的细微差别

  • last 跳出 location 块,重新进行 location 匹配
  • break 跳过 location 下的后续 rewrite 规则,执行其他指令。

所以 last 的特殊在于重新进行 location 匹配, 这也就是为什么会从”locaton = index.php”转向”locaton = error.html”

所以一般情况下, 使用 break 指令会相对安全, 不会造成循环重定向。

比如:

location = error.html {

    rewrite /error.html /error.html  break;

&nbsp;

    if ($arg_q = "") {

      return 404 "not q";

    }

&nbsp;

    fastcgi_pass 127.0.0.1:9000;

    #其他 fastcgi 配置

}

 

location = error.html {

    rewrite /error.html /error.html last;

    fastcgi_pass 127.0.0.1:9000;

}

第一个例子,完成了 rewrite 指令之后,break 指令使得后续的其他 rewrite 规则失效, 接着进行 proxy. 第二个例子会导致不断地进行 location 匹配, 最终导致 nginx 返回 500.

返回结果是这样的:

HTTP/1.1 500 Internal Server Error

Server: nginx/1.6.3

Date: Sat, 18 Apr 2015 12:10:49 GMT

Content-Type: text/html

Content-Length: 192

Connection: close

注:nginx 会记录同一条 rewrite 规则的执行次数,如果超过10次,将自动触发 500 进行自我保护。

小结

这里构造了两组例子用来说明 last 和 break 两个 flag 参数行为上的不一致。 并不是说 rewrite 规则在 server 和 location 上下文中的行为不一致, 而是他们的行为特征很容易造成误解。

两者的本质区别在于是否重新进行 location 匹配,所以当在 location 上下文 进行 last rewrite时。 对于不熟悉 rewrite 指定的其他人容易造成误解。

所以还是前文所提到的观点, 尽可能地将 rewrite 和 location 离开来。 在 location 中进行 rewrite, 容易造成重定向问题。

由于 rewrite 模块的 `rewrite` 和 `if` 指令会使得 nginx

的路由规则出现较多的逻辑和分支跳转, 在维护性上是比较糟糕的,

并不推荐过多地进行使用, 本文只是从行为和特性上分析了这些指令,

并不代表支持过度使用 rewrite 指令。

return 指令的应用

在 rewrite 模块中, 有一条非常有用的指令 return, 用于直接返回客户端指定的状态码。 甚至支持指定文本内容和url, 相比起使用 rewrite 指令302进行曲线救国,要简便地多。

location = /index.php {

    if ( $arg_q = "" ) {

        return 302 /page_not_found.html;

    }

&nbsp;

    if ( $arg_id = "" ) {

        return 404 "page not found";

    }

    return 200 "hello";

}

对于常规的基于 url 提供服务的应用, 基础的 rewrite 指令配合已经足够完成大部分任务。