大纲

SSL_加密解密

进程间通信所引发的安全问题
我们知道不同主机进程间的通信可以通过socket(ip:port)来实现.这里主要以C/S模型来介绍,
服务器端为了能让任何人随时能够访问自己,因此有一个固定的ip和port,时刻保持在监听状态.
而客户端想要去访问时,会在自己linux内核中随机注册一个socket,进而通过TCP/IP协议,以及交换机和路由器层层递进.将消息发生至服务器端,而后服务器端将本地磁盘的文件信息再次以同意层层递进的方式返回给客户端.以达到双方进程间通信.

以上的通信过程,完全是基于明文发生,也就是可以被所有人看见,且能获取其内容的.由于此问题的出现,ITSEC这一组织,首次提出信息安全的保密性、完整性、可用性的概念.

安全威胁
    保密性威胁:通过窃听等手段窃取信息.
    完整性威胁: 通过修改、伪装、重放来进行攻击.
    可用性威胁: 使用某种手段让目标机器停止提供服务,也称为拒绝服务.(Dos)
安全通信的ssl协议
在此需求下,之后有网景公司写出ssl协议.Secure Socket layer,是安全套接字层协议.
其是处于TCP/IP协议的应用层及传输层之间,当数据需要进行通信保密时,可以借用此ssl层,进而达到保密的功用.
ssl版本有(Netscape,1994)ssl1.0,ssl2.0,ssl3.0,在之后又有了将其标准化后的协议tls(transport layer security),tls的版本有tls1.0(相当于ssl3.0;IETF:1999),tls1.1,tls1.2(常用版本),tls1.3(草案阶段).


预防以上安全威胁的解决方案(加密解密技术与协议)
安全机制有:访问控制(安全服务)和密码学(加密解密).

    加密解密的方式:

        对称加密:
            加密和解密使用同一密钥的方法.
            采用的是块密码,将数据分成固定大小的块,逐个进行加密、解密.

        常见的算法:
            DES(Data Encryption Standard)
            3DES(tripe DES)
            AES(Advanced Encryption Standard)
            Twofish、Blowfish、IDEA、RC6、CAST5等

        用途:
            数据的加密解密;

        缺陷:
            1 密钥过长(由于密钥安全性跟所给的密钥相关,密钥越复杂,则其加密算法安全性更高)
            2 由于密钥过长,导致了分发的难度

        非对称加密(公开密钥加密):
            非对称加密也加公开密钥加密,也就是俗称的公钥加密.使用一对密钥进行加密解密,分别为公钥(public key)、私钥(private key).

            特征:
                私钥自己保留,公钥由私钥提取出来可公开给所有人.
                公钥加密的数据只能由与之对应的私钥解密.反之,私钥加密的数据只能由与之对应的公钥解密.

            常见算法:
                RSA、DSA、ELGamal、DH
                DSS: Digital Signature Standard
                DSA:Digital Signature Algorithm

            用途:
                1 身份验证;
                2 密钥交换;
                3 加密(不常用):加密数据

            缺陷:
                 对数据的加密比对称加密要慢3个数量级

        单向加密(哈希函数):
            给定一个数据,根据其算法定长输出一个固定长度的值.

            特征:
                1 定长输出(不管数据大小,输出的特征码长度不变)
                2 雪崩效应(数据改变一个微小的字符,导致其特征码大幅变化)
                3 只能加密不能解密(单向加密)

            常见算法:
                MD5(Message Digest 5),128bits
                SHA1(Secure Hash Algorithm 1),160bits
                SHA224、SHA256、SHA384、SHA512

            用途:
                用于提取数据的特征码,验证数据完整性.
加密解密的详细步骤:

SSL_ssl_02

发送方:
       1 提取数据的特征码,将其附加在数据后面(用于数据完整性验证)        
       2 使用发送方自己的私钥对特征码进行加密,加密后的密文称为数字签名(用于身份验证)          
       3 生成一个临时密钥,用此密钥对数据以及签名一起加密(对称加密,用于加强保密性)            
       4 将临时密钥用接受方的公钥进行加密(用于密钥交换)

接受方:

       1 将收到的数据用自己的私钥解密,获取临时密钥(密钥交换实现)         
       2 用临时密钥解密,获取数字签名(数据保密性实现)           
       3 用发送方的公钥进行解密,获取特征码.(若能够解密则证明是发送方本人,也就是验证身份)            
       4 对数据进行提取特征码,与解密的特征码比对.(如果两者的特征码相同,则说明数据没有变动.也就是完整性得以验证)


看完上述过程不知有何不妥呢?发送方与接受方之间存在不确定关系.为什么这样说,如果是一个第三方的用户,像告诉"发送方"我是"接受方",反之,告诉"接收方"我是"发送方".在此场景下,完全无法确定通信对象,就是我想要通信的对象.因而我们需要这么一个能够保证,与我通信的人就是我想要通信的对象,这么一个功能.于是有了一个名为CA的机构.


认证协议:

    CA是PKI(public key infrastructure)公钥基础设施的一个组成部分.CA是一个证书颁发机构,使用数字证书的形式,为双方提供可信、可靠的通信.

    证书作用机制:

        首先要想提供一个可信、可靠的通道.那么首先此CA机构自身,必须要能够被信任.因此证书机构自己先给自己颁发证书,再给注册者发放证书.证书有此机构的公钥,用于验证证书来源可靠性.还有一点,所有的CA都是由根CA所衍生,只有是可信机构发布的证书,则都能够被认同.

    先来看一下PKI的组成:

        签证机构:CA    (办理认证的机构)            
        注册机构:RA    (申请×××的机构)            
        证书吊销列表:CRL   (证书丢失,用于挂失)            
        证书存取库       (当别人请求认时的资料库)

    由于每个CA的证书格式的理解都有所不同,因而有了x.509这个数字证书标准,常用版本为x.509.v3此标准定义了证书所需要:

        1 证书的版本号;               
        2 证书的序列号,每个证书的序列号唯一;            
        3 证书所使用的签名算法;           
        4 证书的发行机构名称;            
        5 证书的有效期限;              
        6 证书所有人的名称;             
        7 证书所有人的公钥;             
        8 发行商的唯一标识;             
        9 证书所有人的唯一标识;              
       10 扩展;              
       11 签名:CA对此证书的签名;
ssl会话主要三步:
客户端向服务器端索要并验证证书;
双方协商生成"会话密钥";
双方采用"会话密钥"进行加密通信;


SSL_CA_03

SSL_CA_04



基于ssl通讯的过程具体阶段是这样(以下基于公钥的密钥交换):

第一阶段
    客户端发出握手请求(client_hello):
    发送信息包括:
        客户端支持的加密算法(如RSA),
        支持的ssl协议的版本(如TLS2.0,如果对方支持版本不同,中断通讯)
        生成一个随机数并发送给服务器(用于生成"会话密钥")
        支持的压缩算法.
    服务器端回复握手请求(server_hello):
        确认加密算法、协议版本、支持压缩算法信息,并生成一个随机数(用于生成"会话密钥").
第二阶段
    服务器端将自己的证书发送给客户端,并请求客户端证书.
    客户端检查证书,检查项目:
        证书是否可靠,证书内容的完整性,证书的名称是否与我访问目标名称一致,证书是否过期,证书是否被吊销.
        检查通过进入下一阶段.
第三阶段
    客户端将自己的证书发送给服务器端,并将上述所有信息用hash算法计算并使用私钥进行数字签名发送给服务器端(用于验证数据的完整性)
    客户端生成名为pre-master-secret的随机数,将其通过服务器端公钥加密并发送至服务器端.
    服务器端检查证书,检查标准与客户端一致.解密数字签名提取hash值来,确定数据完整性.
    客户端和服务器端同时使用三组随机数生成相同的密钥,成为Master-secret.
第四阶段
    双方通过Master-secret作为通信密钥,同时结束握手.

以后则进入加密通信的阶段.
注意:如果是用DH算法进行密钥交换,则过程有所不同.

        以下转自http://blog.csdn.net/dog250/article/details/5717162,解决上述过程某些细节.
        ssl3_send_client_key_exchange是openssl中客户端确定密钥的函数,同时也发送了“一部分”数据给服务器,这一部分数据就是所谓的pre_master,不管是客户端还是服务器都根据对端传过来的pre_master和自己计算出来的另一部分数据来生成最终的对称密钥,生成过程中需要hello消息中的随机数,这样生成的密钥才不会每次都一样。由于ssl协议中dh份额来源于证书,而证书又是静态的,因此十分有必要引入一种随机因素来保证通过静态证书导出的密钥份额协商出来的密钥的随机性。同时这也是pre_master的意义,那就是随机,对于rsa密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥,但是对于dh,包括ecdh算法(不考虑匿名dh和瞬时dh),就只有hello消息中的两个随机数因子了。

        pre master的存在在于ssl协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。
openssl工具
openssl是对ssl/tls协议的实现工具.其主要包括:
    libcryto库(用于加密解密库)
    libssl库(用于安全通信)
    openssl多用于命令行工具
libcryto、libssl库用于开发使用;此处只使用openssl命令行工具.

openssl COMMAND SOMETHING        ///简单格式
    COMMAND:
        标准命令
        信息摘要(dgst子命令)
        加密命令(enc子命令)

openssl对称加密
    加密:
        openssl enc -e -des3 -a -salt -in input_file -out out_file
    解密:
        openssl enc -d -des3 -in input_file -out output_file
单向加密:
     openssl dgst -md5 file

生成用户密码:
     openssl passwd -1 -salt xxx

    # openssl passwd -1 -salt yxq 
    Password: 
    $1$yxq$SqnUaPkubA6Nz5/ITpbh/0
生成随机数:
    openssl rand -base64 numbits
    openssl rand -hex numbits

    ]# openssl passwd -1 -salt $(openssl rand -hex 8) 
    Password: 
    $1$cd07c06e$3NB/ejbKySsQ2XQbWD9Vu0

公钥加密:

    openssl genrsa [-out file] [numbits]
    # (umask 077;openssl genrsa -out /tmp/rsa2 2048)
    ()使命令在子shell中运行,则不会影响父shell.

    提取公钥:
        openssl rsa -in private_key_file

openssl加密总结:
    openssl [Standard|Message Digest|Cipher]COMMAND

            genrsa:生成rsa私钥
                openssl genrsa [-out filename] [numbits]
                            numbits:生成多少位的密钥(默认为512)
            rand:随机数生成器
                openssl rand [-out file] [-base64] [-hex] num
                        -base64:以base64编码输出
                        -hex:以16进制输出
            dgst:消息摘要(单向加密)
                openssl dgst [-md5|sha1...] [file...]
                            -md5:md5加密算法
                            -sha1:sha1加密算法
            enc:对称加密
                openssl enc -ciphername [-e] [-d] [-a/-base64] [-salt] [-in filename] 
                        -e:加密
                        -d:解密
                        -a|-base64:使用base64编码输出
                        -salt:给加密加点盐
                        -in filename:需要加密的文件
            passwd:计算密码hash值
                openssl passwd [-1] [-salt string] [-in file]
                        -1:使用md5加密算法
                        -salt string:给加密添加额外的字符

    熵池:运行中的内核在内存中维护的内存空间

        随机数设备文件:
            /dev/random         ///存放随机数
            /dev/urandom        ///软件生成伪随机数
        熵池中随机数来源:
            硬盘IO
            键盘IO


构建私有CA:
        根据/etc/pki/tls/openssl.cnf配置文件
        (1)生成与配置文件对应的私钥
          # (umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)
        (2)请求自签(只有作为CA生成端才能使用)
          # openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cakey.pem -days 3655
        (3)创建CA相关目录及文件,并对部分文件初始化
          # mkdir -pv /etc/pki/CA/{certs,newcerts,crl}
          # touch /etc/pki/CA/{serial,crlnumber,index.txt}
          # echo 01 > /etc/pki/CA/{serial,crlnumber}

    申请CA证书:
         以httpd为例
         (1)在/etc/httpd目录下创建ssl目录,用于存放证书
          # mkdir /etc/httpd/ssl
         (2)首先生成私钥
          # (umask 077;openssl genrsa -out /etc/httpd/ssl/httpd.key 4096)
         (3)接着生成证书签署请求文件
          # openssl req -new -key /etc/httpd/ssl/httpd.key -out /etc/httpd/ssl/httpd.csr -days 365 
          注意:   
                Organization Name ,此名称要与颁发CA的一致
                Common Name ,此名称需要与所需要申请的网址域名一致
         (4)使用安全方式将请求文件给CA(此处只为测试,直接将文件复制到CA主机)
          # scp /etc/httpd/ssl/httpd.csr user@localhost:/etc/pki/CA
         (5)在CA主机上,签署证书
          # openssl ca -in /etc/pki/CA/httpd.csr -out /etc/pki/CA/certs/httpd.crt
         (6)将证书以安全方式给申请者
          # scp /etc/pki/CA/certs/httpd.crt  user@localhost:/etc/httpd/ssl


    吊销证书:
        (1) 初始化吊销列表(前面已经初始化)
         # echo 01 > /etc/pki/CA/crlnumber
        (2) 申请吊销的主机,将证书的serial,subject信息告知CA(查看命令)
         # openssl x509 -in /etc/httpd/ssl/httpd.crt -noout -serial -subject
        (3) CA查看对应的serial和subject信息与index.txt数据库文件内容进行比对.一致则执行吊销.
         # openssl ca -revoke  /etc/pki/CA/newcerts/SERIAL.pem 
        (4) 更新证书吊销列表(以.crl为后缀即可)
         # openssl  ca  -gencrl  -out  thisca.crl 
        (5) 查看吊销信息
         # openssl crl -in /etc/pki/CA/crl/thisca.crl -noout -text


        总结相关命令:
            openssl req -new -x509 -key /path/to/*.key -out /path/to/*.pem -days 365
                    req : 用于请求
                         -new: 新证书请求
                         -x509:生成自签格式证书,专用于创建私有CA时
                         -key filename: 私钥地址
                         -out filename: 输出地址
                         -days:期限
                    ca : ca管理
                         -gencrl: 生成一个基于index数据库的CRL
                         -out filename: 输出地址
                  x509 : 显示证书和签名
                         -in filename: 证书路径
                         -noout:阻隔输出编码的版本
                         -serial: 显示serial
                         -subject: 显示subject
                   crl : CRL管理
                         -in filename: 吊销文件路径
                         -noout:不输出CRL编码的版本
                         -text:以文本格式输出