openssl handshake

通过openssl命令来建立一个SSL测试环境

环境背景:Ubuntu 16.04.1 & OpenSSL-1.0.2g

1. 在openssl安装目录/usr/lib/ssl/misc目录下,运行脚本 ./CA.sh –newca

随后会生成一个demonCA的目录,里面包含了ca证书及其私钥。

2. 生成客户端和服务端证书申请

$ openssl req -newkey rsa:1024 -out req1.pem -keyout sslclientkey.pem
$ openssl req -newkey rsa:1024 -out req2.pem -keyout sslserverkey.pem

3. 签发客户端和服务端证书

$ openssl ca -in req1.pem -out sslclientcert.pem
$ openssl ca -in req2.pem -out sslservercert.pem

4. 运行ssl 服务端

$ openssl s_server -cert sslservercert.pem -key sslserverkey.pem -CAfile demoCA/cacert.pem
Enter pass phrase for sslserverkey.pem:
Using default temp DH parameters
ACCEPT
-----BEGIN SSL SESSION PARAMETERS-----
MFUCAQECAgMDBALAMAQABDBZ6RLUgd5qBfj3oeCfRzD/1sdK9aQcpbmvFVRLBJ66
roEscQm1tHBUOrYWX9UYjNehBgIEX/U+rqIEAgIBLKQGBAQBAAAA
-----END SSL SESSION PARAMETERS-----
Shared ciphers:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA
Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Supported Elliptic Curve Point Formats: uncompressed:ansiX962_compressed_prime:ansiX962_compressed_char2
Supported Elliptic Curves: P-256:P-521:brainpoolP512r1:brainpoolP384r1:P-384:brainpoolP256r1:secp256k1:B-571:K-571:K-409:B-409:K-283:B-283
Shared Elliptic curves: P-256:P-521:brainpoolP512r1:brainpoolP384r1:P-384:brainpoolP256r1:secp256k1:B-571:K-571:K-409:B-409:K-283:B-283
CIPHER is ECDHE-RSA-AES256-GCM-SHA384
Secure Renegotiation IS supported

5. 运行客户端

$ openssl s_client -CAfile demoCA/cacert.pem 
CONNECTED(00000003)
depth=1 C = CN, ST = JiangSu, O = Tech, OU = Software Development, CN = wq, emailAddress = wq897387@126.com
verify return:1
depth=0 C = CN, ST = JiangSu, O = Tech, OU = Software Development, CN = wq, emailAddress = wq897387@126.com
verify return:1
---
Certificate chain
 0 s:/C=CN/ST=JiangSu/O=Tech/OU=Software Development/CN=wq/emailAddress=wq897387@126.com
   i:/C=CN/ST=JiangSu/O=Tech/OU=Software Development/CN=wq/emailAddress=wq897387@126.com
 1 s:/C=CN/ST=JiangSu/O=Tech/OU=Software Development/CN=wq/emailAddress=wq897387@126.com
   i:/C=CN/ST=JiangSu/O=Tech/OU=Software Development/CN=wq/emailAddress=wq897387@126.com
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDdjCCAl6gAwIBAgIJAMW4y04XPrUDMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV
BAYTAkNOMRAwDgYDVQQIDAdKaWFuZ1N1MQ0wCwYDVQQKDARUZWNoMR0wGwYDVQQL
DBRTb2Z0d2FyZSBEZXZlbG9wbWVudDELMAkGA1UEAwwCd3ExIjAgBgkqhkiG9w0B
CQEWE3dxODk3Mzg3NjNAeWVhaC5uZXQwHhcNMjEwMTA2MDQzMDEyWhcNMjIwMTA2
MDQzMDEyWjB+MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdTdTENMAsGA1UE
CgwEVGVjaDEdMBsGA1UECwwUU29mdHdhcmUgRGV2ZWxvcG1lbnQxCzAJBgNVBAMM
AndxMSIwIAYJKoZIhvcNAQkBFhN3cTg5NzM4NzYzQHllYWgubmV0MIGfMA0GCSqG
SIb3DQEBAQUAA4GNADCBiQKBgQDAO8Y56uwwL1FQtNGvfLJhaAp5898SWaenYOAl
w906uY6gLEZQ2+PbndPSOwHxrTH4tOYdAdan7dXHA0V5a2w20qn9zn5RbyXpX/Cp
eVaRmI8rgq3kafPTeQMoCXfcaKjydy+oywlDPkbS7q1h5iOTVHsEJLKIg46oaJLl
gLFOswIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU2QySKT5mNzgFVk2cOxk6
JdDBIIgwHwYDVR0jBBgwFoAUozwxNsifkC4u51ET6KQpuht1z8AwDQYJKoZIhvcN
AQELBQADggEBAK70RFqguCwO7ebmiI2pFWvrbilm2LHBsFPWXedOKWJ1l84OVGOO
FGrAmG69Kd1BFpMk/16a9EHwecbS+5CcfqxdtKWvWXpvpq1oVlqcxcJxXu7bqR5v
v9MONZj0LFfo30JUXMjJ8Nq0NiAHMi8PEXhGXgYtWBWKHbPpS+k/bs+fW1V6zUl6
/xFbgw8/c6UsPdDpQtMrmwZqmbQULqObEBB0tU7ggisdYfIFZ3dfLvw2sB+oDmGt
pzdDtjzPCSqOkT4S1/twgu8sYAx7EXKM0UkrATDp6Is1nuQNzcV8TmC53hMapP52
1fd0JOu6IXBbIFtXZ1x7vjkit1g+u2cTT3g=
-----END CERTIFICATE-----
subject=/C=CN/ST=JiangSu/O=Tech/OU=Software Development/CN=wq/emailAddress=wq897387@126.com
issuer=/C=CN/ST=JiangSu/O=Tech/OU=Software Development/CN=wq/emailAddress=wq897387@126.com
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 2403 bytes and written 391 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 131EC22EF3270199458720A32F7C626FD9C177EDEBABD4D2CBFC38A69A0A536A
    Session-ID-ctx: 
    Master-Key: 59E912D481DE6A05F8F7A1E09F4730FFD6C74AF5A41CA5B9AF15544B049EBAAE812C7109B5B470543AB6165FD5188CD7
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 49 f5 d2 ed 95 0b 9b c7-a9 1e 5d ab bc 54 2c 4e   I.........]..T,N
    0010 - 13 68 d9 60 92 57 f8 0d-cd f6 75 f7 67 a3 21 27   .h.`.W....u.g.!'
    0020 - cb 5b ed c1 db 11 17 dd-99 fb 57 b3 ff 83 64 f7   .[........W...d.
    0030 - 18 31 89 9a 99 5c 6c f6-1e 87 2e 03 ec b9 50 cb   .1...\l.......P.
    0040 - fe 1e 7a fb 95 86 ab 8c-f4 c6 a2 84 77 70 d4 76   ..z.........wp.v
    0050 - ec f0 f8 48 a3 c5 29 7c-d6 4b 7d 67 8e a8 01 46   ...H..)|.K}g...F
    0060 - 17 01 fd f4 b3 b6 11 28-05 3e b8 dd aa 25 a7 f8   .......(.>...%..
    0070 - 47 05 96 c1 1f 18 e7 8b-a9 81 ca dd e2 2e f4 8d   G...............
    0080 - 25 9e e5 be a9 ed 61 2b-0a d4 61 50 92 ff fe b9   %.....a+..aP....
    0090 - 1d bb 42 09 7f ce be 65-f1 73 16 72 a3 07 4a cf   ..B....e.s.r..J.

    Start Time: 1609907886
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

 

通过openssl编程接口建立一个SSL测试环境

Server端

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <linux/in.h>
#include <errno.h>
#include <openssl/ssl.h>
int err;

#define CERTF "certs/sslservercert.pem"
#define KEYF "certs/sslserverkey.pem"
#define CAFILE "certs/cacert.pem"

int verify_callback_server(int ok, X509_STORE_CTX *ctx)
{
    printf("verify_callback_server.\n");
    return ok;
}

int SSL_CTX_use_PrivateKey_file_pass(SSL_CTX *ctx, char *filename, char *pass)
{
    EVP_PKEY *pkey = NULL;
    BIO *key = NULL;
    key = BIO_new(BIO_s_file());

    BIO_read_filename(key, filename);
    pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, pass);

    if (pkey==NULL)
    {
        printf("PEM_read_bio_PrivateKey failed");
        return -1;
    }

    if (SSL_CTX_use_PrivateKey(ctx, pkey)<=0)
    {
        printf("SSL_CTX_use_PrivateKey err.\n");
        return -1;
    }

    BIO_free(key);
    return 1;
}

int main()
{
    int ret;

    SSL_load_error_strings();
    SSLeay_add_ssl_algorithms();

    const SSL_METHOD *meth = SSLv3_server_method();
    SSL_CTX *ctx = SSL_CTX_new(meth);
    if (!ctx)
    {
        printf("SSL_CTX_new failed. ctx=%d\n", ctx);
        return -1;
    }

    if ((!SSL_CTX_load_verify_locations(ctx, CAFILE, NULL))||(!SSL_CTX_set_default_verify_paths(ctx)))
    {
        printf("error.\n");
        return -1;
    }

    if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM)<=0)
    {
     
   printf("SSL_CTX_use_certificate_file failed.\n");
        return -1;
    }

    if (SSL_CTX_use_PrivateKey_file_pass(ctx,KEYF,NULL)<=0)
    {
  
  printf("SSL_CTX_use_PrivateKey_file_pass failed.\n");
        return -1;
    }

    if (!SSL_CTX_check_private_key(ctx))
    {
        printf("SSL_CTX_check_private_key failed.\n");
        return -1;
    }

    int s_server_verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_CLIENT_ONCE;
    SSL_CTX_set_verify(ctx, s_server_verify, verify_callback_server);
    SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAFILE));

    int s_handle = socket(AF_INET, SOCK_STREAM, 6);
    if (s_handle<0)
    {
        printf("create socket failed.\n");
        return -1;
    }

    struct sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr("192.168.44.99");
    service.sin_port = htons(1111);

    if (bind(s_handle, (const struct sockaddr *)&service, sizeof(service))==-1)
    {
        printf("bind failed.\n");
        close(s_handle);
        return -1;
    }

    if (listen(s_handle, 1)==-1)
    {
        printf("listen failed.\n");
        return -1;
    }

    while(1)
    {
        int session_socket = accept(s_handle, NULL, NULL);
        if(session_socket < 0)
        {
            printf("accept failed.\n");
            return -1;
        }
        SSL *ssl = SSL_new(ctx);
        err = SSL_set_fd(ssl, session_socket);
        if (err < 0)
        {
            printf("SSL_set_fd failed.\n");
            return -1;
        }

        err = SSL_accept(ssl);
        if (err < 0)
        {
            printf("SSL_accept failed. errstr=%s\n", SSL_state_string_long(ssl));
            return -1;
        }

        printf("SSL_connection using %s\n", SSL_get_cipher(ssl));

        X509 *client_cert = SSL_get_peer_certificate(ssl);
        if (client_cert != NULL)
        {
            printf("client cerificate:\n");
            char *str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0);
            if (str&&(*str))
                printf("\tsubject:%s\n", str);
            OPENSSL_free(str);

            str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0);
            if(str&&(*str))
                printf("\t issuer:%s\n", str);
            OPENSSL_free(str);

            X509_free(client_cert);
        }else
            printf("Client does not have certificate.\n");
        const char *cipher_name = SSL_get_cipher_name(ssl);
        if (cipher_name && *cipher_name)
        {
            printf("SSL_get_cipher_name %s.\n", cipher_name);
            return -1;
        }

        char buf[1024];
        memset(buf, 0, 1024);
        err = SSL_read(ssl, buf, sizeof(buf)-1);
        if (err<0)
        {
            printf("SSL_read failed.\n");
            close(ssl);
            return err;
        }
        printf("get: %s\n", buf);

        SSL_free(ssl);
        close(s_handle);
    }

    SSL_CTX_free(ctx);
    return 0;
}

 

Client端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <string.h>

#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define MAX_T 1000
#define CLIENTCERT "certs/sslclientcert.pem"
#define CLIENTKEY "certs/sslclientkey.pem"
#define CAFILE "certs/cacert.pem"
int verify_callback(int ok, X509_STORE_CTX *ctx)
{
    printf("verify_callback.\n");
    return ok;
}

int SSL_CTX_use_PrivateKey_file_pass(SSL_CTX *ctx, char *filename, char *pass)
{
    EVP_PKEY *pkey = NULL;
    BIO *key = NULL;

    key = BIO_new(BIO_s_file());
    BIO_read_filename(key, filename);
    pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, pass);
    if (pkey==NULL)
    {
        printf("PEM_read_bio_PrivateKey failed");
        return -1;
    }

    if (SSL_CTX_use_PrivateKey(ctx, pkey)<=0)
    {
        printf("SSL_CTX_use_PrivateKey err.\n");
        return -1;
    }

    BIO_free(key);
    return 1;
}

int main()
{
    int ret;
    SSL_load_error_strings();
    SSLeay_add_ssl_algorithms();
 
    const SSL_METHOD *meth = SSLv3_client_method();
    SSL_CTX *ctx = SSL_CTX_new(meth);
    if (!ctx)
    {
        printf("SSL_CTX_new failed.\n");
        return -1;
    }

    if (SSL_CTX_use_certificate_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM)<=0)
    {
        printf("SSL_CTX_use_certificate failed.\n");
        return -1;
    }

    if (SSL_CTX_use_PrivateKey_file_pass(ctx, CLIENTKEY, NULL)<=0)
    {
      printf("SSL_CTX_use_PrivateKey_file_pass failed.\n");
        return -1;
    }

    int s_handle = socket(AF_INET, SOCK_STREAM, 0);
    if (s_handle <= 0)
    {
        printf("create socket handle failed.\n");
        return -1;
    }

    struct sockaddr_in dest_sin;
    dest_sin.sin_family = AF_INET;
    dest_sin.sin_addr.s_addr = inet_addr("192.168.44.99");
    dest_sin.sin_port = htons(1111); 
    ret = connect(s_handle, (struct sockaddr *)&dest_sin, sizeof(dest_sin));
    if (ret < 0)
    {
        printf("connect failed.\n");
        return -1;
    } 

    SSL *ssl = SSL_new(ctx);
    if (ssl==NULL)
    {
        printf("SSL_new failed.\n");
        return -1;
    }

    SSL_set_fd(ssl, s_handle);
    ret = SSL_connect(ssl);
    if (ret<0)
    {
        printf("SSL_connect failed.\n");
        return -1;
    }
    printf("SSL_ connection using %s\n", SSL_get_cipher(ssl));

    X509 * server_cert = SSL_get_peer_certificate(ssl);
    printf("Server certificate:");
    char *str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0);
    printf("\t subject: %s\n", str);
    OPENSSL_free(str);

    str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0);
    printf("\tissuer:%s\n",str);
    OPENSSL_free(str);
    X509_free(server_cert);

    ret = SSL_write(ssl, "Hello World!",strlen("Hello World!"));
    if (ret<0)
    {
        printf("SSL_Write failed.\n");
        return ret;
    }

    SSL_CTX_free(ctx);
    return 0;
}

Makefile

all: ssl_server ssl_client

ssl_server:
    gcc -g ssl_server.c libssl.a libcrypto.a -o ssl_server -ldl

ssl_client:
    gcc -g ssl_client.c libssl.a libcrypto.a -o ssl_client -ldl

clean:
    rm ssl_server ssl_client

在当前目录创建certs文件夹,塞入如下证书

cacert.pem  sslclientcert.pem  sslclientkey.pem  sslservercert.pem  sslserverkey.pem 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值