Yi's Knowledge Base

3 object(s)
 

HTTPS

HTTPS

HTTP Secure

TLS/SSL中使用了非对称加密,对称加密以及HASH算法

TLS Glossary

For example “AES128-SHA” defines a session that uses:

Process

握手过程的简单描述如下:

  1. 浏览器将自己支持的一套加密规则发送给网站。
  2. 网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
  3. 获得网站证书之后浏览器要做以下工作: a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等) b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码(Pre-master secret),并用证书中提供的公钥加密。 c) 使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密。客户端发送报文,并提示服务器,此后的报文通信会采用Pre-master secret密钥加密。最后将之前生成的所有信息以发送Finished报文发送给网站。
  4. 网站接收浏览器发来的数据之后要做以下的操作: a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。 b) 使用密码加密一段握手消息,发送给浏览器。
  5. 浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。

/**********************************************************************
* HTTP权威指南
* https_client.c --- very simple HTTPS client with no error checking
* usage: https_client servername
**********************************************************************/
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

void main(int argc, char **argv)
{
	SSL *ssl;
	SSL_CTX *ctx;
	SSL_METHOD *client_method;
	X509 *server_cert;
	int sd,err;
	char *str,*hostname,outbuf[4096],inbuf[4096],host_header[512];
	struct hostent *host_entry;
	struct sockaddr_in server_socket_address;
	struct in_addr ip;

	/*========================================*/
	/* (1) initialize SSL library */
	/*========================================*/
	SSLeay_add_ssl_algorithms( );
	client_method = SSLv2_client_method( );
	SSL_load_error_strings( );
	ctx = SSL_CTX_new(client_method);
	printf("(1) SSL context initialized\n\n");

	/*=============================================*/
	/* (2) convert server hostname into IP address */
	/*=============================================*/
	hostname = argv[1];
	host_entry = gethostbyname(hostname);
	bcopy(host_entry->h_addr, &(ip.s_addr), host_entry->h_length);
	printf("(2) '%s' has IP address '%s'\n\n", hostname, inet_ntoa(ip));

	/*=================================================*/
	/* (3) open a TCP connection to port 443 on server */
	/*=================================================*/
	sd = socket (AF_INET, SOCK_STREAM, 0);
	memset(&server_socket_address, '\0', sizeof(server_socket_address));
	server_socket_address.sin_family = AF_INET;
	server_socket_address.sin_port = htons(443);
	memcpy(&(server_socket_address.sin_addr.s_addr),
		   host_entry->h_addr, host_entry->h_length);
	err = connect(sd, (struct sockaddr*) &server_socket_address,
				  sizeof(server_socket_address));
	if (err < 0) { perror("can't connect to server port"); exit(1); }
	printf("(3) TCP connection open to host '%s', port %d\n\n",
		   hostname, server_socket_address.sin_port);

	/*========================================================*/
	/* (4) initiate the SSL handshake over the TCP connection */
	/*========================================================*/
	ssl = SSL_new(ctx); /* create SSL stack endpoint */
	SSL_set_fd(ssl, sd); /* attach SSL stack to socket */
	err = SSL_connect(ssl); /* initiate SSL handshake */
	printf("(4) SSL endpoint created & handshake completed\n\n");

	/*============================================*/
	/* (5) print out the negotiated cipher chosen */
	/*============================================*/
	printf("(5) SSL connected with cipher: %s\n\n", SSL_get_cipher(ssl));

	/*========================================*/
	/* (6) print out the server's certificate */
	/*========================================*/
	server_cert = SSL_get_peer_certificate(ssl);
	printf("(6) server's certificate was received:\n\n");
	str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0);
	printf(" subject: %s\n", str);
	str = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0);
	printf(" issuer: %s\n\n", str);
	/* certificate verification would happen here */
	X509_free(server_cert);

	/*********************************************************/
	/* (7) handshake complete --- send HTTP request over SSL */
	/*********************************************************/
	sprintf(host_header,"Host: %s:443\r\n",hostname);
	strcpy(outbuf,"GET / HTTP/1.0\r\n");
	strcat(outbuf,host_header);
	strcat(outbuf,"Connection: close\r\n");
	strcat(outbuf,"\r\n");
	err = SSL_write(ssl, outbuf, strlen(outbuf));
	shutdown (sd, 1); /* send EOF to server */
	printf("(7) sent HTTP request over encrypted channel:\n\n%s\n",outbuf);

	/**************************************************/
	/* (8) read back HTTP response from the SSL stack */
	/**************************************************/
	err = SSL_read(ssl, inbuf, sizeof(inbuf) - 1);
	inbuf[err] = '\0';
	printf ("(8) got back %d bytes of HTTP response:\n\n%s\n",err,inbuf);

	/************************************************/
	/* (9) all done, so close connection & clean up */
	/************************************************/
	SSL_shutdown(ssl);
	close (sd);
	SSL_free (ssl);
	SSL_CTX_free (ctx);
	printf("(9) all done, cleaned up and closed connection\n\n");
}