openssl使用

一.生成自己的CA根证书
1.生成 CA 根证书私钥
openssl genrsa -des3 -out root.key 1024

genrsa 表示采用RSA算法生成根证书私钥
-des3 表示使用3DES给根证书私钥加密
1024 表示根证书私钥的长度,建议使用2048,越长越安全

这个时候会让你输入两次根证书的加密密码,就是加密证书的3des密码


2.生成 CA 的自签证书
openssl req -new -x509 -key root.key -out root.crt -days 365

这个手输如一堆东西,注意Common Name输入服务器域名或服务器IP.

 


二.生成服务器证书
1.生成服务器证书私钥
openssl genrsa -out server.key 1024


2.生成服务器端签名请求文件
openssl req -new -key server.key -out server.csr

同样会输入一堆东西,记得跟根证书一样,如果不一样,要去
/etc/pki/tls/openssl.cnf
将对应的项目由 match 设置成 optional


3.要在/etc/pki/CA/ 文件夹下建立一个空文件 index.txt
touch /etc/pki/CA/index.txt


4.要在/etc/pki/CA/ 文件夹下建立一个文件 serial,并写入01
echo "01" > /etc/pki/CA/serial


5.利用 CA 进行签名证书
openssl ca -in server.csr -out server.crt -keyfile root.key -cert root.crt -days 365


附:
得到 pfx 格式的私钥,密钥算法为 pkcs12
openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt

从pfx文件中分离出 cer 格式的公钥
openssl x509 -inform pem -in server.crt -outform der -out server_public.cer

 

客户端证书类似操作

 

 

 服务端程序

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>


#include "openssl/rsa.h"      
#include "openssl/crypto.h"
#include "openssl/x509.h"
#include "openssl/pem.h"
#include "openssl/ssl.h"
#include "openssl/err.h"

/*所有需要的参数信息都在此处以#define的形式提供*/
#define CERTF   "server.crt" /*服务端的证书(需经CA签名)*/
#define KEYF   "server.key"  /*服务端的私钥(建议加密存储)*/
#define CACERT "root.crt" /*CA 的证书*/
#define PORT   1111   /*准备绑定的端口*/

#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }

int main ()
{
  int err;
  int listen_sd;
  int sd;
  struct sockaddr_in sa_serv;
  struct sockaddr_in sa_cli;
  socklen_t client_len;
  SSL_CTX* ctx;
  SSL*     ssl;
  X509*    client_cert;
  char*    str;
  char     buf [4096];
  const SSL_METHOD *meth;

/*
  WSADATA wsaData;

  if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0){
    printf("WSAStartup()fail:%d/n",GetLastError());
    return -1;
  }
*/

  SSL_load_error_strings();            /*为打印调试信息作准备*/
  OpenSSL_add_ssl_algorithms();        /*初始化*/
  meth = TLSv1_server_method();  /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/

  ctx = SSL_CTX_new (meth);
  CHK_NULL(ctx);

  SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,NULL);   /*验证与否,服务器不验证客户端*/
  //SSL_CTX_load_verify_locations(ctx,CACERT,NULL); /*若验证,则放置CA证书*/

  if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(3);
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(4);
  }

  if (!SSL_CTX_check_private_key(ctx)) {
    printf("Private key does not match the certificate public key\n");
    exit(5);
  }

  SSL_CTX_set_cipher_list(ctx,"RC4-MD5"); 

  /*开始正常的TCP socket过程.................................*/
  printf("Begin TCP socket...\n");

  listen_sd = socket (AF_INET, SOCK_STREAM, 0);  
  CHK_ERR(listen_sd, "socket");

  memset (&sa_serv, 0, sizeof(sa_serv));
  sa_serv.sin_family      = AF_INET;
  sa_serv.sin_addr.s_addr = INADDR_ANY;
  sa_serv.sin_port        = htons (PORT);         

  err = bind(listen_sd, (struct sockaddr*) &sa_serv,

  sizeof (sa_serv));

  CHK_ERR(err, "bind");

  /*接受TCP链接*/
  err = listen (listen_sd, 5);                   
  CHK_ERR(err, "listen");

  client_len = sizeof(sa_cli);
  sd = accept (listen_sd, (sockaddr*) &sa_cli, &client_len);
  CHK_ERR(sd, "accept");
  close (listen_sd);

  printf ("Connection from %lx, port %x\n",
      sa_cli.sin_addr.s_addr, sa_cli.sin_port);

  /*TCP连接已建立,进行服务端的SSL过程. */
  printf("Begin server side SSL\n");

  ssl = SSL_new (ctx);                          
  CHK_NULL(ssl);
  SSL_set_fd (ssl, sd);
  err = SSL_accept (ssl);
  printf("SSL_accept finished\n");
  CHK_SSL(err);

  /*打印所有加密算法的信息(可选)*/
  printf ("SSL connection using %s\n", SSL_get_cipher (ssl));

  /*得到服务端的证书并打印些信息(可选) */
  client_cert = SSL_get_peer_certificate (ssl);
  if (client_cert != NULL) {
    printf ("Client certificate:\n");

    str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("/t subject: %s\n", str);
    free (str);

    str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("/t issuer: %s\n", str);
    free (str);

    X509_free (client_cert);/*如不再需要,需将证书释放 */
  }
  else
    printf ("Client does not have certificate.\n");

  /* 数据交换开始,用SSL_write,SSL_read代替write,read */
  err = SSL_read (ssl, buf, sizeof(buf) - 1);                  
  CHK_SSL(err);
  buf[err] = 0;
  printf ("Got %d chars:'%s'\n", err, buf);

  err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); 
  CHK_SSL(err);

  /* 收尾工作*/
  shutdown (sd,2);
  SSL_free (ssl);
  SSL_CTX_free (ctx);

  return 0;
}

客户端代码

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include "openssl/rsa.h"      
#include "openssl/crypto.h"
#include "openssl/x509.h"
#include "openssl/pem.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "openssl/rand.h"

/*所有需要的参数信息都在此处以#define的形式提供*/
#define CERTF  "client.crt"  /*客户端的证书(需经CA签名)*/
#define KEYF  "client.key"   /*客户端的私钥(建议加密存储)*/
#define CACERT "root.crt"      /*CA 的证书*/
#define PORT   1111          /*服务端的端口*/
#define SERVER_ADDR "10.18.12.171"    //"127.0.0.1"  /*服务段的IP地址*/

#define CHK_NULL(x) if ((x)==NULL) exit (-1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(-2); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(-3); }

int main ()
{
  int            err;
  int            sd;
  struct sockaddr_in sa;
  SSL_CTX*        ctx;
  SSL*            ssl;
  X509*            server_cert;
  char*            str;
  char            buf [4096];
  const SSL_METHOD*    meth;
  int            seed_int[100]; /*存放随机序列*/

/*
  WSADATA        wsaData;

  if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
  {
    printf("WSAStartup()fail:%d\n",GetLastError());
    return -1;
  } 
*/
  
  /*初始化*/
  OpenSSL_add_ssl_algorithms(); 
  /*为打印调试信息作准备*/
  SSL_load_error_strings();     

  /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
  meth = TLSv1_client_method();
  /*申请SSL会话环境*/
  ctx = SSL_CTX_new (meth);                       
  CHK_NULL(ctx);
  
  /*验证与否,是否要验证对方,客户端要验证服务器*/
  SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);   
  /*若验证对方,则放置CA证书*/
  SSL_CTX_load_verify_locations(ctx,CACERT,NULL); 

/* 服务器不验证自己
  //加载自己的证书
  if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) 
  {
    ERR_print_errors_fp(stderr);
    exit(-2);
  }
  
  //加载自己的私钥,以用于签名
  if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) 
  {
    ERR_print_errors_fp(stderr);
    exit(-3);
  }
  //调用了以上两个函数后,检验一下自己的证书与私钥是否配对
  if (!SSL_CTX_check_private_key(ctx)) 
  {
    printf("Private key does not match the certificate public key\n");
    exit(-4);
  } 
*/

  /*构建随机数生成机制,WIN32平台必需*/
/*
  srand( (unsigned)time( NULL ) );
  for( int i = 0;   i < 100;i++ )
        seed_int = rand();
  RAND_seed(seed_int, sizeof(seed_int));
*/

  /*以下是正常的TCP socket建立过程 .............................. */
  printf("Begin tcp socket...\n");

  sd = socket (AF_INET, SOCK_STREAM, 0);       
  CHK_ERR(sd, "socket");

  memset (&sa, 0, sizeof(sa));
  sa.sin_family      = AF_INET;
  sa.sin_addr.s_addr = inet_addr (SERVER_ADDR);   /* Server IP */
  sa.sin_port        = htons     (PORT);          /* Server Port number */

  err = connect(sd, (struct sockaddr*) &sa, sizeof(sa)); 
  CHK_ERR(err, "connect");

  /* TCP 链接已建立.开始 SSL 握手过程.......................... */
  printf("Begin SSL negotiation \n");

  /*申请一个SSL套接字*/
  ssl = SSL_new (ctx);                        
  CHK_NULL(ssl);

  /*绑定读写套接字*/
  SSL_set_fd (ssl, sd);
  err = SSL_connect (ssl);
  CHK_SSL(err);

  /*打印所有加密算法的信息(可选)*/
  printf ("SSL connection using %s\n", SSL_get_cipher (ssl));

  /*得到服务端的证书并打印些信息(可选) */
  server_cert = SSL_get_peer_certificate (ssl);      
  CHK_NULL(server_cert);
  printf ("Server certificate:\n");

  str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
  CHK_NULL(str);
  printf ("/t subject: %s\n", str);
  free (str);

  str = X509_NAME_oneline (X509_get_issuer_name  (server_cert),0,0);
  CHK_NULL(str);
  printf ("/t issuer: %s\n", str);
  free (str);

  X509_free (server_cert);  /*如不再需要,需将证书释放 */

  /* 数据交换开始,用SSL_write,SSL_read代替write,read */
  printf("Begin SSL data exchange\n");

  err = SSL_write (ssl, "Hello World!", strlen("Hello World!")); 
  CHK_SSL(err);

  err = SSL_read (ssl, buf, sizeof(buf) - 1); 
  CHK_SSL(err);

  buf[err] = 0;
  printf ("Got %d chars:'%s'\n", err, buf);
  SSL_shutdown (ssl);  /* send SSL/TLS close_notify */

  /* 收尾工作 */
  shutdown (sd,2);
  SSL_free (ssl);
  SSL_CTX_free (ctx);

  return 0;
}

一些测试

#include <openssl/evp.h>  
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <string.h>
#include <iostream>

using namespace std;

char * base64Encode(const char *buffer, int length, bool newLine);
char * base64Decode(char *input, int length, bool newLine);

int main(int argc, char* argv[])
{
    bool newLine = false;
    const char * input = "Hello World!";

    char * encode = base64Encode(input, strlen(input), newLine);
    char * decode = base64Decode(encode, strlen(encode), newLine);

    cout << "Base64 Encoded : " << encode << endl;
    cout << "Base64 Decoded : " << decode << endl;

    cin.get();
}

// base64 编码
char * base64Encode(const char *buffer, int length, bool newLine)
{
    BIO *bmem = NULL;
    BIO *b64 = NULL;
    BUF_MEM *bptr;

    b64 = BIO_new(BIO_f_base64());
    if (!newLine) {
        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    }
    bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, buffer, length);
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);
    BIO_set_close(b64, BIO_NOCLOSE);

    char *buff = (char *)malloc(bptr->length + 1);
    memcpy(buff, bptr->data, bptr->length);
    buff[bptr->length] = 0;
    BIO_free_all(b64);

    return buff;
}

// base64 解码
char * base64Decode(char *input, int length, bool newLine)
{
    BIO *b64 = NULL;
    BIO *bmem = NULL;
    char *buffer = (char *)malloc(length);
    memset(buffer, 0, length);
    b64 = BIO_new(BIO_f_base64());
    if (!newLine) {
        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    }
    bmem = BIO_new_mem_buf(input, length);
    bmem = BIO_push(b64, bmem);
    BIO_read(bmem, buffer, length);
    BIO_free_all(bmem);

    return buffer;
}
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <iomanip>
#include <stdlib.h>
#include <openssl/md5.h>

#include <string.h>
using namespace std;

string MD5_Digest(const string cleartext)
{
    string strDigest;
    unsigned char tmp[16] = {0};
 
#if 0
    MD5((const unsigned char*)cleartext.c_str(), cleartext.length(), tmp);
#else
    MD5_CTX c;
    MD5_Init(&c);
    MD5_Update(&c, cleartext.c_str(), cleartext.length());
    MD5_Final(tmp, &c);
#endif
 
    char* tmp1 = new char[32 + 1];
    memset(tmp1, 0, 32 + 1);
 
    for(int i = 0; i < 16; i++) 
        sprintf(&(tmp1[i*2]), "%02x", tmp[i]);
        //cout<<hex<<setw(2)<<setfill('0')<<(int)tmp[i]; 
 
    strDigest = (char*)tmp1;
 
    delete [] tmp1;
 
    return strDigest;
}

int main()
{
    string str = MD5_Digest("hello world");
    cout<<str<<endl;
}
#include <stdio.h>
#include <string.h>
#include <openssl/rc4.h>

void dumprawmsg(char *p, int len)
{
    int i = 0;
    for (i = 0; i < len; i++)
    {
        if (i % 16 == 0) {
            printf("\n");
        }
        unsigned char c = p[i];
        printf("%.2X ", c);
    }
    printf("\n\n");
}

static unsigned char g_rc4key[16] =
{
      0x2c, 0xb6, 0xa1, 0xe7, 0xe1, 0x0c, 0x50, 0x02,
        0xa5, 0xde, 0xae, 0x7f, 0xe6, 0x05, 0xbd, 0x90,
};

int main()
{
    unsigned char buffer[10];
    unsigned char buffer1[10];
    RC4_KEY m_rc4SendKey, decryKey;
    unsigned char str[10] = "123456789";
    int len = 10;

    memset(buffer, 0, 10);
    memset(buffer1, 0, 10);
    RC4_set_key(&m_rc4SendKey, sizeof(g_rc4key), g_rc4key);
    RC4_set_key(&decryKey, sizeof(g_rc4key), g_rc4key);

    printf("org: %s\n", str);

    RC4(&m_rc4SendKey, len, str, buffer);
    dumprawmsg((char*)buffer, len);

    RC4(&decryKey, len, buffer, buffer1);
    printf("no_cry: %s\n", buffer1);

    return 0;
}
#include <sstream>
#include <string>
#include <iomanip>
#include <iostream>
using namespace std;

#include <openssl/sha.h>

string sha256(const string str)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
/*
    // SHA1
    SHA_CTX sha;
    SHA_Init(&sha);
    SHA_Update(&sha, str.c_str(), str.size());
    SHA_Final(hash, &sha);
    stringstream ss;
    for(int i = 0; i < 20; i++)
*/
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    stringstream ss;
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)

    {
        ss << hex << setw(2) << setfill('0') << (int)hash[i];
    }
    return ss.str();
}

int main()
{

    cout << sha256("test") << endl;
    cout << sha256("test2") << endl;

    return 0;

}

 

posted on 2021-12-26 17:11  litandy  阅读(188)  评论(0编辑  收藏  举报

导航