openssl指令

base64 编码: openssl enc -base64 -in plain.txt -out base64.txt
enc: 通用加密指令
-base64: 指定加密方式为 base64
-in 文件名: 需要进行 base64 的文件
-out 文件名: base64 后的文件保存到哪里
-e(默认): 表示当前需要执行编码操作

base64 解码: openssl enc -d -base64 -in plain.txt -out base64.txt
-d: 表示当前需要执行解码操作

查看 md5 输出到控制台: openssl dgst -md5 demo.exe
查看 md5 输出到文件中: openssl dgst -md5 -out md5.txt demo.exe
-md5: 指定使用 md5 算法计算消息摘要,通过 help 查看支持的所有算法

对称加密: openssl enc -des-cbc -in demo.png -out encrypt.png -pass pass:12345678
-des-cbc: 指定加密方式和分组模式,使用 help 查看所有
-pass: 指定对称加密使用的 key

生成公钥:
openssl rsa -in pri.pem -pubout pub.pem
生成私钥:
openssl genrsa -out private.pem 1024
加密文件:
openssl rsautl -encrypt -in md5.txt -inkey pub.pem -pubin -out md5.en
解密文件:
openssl rsautl -decrypt -inkey private.pem -in file.rsa -out file

实例

base64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>

#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#pragma comment(lib, "libcrypto.lib")

// 1. 在项目属性的目录中添加 openssl 的 lib 和 include 路径
// 2. 用到了什么东西就加上相应的头文件
// 3. 必须需要链接到 libcrypto.lib 静态库


// 要求传入一个需要加密的串,以及串的长度,参数三是否需要换行,返回编码后的数据
char* Base64Encode(const char* input, int length, bool with_new_line)
{
// 创建一个 base64 对象,对象的特点就是使用 write 写入的
// 数据会被自动编码,使用 read 读取的数据会自动解码
BIO* b64 = BIO_new(BIO_f_base64());

// 默认编码之后存在换行符,通常不需要换行符
if (!with_new_line)
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

// 再次创建了一个内存对象,对象的特点就是使用 write 写入的
// 数据会自动保存到某一个缓冲区。BIO_push 将两个对象进行关
// 联,也就是说传入的数据首先会进行 base64 编码,然后保存到
// 缓冲区。
b64 = BIO_push(b64, BIO_new(BIO_s_mem()));

// 将传入的数据进行编码,BIO_flush 将操作刷新到对象
BIO_write(b64, input, length);
BIO_flush(b64);

// 从 base64 对象中获取到相应的编码后的内容
BUF_MEM* bptr = NULL;
BIO_get_mem_ptr(b64, &bptr);

// 将编码后的数据拷贝到指定的位置
char* b64encode = new char[bptr->max]{};
memcpy(b64encode, bptr->data, bptr->max);

// 清理 BIO 对象,并返回结果
BIO_free_all(b64);
return b64encode;
}

char* Base64Decode(char* input, int length, bool with_new_line)
{
BIO* b64 = BIO_new(BIO_f_base64());

if (!with_new_line)
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

// 编码后的长度和原文大概比例是 4:3,使用编码后的长度
// 进行解码,空间是绝对足够的
char* buffer = (char*)malloc(length);
if (buffer) memset(buffer, 0, length);

// 创建一个内存对象,存入编码后的内容,并关联到 base64 对象
BIO* bmem = BIO_push(b64, BIO_new_mem_buf(input, length));

// 对 base64 read 就是解码数据
BIO_read(bmem, buffer, length);

// 清理并返回原文
BIO_free_all(bmem);
return buffer;
}

int main()
{
auto b64e = Base64Encode("hello15pbo", 10, false);
printf("b64e: %s\n", b64e);

auto b64d = Base64Decode(b64e, strlen(b64e), false);
printf("b64d: %s\n", b64d);

return 0;
}

MD5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
using namespace std;

#include <openssl/md5.h>
#include <openssl/sha.h>
#pragma comment(lib, "libcrypto.lib")

int md5_encrypt(const void* data, size_t len, unsigned char* md5)
{
// 初始化保存 md5 信息的结构体
MD5_CTX ctx = { 0 };
MD5_Init(&ctx);

// 将需要计算的数据传入到对应的结构中
MD5_Update(&ctx, data, len);

// 从结构中获取计算后的结果
MD5_Final(md5, &ctx);

return 0;
}

int sha1_encrypt(const void* data, size_t len, unsigned char* md5)
{
SHA_CTX ctx = { 0 };
SHA1_Init(&ctx);
SHA1_Update(&ctx, data, len);
SHA1_Final(md5, &ctx);
return 0;
}

int sha256_encrypt(const void* data, size_t len, unsigned char* md5)
{
SHA256_CTX ctx = { 0 };
SHA256_Init(&ctx);
SHA256_Update(&ctx, data, len);
SHA256_Final(md5, &ctx);

return 0;
}

void show_hex(const char* n, unsigned char* hex, size_t length)
{
printf(n);
for (int i = 0; i < length; ++i)
printf("%02X", hex[i]);
printf("\n");
}



int main()
{
unsigned char hex[100] = { 0 };

md5_encrypt("hello15pb", 9, hex);
show_hex("md5: ", hex, 16);

sha1_encrypt("hello15pb", 9, hex);
show_hex("sha1: ", hex, 20);

sha256_encrypt("hello15pb", 9, hex);
show_hex("sha256: ", hex, 32);

return 0;
}

AES

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <openssl/evp.h>
#pragma comment(lib, "libcrypto.lib")


// 返回值是加密后的密文长度,传入明文,明文长度和保存密文的缓冲区
int evp_en_cipher(unsigned char* source_string, unsigned char* des_string, int length)
{
// 创建一个通用加解密的对象,设置填充方式
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_set_padding(ctx, 1);

// once_length 是一次加密的长度, out_length 加密后密文的长度
int once_length = 0, out_length = 0;

// 设置加密时使用的算法+分组模式和 key,函数的倒数第二个参数可以
// 用于指定初始化向量,最后一个参数是 1 表示加密,否则解密
unsigned char key[16] = "15pb";
EVP_CipherInit_ex(ctx, EVP_des_ede3_ecb(), NULL, key, nullptr, 1);

// 使用 EVP_CipherUpdate + EVP_CipherFinal 完成整个加密
EVP_CipherUpdate(ctx, des_string, &once_length, source_string, length);
out_length += once_length;
EVP_CipherFinal(ctx, des_string + once_length, &once_length);
out_length += once_length;

// 清理对象并返回长度
EVP_CIPHER_CTX_free(ctx);
return out_length;
}

int evp_de_cipher(unsigned char* source_string, unsigned char* des_string, int length)
{
EVP_CIPHER_CTX * ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_set_padding(ctx, 1);

int once_length = 0, out_length = 0;

// 解密的代码和加密除 EVP_CipherInit_ex 的最后一个参数外基本相同
unsigned char key[16] = "15pb";
EVP_CipherInit_ex(ctx, EVP_des_ede3_ecb(), NULL, key, nullptr, 0);

EVP_CipherUpdate(ctx, des_string, &once_length, source_string, length);
out_length += once_length;
EVP_CipherFinal(ctx, des_string + once_length, &once_length);
out_length += once_length;

// 为加密后的数据添加空字符
des_string[out_length] = 0;

EVP_CIPHER_CTX_free(ctx);
return out_length;
}

int main(int argc, char* argv[])
{
unsigned char planttext[] =
"123456789123456789"
"123456789123456789"
"123456789123456789"
"123456789123456789"
"123456789123456789"
"123456789123456789";
unsigned char temp_string[1000] = { 0 };

int en_length = evp_en_cipher(planttext, temp_string, 108);
int de_length = evp_de_cipher(temp_string, temp_string, en_length);

printf("%s", temp_string);

return 0;
}

RSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <windows.h>
#include <openssl\rsa.h>
#include <openssl\pem.h>
#include <openssl\rand.h>
#include <openssl\applink.c>
#pragma comment(lib, "libcrypto.lib")

#define PUB_KEY_FILE "pubkey.pem" // 公钥路径
#define PRI_KEY_FILE "prikey.pem" // 私钥路径

// 函数方法生成密钥对
void generate_rsa_key()
{
// 生成 rsa 密钥对, 参数一密钥长度,参数二公钥指数 e,参数三四可以不指定
RSA* keypair = RSA_generate_key(1024, RSA_F4, NULL, NULL);

// 从生成的密钥对中读取私钥到内存对象
BIO* pri = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
// 获取密钥长度并且申请空间进行保存
size_t pri_len = BIO_pending(pri);
char* pri_key = (char*)calloc(pri_len + 1, sizeof(char));
BIO_read(pri, pri_key, pri_len);
// 将生成的私钥写入到指定的文件中
FILE* private_file = nullptr;
if (fopen_s(&private_file, PRI_KEY_FILE, "w") == NULL)
{
if (pri_key && private_file)
{
fputs(pri_key, private_file);
fclose(private_file);
}
}

BIO* pub = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPublicKey(pub, keypair);
size_t pub_len = BIO_pending(pub);
char* pub_key = (char*)calloc(pub_len + 1, sizeof(char));
BIO_read(pub, pub_key, pub_len);
FILE* public_file = nullptr;
if (fopen_s(&public_file, PUB_KEY_FILE, "w") == NULL)
{
if (pub_key && public_file)
{
fputs(pub_key, public_file);
fclose(public_file);
}
}

// 释放对应的资源,防止泄露
RSA_free(keypair);
BIO_free_all(pub);
BIO_free_all(pri);

free(pri_key);
free(pub_key);
}

/*加密最大长度为加密长度-41*/
RSA* get_public_key()
{
// 打开公钥文件
FILE* public_file = nullptr;
if (fopen_s(&public_file, PUB_KEY_FILE, "r") == NULL)
{
// 从指定文件中读取公钥
RSA* rsa = PEM_read_RSAPublicKey(public_file, NULL, NULL, NULL);
if(public_file) fclose(public_file);
return rsa;
}
return nullptr;
}

RSA* get_private_key()
{
// 打开私钥文件
FILE* private_file = nullptr;
if (fopen_s(&private_file, PRI_KEY_FILE, "r") == NULL)
{
// 从指定文件中读取公钥
RSA* rsa = PEM_read_RSAPrivateKey(private_file, NULL, NULL, NULL);
if (private_file) fclose(private_file);
return rsa;
}
return nullptr;
}

BYTE* rsa_encrypt(BYTE* data, RSA* rsa)
{
int rsa_len = RSA_size(rsa);
BYTE* encrypt = (BYTE*)malloc(rsa_len);
RSA_public_encrypt(117, data, encrypt, rsa, RSA_PKCS1_PADDING);

return encrypt;
}


// 解密数据,
BYTE* rsa_decrypt(BYTE* data, RSA* rsa)
{
int rsa_len = RSA_size(rsa);
BYTE* decrypt = (BYTE*)malloc(rsa_len);
RSA_private_decrypt(rsa_len, data, decrypt, rsa, RSA_PKCS1_PADDING);

return decrypt;
}

int main()
{
// 生成 rsa 密钥对并读取到 rsa 对象中
generate_rsa_key();
RSA* public_key = get_public_key();
RSA* private_key = get_private_key();

// 构建需要加密的文件
BYTE plaintext[117] = { 0 };
memset(plaintext, 'a', 117);

// 加密和解密
BYTE* encrypt = rsa_encrypt(plaintext, public_key);
BYTE* decrypt = rsa_decrypt(encrypt, private_key);

return 0;
}