准备工作双方都生成一个pem格式的证书,发送给对方。

下面代码用来模拟双方加密解密的过程。

先是客户端从服务器的证书取出公钥,加密发送给对方。

/*
param k1 待加密的数据
param in_size 待加密数据的长度
param out 加密后的数据
return 加密后数据的长度
*/
int incode(unsigned char *k1,int in_size,unsigned char* out )
{
    //从证书中取出公钥,并放在evp_pkey中
    auto b = BIO_new_file("server.crt", "r");
    auto x = PEM_read_bio_X509(b, NULL, NULL, NULL);
    auto pkey = X509_get_pubkey(x);
    auto rsa = EVP_PKEY_get1_RSA(pkey);
    //创建加密上下文
    EVP_PKEY_CTX*ctx = nullptr;
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
        //加密初始化
    EVP_PKEY_encrypt_init(ctx);
    
    int key_size = RSA_size(rsa);
    int block_size = key_size - RSA_PKCS1_PADDING_SIZE;
    cout << "key_size=" << key_size << endl;
    cout << "block_size=" << block_size << endl;
    
    int out_size = 0;
    for (int i = 0; i < in_size; i += block_size)
    {
        size_t out_len = key_size;
        size_t en_size = block_size;
        if (in_size - i < block_size)
            en_size = in_size - i;
        int ret = EVP_PKEY_encrypt(ctx, out + out_size, &out_len, k1 + i, en_size);
        if (ret < 0)
        {
            cout << "encrypto error!" << endl;
            break;
        }
        out_size += out_len;

    }
    cout << "out_size=" << out_size << endl;
    cout << "cipher=" << out << endl;
    EVP_PKEY_CTX_free(ctx);
    return out_size;
}    

服务端收到密文后,用自己的私钥解密

/*
param cipher 收到的密文
param cipher_size 密文的长度
param out 解密后的数据
return 解密后数据的长度
*/
int decode(unsigned char*cipher, int cipher_size, unsigned char*out)
{
    
    FILE*fp = fopen("./server.key", "r");
    if (!fp)
    {
        cout << "fopen error!" << endl;
        fclose(fp);
        return -1;
    }
    
    RSA *r = NULL;
    //私钥存在R中
    PEM_read_RSAPrivateKey(fp, &r, NULL, NULL);
    if (!r)
    {
        fclose(fp);
        cout << "rsa error" << endl;
    }
    fclose(fp);
    auto pkey = EVP_PKEY_new();
    //将R中的私钥放在evp_pkey中
    EVP_PKEY_set1_RSA(pkey, r);
    //创建上下文
    EVP_PKEY_CTX *ctx = nullptr;
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
    EVP_PKEY_free(pkey);
    int key_size = RSA_size(r);
    cout << "key_size:" << key_size << endl;
    RSA_free(r);
    int in_len = strlen((char*)cipher);
    //解密
    int out_size = 0;
    EVP_PKEY_decrypt_init(ctx);
    int block_size = key_size;
    for (int i = 0; i < in_len; i += block_size)
    {
        size_t outlen = key_size;//设置输出空间大小;
        if (EVP_PKEY_decrypt(ctx, out + out_size, &outlen, cipher + i, block_size) <= 0)
        {
            
            cout << "decrpt error" << endl;
            return -1;
        }
        out_size += outlen;

    }
    EVP_PKEY_CTX_free(ctx);
    
    return out_size;
}

测试

int main()
{
    
    unsigned char k1[] = "this is a sunny day";
    unsigned char cipher[1024] = { 0 };
    int in_size = strlen((char*)k1);
    int cipher_size = incode(k1, in_size, cipher);
    unsigned char mingwen[120] = { 0 };
    int size = decode(cipher, cipher_size, mingwen);
    cout << "size=" << size << endl;
    cout << "mingwen:" << mingwen << endl;
     return 0;
}