行云无鸣

2008-09-10

(转)SSL单双向验证原理

Filed under: 未分类 — 标签:, , — hellyguo @ 09:04

  为了便于更好的认识和理解 SSL 协议,这里着重介绍 SSL 协议的握手协议。SSL 协议既用到了公钥加密技术又用到了对称加密技术,对称加密技术虽然比公钥加密技术的速度快,可是公钥加密技术提供了更好的身份认证技术。SSL 的握手协议非常有效的让客户和服务器之间完成相互之间的身份认证,其主要过程如下:
① 客户端的浏览器向服务器传送客户端 SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。
② 服务器向客户端传送 SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。
③ 客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的 CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过, 通讯将断开;如果合法性验证通过,将继续进行第四步。
④ 用户端随机产生一个用于后面通讯的“对称密码”,然后用服务器的公钥(服务器的公钥从步骤②中的服务器的证书中获得)对其加密,然后将加密后的“预主密码”传给服务器。
⑤ 如果服务器要求客户的身份认证(在握手过程中为可选),用户可以建立一个随机数然后对其进行数据签名,将这个含有签名的随机数和客户自己的证书以及加密过的“预主密码”一起传给服务器。
⑥ 如果服务器要求客户的身份认证,服务器必须检验客户证书和签名随机数的合法性,具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的 CA 是否可靠,发行 CA 的公钥能否正确解开客户证书的发行 CA 的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的“预主密 码”,然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)。
⑦ 服务器和客户端用相同的主密码即“通话密码”,一个对称密钥用于 SSL 协议的安全数据通讯的加解密通讯。同时在 SSL 通讯过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。
⑧ 客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。
⑨ 服务器向客户端发出信息,指明后面的数据通讯将使用的步骤⑦中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。
⑩ SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。
双向认证 SSL 协议的具体过程
  ① 浏览器发送一个连接请求给安全服务器。
② 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。
③ 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。
④ 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。
⑤ 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。
⑥ 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。
⑦ 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。
⑧ 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。
⑨ 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。
⑩ 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。
上面所述的是双向认证 SSL 协议的具体通讯过程,这种情况要求服务器和用户双方都有证书。单向认证 SSL 协议不需要客户拥有 CA 证书,具体的过程相对于上面的步骤,只需将服务器端验证客户证书的过程去掉,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的 (这并不影响 SSL 过程的安全性)密码方案。 这样,双方具体的通讯内容,就是加过密的数据,如果有第三方攻击,获得的只是加密的数据,第三方要获得有用的信息,就需要对加密的数据进行解密,这时候的 安全就依赖于密码方案的安全。而幸运的是,目前所用的密码方案,只要通讯密钥长度足够的长,就足够的安全。这也是我们强调要求使用 128 位加密通讯的原因。

证书各部分的含义
  Version ,证书版本号,不同版本的证书格式不同
Serial Number, 序列号,同一身份验证机构签发的证书序列号唯一
Algorithm Identifier, 签名算法,包括必要的参数 Issuer 身份验证机构的标识信息
Period of Validity, 有效期
Subject, 证书持有人的标识信息
Subject’s Public Key, 证书持有人的公钥
Signature, 身份验证机构对证书的签名
证书的格式
认证中心所发放的证书均遵循 X.509 V3 标准,其基本格式如下:
证书版本号(Certificate Format Version) 含义:用来指定证书格式采用的 X.509 版本号。
证书序列号(Certificate Serial Number) 含义:用来指定证书的唯一序列号,以标识 CA 发出的所有公钥证书。
签名(Signature) 算法标识(Algorithm Identifier) 含义:用来指定 CA 签发证书所用的签名算法。   签发此证书的 CA 名称(Issuer ) 含义:用来指定签发证书的 CA 的 X.500 唯一名称(DN, Distinguished Name)。
证书有效期(Validity Period) 起始日期(notBefore) 终止日期(notAfter) 含义:用来指定证书起始日期和终止日期。
用户名称(Subject) 含义:用来指定证书用户的 X.500 唯一名称(DN,Distinguished Name)。
用户公钥信息(Subject Public Key Information)
算法(algorithm)
算法标识(Algorithm Identifier)
用户公钥(subject Public Key) 含义:用来标识公钥使用的算法,并包含公钥本身。
证书扩充部分(扩展域)(Extensions) 含义:用来指定额外信息。

X.509 V3 证书的扩充部分(扩展域)及实现方法
CA 的公钥标识(Authority Key Identifier)
公钥标识(SET 未使用)(Key Identifier)
签发证书者证书的签发者的甄别名(Certificate Issuer)
签发证书者证书的序列号(Certificate Serial Number)

X.509 V3 证书的扩充部分(扩展域)及实现
  CA 的公钥标识(Authority Key Identifier)
公钥标识(SET 未使用)(Key Identifier)
签发证书者证书的签发者的甄别名(Certificat
签发证书者证书的序列号(Certificate Serial N含义:CA 签名证书所用的密钥对的唯一标识
用户的公钥标识(Subject Key Identifier) 含义:用来标识与证书中公钥相关的特定密钥进行解密。
证书中的公钥用途(Key Usage) 含义:用来指定公钥用途。
用户的私钥有效期(Private Key Usage Period)
起始日期(Note Before)
终止日期(Note After) 含义:用来指定用户签名私钥的起始日期和终止日期。
CA 承认的证书政策列表(Certificate Policies) 含义:用来指定用户证书所适用的政策,证书政策可由对象标识符表示。
用户的代用名(Substitutional Name) 含义:用来指定用户的代用名。
CA 的代用名(Issuer Alt Name) 含义:用来指定 CA 的代用名。
基本制约(Basic Constraints) 含义:用来表明证书用户是最终用户还是 CA。
在 SET 系统中有一些私有扩充部分(扩展域)Hashed Root Key 含义:只在根证书中使用,用于证书更新时进行回溯。
证书类型(Certificate Type) 含义:用来区别不同的实体。该项是必选的。
商户数据(Merchant Data) 含义:包含支付网关需要的所有商户信息。
持卡人证书需求(Card Cert Required) 含义:显示支付网关是否支持与没有证书的持卡人进行交易。
SET 扩展(SETExtensions) 含义:列出支付网关支持的支付命令的 SET 信息扩展。
CRL 数据定义版本(Version) 含义:显示 CRL 的版本号。
CRL 的签发者(Issuer) 含义:指明签发 CRL 的 CA 的甄别名。
CRL 发布时间(this Update)
预计下一个 CRL 更新时间(Next Update)
撤销证书信息目录(Revoked Certificates)
CRL 扩展(CRL Extension)
CA 的公钥标识(Authority Key Identifier)
CRL 号(CRL Number)

转自:http://hi.baidu.com/ligq/blog/item/ae39bc99a60d810d6e068c4b.html

2008-08-09

BCB6+Indy10完成HTTPS验证服务器证书

Filed under: 未分类 — 标签:, , , , , , — hellyguo @ 10:19

在项目中用到了HTTPS,但仅仅是加密,没有使用证书验证。客户要求加入。
看着Indy简陋的文档,翻阅了无数Delphi英文及中文网页后,始终不得要领。
在拜读了IndySSL – using certificate authentication – Client side issues [zz]一文(此文源头已无法打开,故就不提供URL了,请诸君自行Google)后,终于开始有点头绪了:得设置校验模式,并编写回调函数处理校验事件。
拙劣的BCB功底,让我在申明函数时吃够了苦!
.h
//必须申明函数指针,而且是闭包的,也就是说必须封闭在某个Class中
typedef bool __fastcall (__closure *OnDealVerifyPeer)(TIdX509* Certificate) ;
//在某Class中申明函数,参数与上述函数指针一致
public:
bool __fastcall OnMyDealVerifyPeer(TIdX509* Certificate);

.cpp
//具体回调函数代码
bool __fastcall THttpText::OnMyDealVerifyPeer(TIdX509* Certificate)
{
Application->MessageBoxA(Certificate->Subject->OneLine.c_str(),"info",0);
return true;
}
//初始化SSL环境
void __fastcall InitHttp (TIdHTTP *Http, OnDealVerifyPeer DealMethod1, OnDealStatusInfo DealMethod2)
{
...;
if (NeedSecurity)
{
TIdSSLIOHandlerSocket *InterceptSSL = new TIdSSLIOHandlerSocket (NULL);
//校验模式设置
TIdSSLVerifyModeSet verifyModeSet ;
verifyModeSet << sslvrfPeer << sslvrfFailIfNoPeerCert << sslvrfClientOnce ;
InterceptSSL->SSLOptions->VerifyMode = verifyModeSet;
//校验深度
InterceptSSL->SSLOptions->VerifyDepth = 3;
//SSL运作模式,一度曾认为该参数是校验模式,卡死在这里。在这里,我是客户端,故设置为Client
InterceptSSL->SSLOptions->Mode = sslmClient;
//SSL版本
InterceptSSL->SSLOptions->Method = sslvSSLv3;
//证书配对校验的回调函数设置
InterceptSSL->OnVerifyPeer = DealMethod1;
//SSL状态变化时的回调函数,可在此处设置,借以在回调函数中输出SSL握手信息
InterceptSSL->OnStatusInfo = DealMethod2;
Http->IOHandler = InterceptSSL;
}
...;
}

在尝试了上述代码后,发现的确可以在回调函数中获得证书信息。但,却只是得到根证书的信息。而且,一旦开启了校验,原本可以正常运行的SSL,就会无法连接上服务器,报“SSL Error”。
在诸多Delphi代码中搜寻后,在某pas文件发现了下述语句:

// TODO: Indy9 problems... if we try and verify, it disconnects us.

伤心啊,我用的也是Indy9,看来得升级了。
安装好Indy10后,再度编译程序,就直接报错了:Indy10相对于Indy9,变化还蛮大。
.h
//必须申明函数指针,而且是闭包的,也就是说必须封闭在某个Class中,添加了两个参数
typedef bool __fastcall (__closure *OnDealVerifyPeer)(TIdX509* Certificate) ;
//在某Class中申明函数,参数与上述函数指针一致,添加了两个参数
public:
bool __fastcall OnMyDealVerifyPeer(TIdX509* Certificate,bool aOK,int depth);

.cpp
//具体回调函数代码,添加了两个参数
bool __fastcall THttpText::OnMyDealVerifyPeer(TIdX509* Certificate,bool aOK,int depth)
{
Application->MessageBoxA(Certificate->Subject->OneLine.c_str(),"info",0);
return true;
}
//初始化SSL环境
void __fastcall InitHttp (TIdHTTP *Http, OnDealVerifyPeer DealMethod1, OnDealStatusInfo DealMethod2)
{
...;
if (NeedSecurity)
{
//TIdSSLIOHandlerSocket不存在了,改为TIdSSLIOHandlerSocketOpenSSL
TIdSSLIOHandlerSocketOpenSSL *InterceptSSL = new TIdSSLIOHandlerSocketOpenSSL (NULL);
//校验模式设置
TIdSSLVerifyModeSet verifyModeSet ;
verifyModeSet << sslvrfPeer << sslvrfFailIfNoPeerCert << sslvrfClientOnce ;
InterceptSSL->SSLOptions->VerifyMode = verifyModeSet;
//校验深度
InterceptSSL->SSLOptions->VerifyDepth = 3;
//SSL运作模式,一度曾认为该参数是校验模式,卡死在这里。在这里,我是客户端,故设置为Client
InterceptSSL->SSLOptions->Mode = sslmClient;
//SSL版本
InterceptSSL->SSLOptions->Method = sslvSSLv3;
//根证书,直接从Windows的证书库中导出的VeriSign根证书
InterceptSSL->SSLOptions->RootCertFile = "VeriSign.cer";
//证书配对校验的回调函数设置
InterceptSSL->OnVerifyPeer = DealMethod1;
//SSL状态变化时的回调函数,可在此处设置,借以在回调函数中输出SSL握手信息
InterceptSSL->OnStatusInfo = DealMethod2;
Http->IOHandler = InterceptSSL;
}
...;
}

自此,终于成功在回调函数处获得整个证书链上的每个证书信息,可以进行进一步的校验了

2008-04-14

ihs+was报"Invalid method in request \x80L\x01\x03"

Filed under: 未分类 — 标签:, , , — hellyguo @ 09:43

配置完成,报错:

[Fri Apr 11 13:01:20 2008] [error] [client x.x.x.x] Invalid method in request \x80L\x01\x03

千辛万苦排查,怎么都排查不出原因。结果是URL输入错误,输入了本地回环地址!配置SSL后,是无法使用本地回环地址来访问HTTPS服务的。

2007-12-13

ihs+was配置ssl后,启动报SSL0227E

Filed under: 未分类 — 标签:, , , — hellyguo @ 14:58

消息:SSL0227E:握手失败,密钥文件中未找到指定的标签。

  • 原因:密钥文件中不存在指定的密钥标签
  • 解决方案:检查如果编码,‘SSLServerCert’伪指令是正确的,而且对于密钥数据库中的一个密钥,标签有效。

根据上面的描述,则httpd.conf中,SSLServerCert对应的,应是于IKEYMAN中看到的个人证书一栏中的标签ihsrequest:

证书截图

%d 博主赞过: