ssl证书openssl.docx

上传人:b****8 文档编号:28366024 上传时间:2023-07-10 格式:DOCX 页数:21 大小:620.75KB
下载 相关 举报
ssl证书openssl.docx_第1页
第1页 / 共21页
ssl证书openssl.docx_第2页
第2页 / 共21页
ssl证书openssl.docx_第3页
第3页 / 共21页
ssl证书openssl.docx_第4页
第4页 / 共21页
ssl证书openssl.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

ssl证书openssl.docx

《ssl证书openssl.docx》由会员分享,可在线阅读,更多相关《ssl证书openssl.docx(21页珍藏版)》请在冰豆网上搜索。

ssl证书openssl.docx

ssl证书openssl

ssl证书&&openssl

以一个问题来开始此篇文章的讲解。

你知道我们通常访问的https是如何保障你的安全的吗?

你是否会想到加密、认证和数字证书?

那么

加密:

如何加密,怎么保证数据不被泄露?

认证:

誰认证誰,如何进行认证?

数字证书:

数字证书是何物?

为什么有这个东西?

作用是什么?

本文主要简单地讲述证书及openssl的使用,让我们带着这些问题开始文章的旅程。

一、加密和算法

1.散列(hash)

Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。

常用的散列函数是SHA1和MD5。

哈希是单向的,不可通过散列值得到原文;

不同的内容做散列计算,计算出的散列值为相同的概率几乎等于0;

哈希主要用在:

文件校验、数字签名、快速查找等。

例如:

图1文件校验(散列应用)

图1说明了如何校验文件是否被修改,但是如果中间存在一个攻击者,截获报文后,修改下文件内容,一样可以计算出一个散列值,所以是不够安全的。

图2则使用了密钥化散列信息认证码(HMAC,Keyed-hashMessageAuthenticationCode),通过加入共享密钥(仅用户A和用户B知道密钥),在计算散列,这样来保证数据是完整的,不被修改的。

图2文件校验(HMAC)

2.对称加密(SymmetricCryptography)

需要对加密和解密使用相同密钥的加密算法。

由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。

但是管理密钥不方便,要求共享密钥。

如果N个人相互之间都要用对称加密进行通讯,则每个人维护的密钥是N-1个。

目前流行的对称加密算法有AES、DES、3DES、Blowfish、RC2、RC4、RC5等等。

3.非对称加密(AsymmetricCryptography)

与对称加密算法不同,非对称加密算法需要两个密钥:

公开密钥(publickey)和私有密钥(privatekey)。

公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。

因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

非对称加密算法的优点是密钥管理很方便,缺点是速度慢。

通常来讲,公钥是每个人都能得到的,私钥是只有自己持有;

A与B之间进行通信,安全的方式:

1.A给B发送消息,使用B的公钥进行加密,然后发给B,只有B用私钥才能解密成明文;

2.B给A发送消息,使用A的公钥进行加密,然后发给A,只有A用私钥才能解密成明文;

A获取B的公钥,必须是安全的方式;B获取A的公钥,也必须是安全的方式;

一个例子:

4.数字签名(DigitalSignature)

现实生活中,我们用签名来证明某个东西是与签名者相关的,是不可否认的,不可伪造的;

在虚拟世界里,我们有数字签名来帮助证明某个文档是你创建的,或者是你认可的。

数字签名所用的技术是散列和非对称加密。

基于前面非对称加密的介绍,对签名的信息进行散列计算,用私钥对这个散列值进行加密;这样就得到一个签名。

图3签名示例

当用户B比对散列值3与散列值2是否相同,如果相同则认为是A签名的,否则不是。

二、数字证书

如果现实生活中是用身份证来证明身份,那么在虚拟世界中,则会使用数字证书来证明身份。

并不是每个人都需要用数字证书来证明身份,那么什么情况下,会使用数字证书来证明身份呢?

普通用户一般情况下,不需要证明自己的身份,大部分网站不关心是谁访问了网站,现在的网站只关心流量啊~反过来,网站就需要证明自己的身份了。

比如你想要提交信用卡信息给预定航班的网站,那么你如何确定你正在访问的网站就是你所想要访问的那个呢?

现在钓鱼网站很多的。

比如你想访问的是“”,但其实你访问的是“”,所以在提交自己的信息之前你需要验证一下网站的身份,要求网站出示数字证书。

一般正常的网站都会主动出示自己的数字证书。

由于证书在网页浏览中最为常见,所以我下面举的例子都是基于浏览器的。

1.数字证书的构成

我们的身份证是由公安机关颁发的,并加有很多防伪技术,不能伪造(或者说很难)。

同样的,数字证书也有专门的发证机关(CertificateAuthority,简称CA,其实是一些商业公司啦)。

比较常见的发证机关是VeriSign。

数字证书的发证机关会对自己发放的证书加上自己的数字签名,以保证证书不能被伪造。

那数字证书到底包含了些什么呢?

1.持有者姓名(CommonName)

2.发证机关(Issuer)

3.有效日期(Validity)

4.证书持有人的公钥(Subject’sPublicKeyInfo)

5.扩展信息(Extension)

6.用发证机关对该证书的数字签名(CertificateSignature)

基本信息就这些了(这些信息会在后面的章节有所解释),为了更清晰的说明问题,来几张截图(火狐->工具->选项->高级->证书->查看证书):

图4证书信息

从图4我们可以看到,Certificate(证书)和Signature(签名)是分开的,但其实这个Signature也是证书的一部分。

可以这么理解,数字证书包含证书主体和数字签名。

证书中的签名是对证书主体的签名。

2.如何验证数字证书

当浏览器拿到一个数字证书:

1.先看发证机关(图5),主要是看以下三个:

OrganizationName(O),OrganizationalUnitName(OU),CommonName(CN)

2.找到相应的发证机关的证书,获得发证机关的公钥,用此公钥解密被加密的SHA1,这样就获得了此证书的SHA1值,我们称它为Hash1(图6、图7)。

3.浏览器用SHA1算法对此证书重新计算一遍SHA1,获得Hash2。

4.然后比较Hash1和Hash2是否相等。

如果相等就证明这张证书是由发证机关颁发的,并且没有被篡改过。

图5服务器的公钥证书

图6签名过程

图7验证Server的证书

3.验证证书持有者

经过上述的证书验证后,可以认为证书没问题,是可靠的。

但是还需要做一步,需要查看下发送者是否是证书的持有者(也就是通常意义上的身份证上的照片是否是本人,看完证件,还要比对下脸)。

通过证书里的公钥加密一段信息发送给证书持有者,如果对方能发送回来(加密的或者明文),说明对方是证书的持有者(也即,对方有对应的私钥)。

4.核对名字

通常对于用证书来做web服务器的应用来说,证书中的名字(Commonname)很重要,一般与根域名相等。

如果不相等,则认为证书存在问题。

5.证书的级联

所有的证书都是基于另一张证书(可信任证书)进行认证的。

换句话说,用一张已知合法的证书来证明另一张未知的证书。

发证机关的证书默认是可信任的,这些证书称之为“根证书”。

由于申请证书的人数众多,发证机关忙不过来,这时候需要一些代理来帮忙签发证书,代理可能也需要代理来帮忙签发证书。

这样就存在了层级关系:

图8级联证书

这里的”USERTrustLegacySecureServerCA”是由根证书”AddTrustExternalCARoot”签发的。

验证这张证书的时候,需要从下往上递归验证。

是否是CA证书,可以看下扩展信息中的”基本约束”,如下图:

图9查看是否是CA

三、SSL的基本原理

现在回到我们最原始的问题,由于Internet的架构问题,信息在网络上传输是很容易被别人获取的,那如何建立一个安全的传输网络呢?

前面我们讨论了很多保证信息安全的技术,而SSL就是建立在这些技术的基础上的一套协议,用来保证通信的安全。

SSL全称是SecureSocketsLayer,它是一种间于传输层(比如TCP/IP)和应用层(比如HTTP)的协议。

具体的SSL协议很复杂,我这里只讲一个大概。

最简单的方法来保证通信安全是用非对称加密。

我们前面讲过数字证书的认证,如果双方都认证了对方的数字证书,那么每次传输信息的时候都用对方的公钥加密,这样就只有对方能解密,从而保证了信息的安全。

但是对于日常应用(比如网页浏览)有两个问题:

1.非对称加密速度缓慢,消耗资源

如果客户端和服务器之间传输文件用非对称加密的话,速度一定慢的忍无可忍。

2.不可能要求每个用户都去申请数字证书

申请数字证书是一个相当麻烦的过程,要求每个上网的用户都拥有证书是不可能的事情。

SSL通过“握手协议”和“传输协议”来解决上述问题。

握手协议是基于非对称加密的,而传输协议是基于对称加密的。

根据不同的应用,SSL对证书的要求也是不一样的,可以是单方认证(比如HTTP,FTP),也可以是双方认证(比如网上银行)。

通常情况下,服务器端的证书是一定要具备的,客户端的证书不是必须的。

图10握手过程

Phase1:

图11阶段1

client_hello:

包括一个随机数和一系列的可支持的加密组件(以性能高到低的方式排列)

server_hello:

包含一个随机数和一个从客户端发来的组件中选择的加密组件

加密组件:

每个加密组件包含一个密钥交换算法、加密算法、MAC(消息认证码),例如:

TLS_RSA_WITH_AES_256_CBC_SHA256

密钥交换算法:

DH(Diffie-Hellman)算法、RSA(公钥/私钥)

Phase2(例如使用DH):

图12DH交换密钥

server_key_exchange中包括p、a、S1;

client_key_exchange中包括C1;

最后生成K是共用密钥。

Phase3:

客户端的认证:

服务器或许会请求客户端发送证书,如果客户端有,则发送证书,如果没有则发送一个no_certificate的警告信息。

如果发送了证书才会有certificate_verify,包括了客户端的认证,包括了一个之前握手消息的散列值。

Phase4:

客户端发送ChangeCipherSpec消息,通知SSL服务器后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。

SSL客户端计算已交互的握手消息(除ChangeCipherSpec消息外所有已交互的消息)的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给SSL服务器。

SSL服务器利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。

同样地,SSL服务器发送ChangeCipherSpec消息,通知SSL客户端后续报文将采用协商好的密钥和加密套件进行加密和MAC计算。

SSL服务器计算已交互的握手消息的Hash值,利用协商好的密钥和加密套件处理Hash值(计算并添加MAC值、加密等),并通过Finished消息发送给SSL客户端。

SSL客户端利用同样的方法计算已交互的握手消息的Hash值,并与Finished消息的解密结果比较,如果二者相同,且MAC值验证成功,则证明密钥和加密套件协商成功。

四、openssl开源库的使用(客户端)

openssl开源库的网址https:

//www.openssl.org/,包括源码、文档等内容。

这一节,我们主要使用的是ssl/tls库。

1.初始化

作为一个客户端,首先要初始化一个Context对象(一个SSL_CTX),这个对象是用来创建一个新的连接对象。

Context初始化,包括四个主要的部分,如下:

SSL_METHOD*meth;

SSL_CTX*ctx;

SSL_library_init();//初始化整个库,加载了一些openssl的算法等内容,只需要在程序启动的时候,初始化一次就可以了。

meth=SSLv23_method();//用SSLv2或者V3兼容的方式

ctx=SSL_CTX_new(meth);//创建一个Context对象

/*Loadourkeysandcertificates*/

if(!

(SSL_CTX_use_certificate_chain_file(ctx,keyfile)))//加载证书

berr_exit("Can’treadcertificatefile");

SSL_CTX_set_default_passwd_cb(ctx,password_cb);//如果密码是加密过的,password_cb是个回调函数,可以还原密码

if(!

(SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM)))//加载私有密钥

berr_exit("Can’treadkeyfile");

/*LoadtheCAswetrust*/

if(!

(SSL_CTX_load_verify_locations(ctx,CA_LIST,0)))//加载可信任的CA证书

berr_exit("Ca’treadCAlist");

如果一个client要去执行认证,则需要加载自己的public/privatekey对儿和相关证书。

SSL_CTX_use_certificate_chain_file用来加载CA证书;

SSL_CTX_use_PrivateKey_file用来加载私钥,通常密码是加密的,可以通过SSL_CTX_set_default_passwd_cb回调函数来获取密码。

加载根CA列表,如果你要认证对端,则需要知道CA,加载函数:

SSL_CTX_load_verify_locations

2.握手处理

SSL连接的第一步就是要执行SSL握手过程。

握手认证server(可选的认证client),并且建立关键材料用来保护后续的数据。

SSL_connect()函数用来执行SSL的握手协议。

如果使用阻塞协议,SSL_connect会一直阻塞,直到握手完成,或者返回一个错误。

SSL_connect返回1表示成功,0或者负数表示一个错误。

代码如下:

sock=tcp_connect(host,port);//假设tcp_connect是用来建立一个tcp连接的函数

ssl=SSL_new(ctx);//初始化TLS/SSL

sbio=BIO_new_socket(sock,BIO_NOCLOSE);//创建一个BIO对象,关联到TCPsocket

SSL_set_bio(ssl,sbio,sbio);//将ssl关联到BIO对象上

if(SSL_connect(ssl)<=0)//这里执行握手

berr_exit("SSLconnecterror");

3.检查server的证书

X509*peer;

charpeer_CN[256];

if(SSL_get_verify_result(ssl)!

=X509_V_OK)//对端发来的证书验证,如果不是X509

berr_exit("Certificatedoesn’tverify");

/*Checkthecommonname*/

peer=SSL_get_peer_certificate(ssl);//提取server的证书

X509_NAME_get_text_by_NID(X509_get_subject_name(peer),NID_commonName,peer_CN,256);//获取CommonName

if(strcasecmp(peer_CN,host))

err_exit("Commonnamedoesn’tmatchhostname");

4.读写数据

SSL_write()函数用来发送数据到对端,像write()一样使用。

只是传的参数是SSL对象而不是文件描述符。

在阻塞的模式,SSL_write()不会返回,直到数据都发送完,或者一个错误返回,然而write可能只写部分数据。

注意:

SSL_MODE_ENABLE_PARTIAL_WRITE标记使能部分写的功能。

代码如下:

r=SSL_write(ssl,request,request_len);//写数据,数据在request中,长度是request_len

switch(SSL_get_error(ssl,r)){

caseSSL_ERROR_NONE:

if(request_len!

=r)

err_exit("Incompletewrite!

");

break;

default:

berr_exit("SSLwriteproblem");

break;

}

SSL_read()用来读取数据,就像read一样,我们选择合适的参数传给SSL_read()。

SSL_read返回读到的数据长度。

如果不存在数据可读,则SSL_read是阻塞的,会一直等待。

r=SSL_read(ssl,buf,BUFSIZZ);//读取数据

switch(SSL_get_error(ssl,r)){

caseSSL_ERROR_NONE:

len=r;

break;

caseSSL_ERROR_ZERO_RETURN:

gotoshutdown;

caseSSL_ERROR_SYSCALL:

fprintf(stderr,"SSLError:

Prematureclose0);

gotodone;

default:

berr_exit("SSLreadproblem");

}

//这里对数据进行处理

例子中使用函数SSL_get_error()来替代errno,SSL_get_error()检查返回值,并且指出是否错误发生了,并且错误是什么。

5.关闭Closure/shutdown/cleanup

TCP使用FIN标记来说明发送者已经发完所有的数据。

SSLv2简单的允许任何一方使用一个TCPFIN来终止SSL连接。

这会导致“截断攻击”:

攻击者通过简单地伪造TCPFIN来使看起来消息是短的。

除非受害者有某种方式知道消息的长度。

为了避免这种情况,SSLv3引进了一个close_notify警告。

close_notify是一个SSL消息(因此是安全的),但是不是数据流本身的一部分,不背应用所看到。

当发送完close_notify后,不会再有数据会被发送。

因此,SSL_read返回0,说明socket被关闭了,已经收到了close_notify消息。

如果client先收到一个FIN,则认为是一个“过早关闭”。

如果我们读到SSL_read返回0,没有任何错,则我们需要发送close_notify到server端(通过SSL_shutdown()来发送)。

SSL_shutdown()返回1表示完全关闭,0表示不完全关闭,-1是出现一个错误。

当收到服务器发来的close_notify,唯一可能出错的是发送我们的close_notify,否则SSL_shutdown总是会成功。

代码片段(client):

while

(1)

{

r=SSL_read(ssl,buf,BUFSIZZ);

switch(SSL_get_error(ssl,r))

{

caseSSL_ERROR_NONE:

//未出错

len=r;

break;

caseSSL_ERROR_ZERO_RETURN:

//未出错,我们已经收到close_notify

gotoshutdown;//这里去发送我们的close_notify

caseSSL_ERROR_SYSCALL:

fprintf(stderr,"SSLError:

Prematureclose\n");//收到一个“过早关闭”的信息

gotodone;

default:

berr_exit("SSLreadproblem");/*错误处理,这里是退出程序*/

}

/*数据处理*/

}

shutdown:

r=SSL_shutdown(ssl);//发送给server端一个close_nofity

switch(r)

{

case1:

break;/*Success*/

case0:

case-1:

default:

berr_exit("Shutdownfailed");

}

done:

SSL_free(ssl);/*释放资源*/

/*释放相关变量*/

五、openssl证书常用命令

x509证书一般会用到三类文,key,csr,crt。

Key是私用密钥openssl格,通常是rsa算法。

Csr是证书请求文件,用于申请证书。

在制作csr文件的时,必须使用自己的私钥来签署申,还可以设定一个密钥。

crt是CA认证后的证书文,(windows下面的,其实是crt),签署人用自己的key给你签署的凭证。

1.key的生成

opensslgenrsa-des3-outserver.key2048

这样是生成rsa私钥,des3算法,openssl格式,2048位强度。

server.key是密钥文件名。

为了生成这样的密钥,需要一个至少四位的密码。

可以通过以下方法生成没有密码的key:

opensslrsa-inserver.key-outserver.key

server.key就是没有密码的版本了。

这种没密码的私钥这种用法挺多,比如webserver(lighttpd)这种方式,不可能每次启动server的时候,都要求用户输入密码,太过麻烦。

2.生成CA的crt

opensslreq-new-x509-keyserver.key-outca.crt-days3650

生成的ca.crt文件是用来签署下面的server.csr文件。

需要输入一堆信息,有一个Commonname通常是CA机构的域名(这里,我们可以自己取一个名字)。

3.csr的生成方法

opensslreq-new-keyserver.key-outserver.csr

需要依次输入国家,地区,组织,email。

最重要的是有一个commonname,可以写你的名字或者域名。

如果为了https申请,这个必须和域名吻合,否则会引发浏览器警报。

生成的csr文件交给CA签名后形成服务端自己的证书。

注意Commonname与CA的Commonname要不一样,否则会校验失败。

4.crt生成方法

CSR文件必须有CA的签名才可形成证书,可将此文件发送到verisign等地方由它验证,要交一大笔钱,何不自己做CA呢。

opensslx509-req-days3650-inserver.csr-CAca.crt-CAkeyserver.key-CAcreateserial-outserver.crt

输入

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1