0%

SSL 单向与双向认证

关于SSL认证的两种方式:单向和双向

  • 1-way “Standard” SSL Authentication
  • 2-way “Mutual” SSL Authentication

SSL/TLS 流程

CA: 证书授权中心 ( certificate authority),用于签发证书,由于ca.keyca.crt(含有公钥信息)是一对,于是ca.crt可以解密server.crtclient.crt

如果SSL Client想要校验SSL server. 那么SSL server必须要将他的证书server.crt传给client. 然后 clientca.crt 去校验 server.crt 的合法性。如果是一个钓鱼网站,那么CA是不会给他颁发合法server.crt证书的,这样clientca.crt去校验就会失败。这样就可以保证了 client 的所有 https 访问都是安全的。

SSL/TLS 认证

存在两种

  1. 单向认证 – 1-way “Standard” SSL Authentication,指的是只有一个对象校验对端的证书合法性。通常都是client来校验服务器的合法性。client需要一个ca.crtserver需要server.crtserver.key

    The point of this type of authentication is for you (as the client) to verify the authenticity of the web site you are connecting to and form a secure channel of communication.

  2. 双向认证 – 2-way “Mutual” SSL Authentication ,指的是相互校验。server需要server.keyserver.crtca.crtclient需要client.keyclient.crtca.crt

    Contrary to one-way SSL; in case of two-way SSL, both client and server authenticate each other to ensure that both parties involved in the communication are trusted. Both parties share their public certificates to each other and then verification/validation is performed based on that.

SSL/TLS 握手流程

客户与服务器通信时,首先要进行 SSL 握手,SSL 握手主要完成以下任务:

  1. 协商使用的加密套件。加密套件中包括一组加密参数,这些参数指定了加密算法和密钥的长度等信息
  2. 验证对方的身份,此操作是可选的
  3. 确定使用的加密算法
  4. SSL 握手过程采用非对称加密方法传递数据,由此来建立一个安全的 SSL 会话。SSL 握手完成后,通信双方将采用对称加密方法传递实际的应用数据

以下是 SSL 握手的具体流程:

  1. 客户将自己的 SSL 版本号、加密参数、与 SSL 会话有关的数据及其他一些必要信息发送到服务器
  2. 服务器将自己的 SSL 版本号、加密参数、与 SSL 会话有关的数据及其他一些必要信息发送给客户,同时发给客户的还有服务器的证书。如果服务器需要验证客户身份,服务器还会发出要求客户提供安全证书的请求
  3. 客户端验证服务器证书,如果验证失败,就提示不能建立 SSL 连接。如果成功,那么继续下一步骤
  4. 客户端为本次 SSL 会话生成预备主密码(pre-master secret),并将其用服务器公钥加密后发送给服务器
  5. 如果服务器要求验证客户身份,客户端还要对另外一些数据签名后,将其与客户端证书一起发送给服务器
  6. 如果服务器要求验证客户身份,则检查签署客户证书的 CA(Certificate Authority,证书机构)是否可信。如果不在信任列表中,结束本次会话。如果检查通过,服务器用自己的私钥解密收到的预备主密码(pre-master secret),并用它通过某些算法生成本次会话的主密码(master secret)
  7. 客户端与服务器端均使用此主密码(master secret)生成此次会话的会话密钥(对称密钥)。在双方 SSL 握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量要低一个数量级以上,能够显著提高双方会话时的运算速度
  8. 客户端通知服务器此后发送的消息都使用这个会话密钥进行加密,并通知服务器客户端已经完成本次 SSL 握手
  9. 服务器通知客户端此后发送的消息都使用这个会话密钥进行加密,并通知客户端服务器已经完成本次 SSL 握手
  10. 本次握手过程结束,SSL 会话已经建立。在接下来的会话过程中,双方使用同一个会话密钥分别对发送和接收的信息进行加密和解密

证书工作流

1555588843545

  1. 申请认证:服务器需自己生成公钥私钥对pub_svr & pri_svr,同时根据 pub_svr 生成请求文件 csr, 提交给 CA,csr 中含有公钥、组织信息、个人信息(域名)等信息
  2. 审核信息:CA 通过线上、线下等多种手段验证申请者提供信息的真实性
  3. 签发证书:如信息审核通过,CA 会向申请者签发认证文件 - 证书。 包含以下信息:申请者公钥、申请者的组织信息和个人信息、签发机构 CA 的信息、有效时间、证书序列号等信息的明文,同时包含一个签名
  4. 返回证书:client 如果请求验证服务器,服务器需返回证书文件 – SERVER_HELLO
  5. client 验证证书:client 读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,然后,利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法。客户端然后验证证书相关的域名信息、有效时间是否吊销等信息。 客户端会内置信任 CA 的证书信息(包含公钥),如果 CA 不被信任,则找不到对应 CA 的证书,证书也会被判定非法
  6. 秘钥协商:验证通过后,Server 和 Client 将进行秘钥协商。接下来 Server 和 Client 会采用对称秘钥加密
    • pre-master
    • change_cipher_spec
    • encrypted_handshake_message
  7. 数据传输:Server 和 Client 采用对称秘钥加密解密数据

1-way 单向认证

1555589285068

  1. Client requests for some protected data from the server on HTTPS protocol. This initiates SSL/TLS handshake process. – CLIENT_HELLO
  2. Server returns its public certificate to the client along with SERVER_HELLO message.
  3. Client validates/verifies the received certificate. Client verifies the certificate through certification authority (CA) for CA signed certificates.

    The client receives the servers certificate and it is verified against a list of known Certificate Authorities.

  4. SSL/TLS client sends the random byte string that enables both the client and the server to compute the secret key to be used for encrypting subsequent message data. The random byte string itself is encrypted with the server’s public key.
  5. After agreeing on this secret key, client and server communicate further for actual data transfer by encryping/decrypting data using this key.

2-way 双向认证

1555589401105

  1. Client requests a protected resource over HTTPS protocol and the SSL/TSL handshake process begins.
  2. Server returns its public certificate to the client along with SERVER_HELLO.
  3. Client validates/verifies the received certificate. Client verifies the certificate through certification authority (CA) for CA signed certificates.
  4. If Server certificate was validated successfully, client will provide its public certificate to the server.
  5. Server validates/verifies the received certificate. Server verifies the certificate through certification authority (CA) for CA signed certificates.
  6. After completion of handshake process, client and server communicate and transfer data with each other encrypted with the secret keys shared between the two during handshake.

编程 API

证书验证函数SSL_CTX_set_verify

  • SSL_VERIFY_NONE 表示不验证
  • SSL_VERIFY_PEER 用于客户端时要求服务器必须提供证书,用于服务器时服务器会发出证书请求消息要求客户端提供证书,但是客户端也可以不提供
  • SSL_VERIGY_FAIL_IF_NO_PEER_CERT 只适用于服务器且必须提供证书。他必须与 SSL_VERIFY_PEER 一起使用
/* Specify that we need to verify the client as well */
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);

/* We accept only certificates signed only by the CA himself */
SSL_CTX_set_verify_depth(ctx, 1);

设置可信证书默认位置SSL_CTX_load_verify_locations
加载自身证书,用于发送到对端SSL_CTX_use_certificate_file
加载私钥SSL_CTX_use_PrivateKey_file
验证私钥SSL_CTX_check_private_key
加载可信 CAsSSL_load_client_CA_file
设置 CAs 列表,用于发送到客户端SSL_CTX_set_client_CA_list
设置握手时使用的密钥套件SSL_CTX_set_cipher_list

SSLeay_add_ssl_algorithms();

// 我们使用 SSL V3,V2
ctx = SSL_CTX_new(SSLv23_server_method());
if (ctx == NULL) {
    ERR_print_errors_fp(stdout);
    exit(1);
}

// 加载 CA 的证书,加载受信任的 CA 证书
if (!SSL_CTX_load_verify_locations(ctx, "../CA/ca.crt", NULL)) {
    ERR_print_errors_fp(stdout);
    exit(1);
}

/* Load the client's CA file location as well */
// load user certificate,this cert will be send to server for server verify
// 当需要客户端验证的时候,服务器把 CAfile 里面的可信任 CA 证书发往客户端
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file("../CA/ca.crt"));

// 加载自己的证书
if (!SSL_CTX_use_certificate_file(ctx, "./server.crt", SSL_FILETYPE_PEM)) {
    ERR_print_errors_fp(stdout);
    exit(1);
}

// 加载自己的私钥
if (!SSL_CTX_use_PrivateKey_file(ctx, "./server.key", SSL_FILETYPE_PEM)) {
    ERR_print_errors_fp(stdout);
    exit(1);
}

// 判定私钥是否正确
if (!SSL_CTX_check_private_key(ctx)) {
    ERR_print_errors_fp(stdout);
    exit(1);
}

//set cipher ,when handshake client will send the cipher list to server
SSL_CTX_set_cipher_list(g_sslctx,"HIGH:MEDIA:LOW:!DH");

/* We won't handle incomplete read/writes due to renegotiation */
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);

/* Specify that we need to verify the client as well */
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);

/* We accept only certificates signed only by the CA himself */
// 最大的验证用户证书的上级数
SSL_CTX_set_verify_depth(ctx, 1);

Ref

  1. two-way-ssl-c
  2. openssl_2way_auth.sh
  3. 1-Way vs 2-Way SSL authentication
  4. SSL 握手通信详解及 linux 下 c/c++ SSL Socket(另附 SSL 双向认证客户端代码)
  5. SSL/TLS 双向认证(一) – SSL/TLS 工作原理及抓包分析
  6. openssl 有关 SSL 客户端认证的问题
  7. Https 单向认证和双向认证
  8. Implementing Mutual SSL Authentication
  9. 相互身份验证总是成功与 OpenSSL
  10. One-way and two-way SSL authentication – IBM Security Identity Manager
  11. An Overview of One-Way SSL and Two-Way SSL