准备工作双方都生成一个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; }