在编写各种客户端的过程中需要在配置文件中存储密码,但是密码肯定需要加密,当读取配置文件密码时又需要解密,下面代码就通过openssl库在linux下实现了这两个加解密的功能。
之前是使用《c语言通过openssl aes对称加解密和base64编解码将密码存储成密文》
c语言通过openssl aes对称加解密和base64编解码将密码存储成密文_GT19930910的博客-CSDN博客
这篇文章来实现的,后来发现这个加解密过程对于有些字符串来说有问题,会导致加解密之后出来的字符串和原字符串不一样,很有可能是因为编码之后16进制字符中有特殊字符所以导致base64编解码失败,所以下面给大家又展现一版现在咱们项目里面一直在用的接口,完成编解码功能。
/* Created by verycloud on 2020/09/18.
Copyright © 2019 verycloud. All rights reserved.
build in cmdline
gcc -g -O0 main.c -lssl -lcrypto
*/
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <string.h>
#include <stdio.h>
/*
* @parme in str end by '\0'
* @parme out buf size >= 33
*/
void make_md5(const char* in,char* out)
{
int inSize = (int)strlen(in);
unsigned char buf[16];
MD5((const unsigned char*)in, inSize, (unsigned char*)buf);
char tmp[3] = {0};
for (int i = 0; i < 16; i++) {
sprintf(tmp, "%02x", (int)buf[i]);
strcat(out,tmp);
}
}
void make_base64_2K(char s[])
{
unsigned char buf[2048];
int len = EVP_EncodeBlock((unsigned char*)buf, (const unsigned char*)s, strlen(s));
strncpy(s, buf, len);
}
void m_append(char s[], char tmp[], int len)
{
if(s[0] == 0)
{
strncpy(s, tmp, len);
}else
{
strncat(s, tmp, len);
}
}
int string_find(char tmp[], char c)
{
int i;
for(i=0; i<strlen(tmp); i++)
{
if(tmp[i] == c)
{
break;
}
}
return i;
}
char* vcd_encode_crypto(const char* in, char* out)
{
int i, j, k = 0;
char str[1024] = {0};
strncpy(str, in, 1024);
const char* public_key = "!Knowledge@#is#@power~@";
const char* lockstream = "st=lDEFABCNOPyzghi_jQRST-UwxkVWXYZabcdefIJK67nopqr89LMmGH012345uv";
int strLen = (int)strlen(str);
int lockLen = (int)strlen(lockstream);
char randomLock = str[strLen-1];
int lockCount = (int)(strchr(lockstream, randomLock) - lockstream);
// public_key + randomLock + '\0'
int keyLen = (int)strlen(public_key) + 1 + 1;
char* keyBuf = malloc(keyLen);
sprintf(keyBuf, "%s%c", public_key, randomLock);
char password[33] = {0};
make_md5(keyBuf, password);
make_base64_2K(str);
char tmpStream[200] = {0};
for(i=0,j=0,k=0; i<strlen(str); i++)
{
k = (k == strlen(password)) ? 0 : k;
j = (lockCount + (int)password[k] + string_find(lockstream, str[i])) % lockLen;
tmpStream[strlen(tmpStream)] = lockstream[j];
k++;
}
tmpStream[strlen(tmpStream)] = randomLock;
strcpy(out, tmpStream);
free(keyBuf);
return out;
}
char* vcd_decode_crypto(const char* str, char* out){
if (!str || !out) return NULL;
const char* public_key = "!Knowledge@#is#@power~@";
const char* lockstream = "st=lDEFABCNOPyzghi_jQRST-UwxkVWXYZabcdefIJK67nopqr89LMmGH012345uv";
int strLen = (int)strlen(str);
int lockLen = (int)strlen(lockstream);
char randomLock = str[strLen-1];
int lockCount = (int)(strchr(lockstream, randomLock) - lockstream);
// public_key + randomLock + '\0'
int keyLen = (int)strlen(public_key) + 1 + 1;
char* keyBuf = malloc(keyLen);
sprintf(keyBuf, "%s%c", public_key, randomLock);
char password[33] = {0};
make_md5(keyBuf, password);
//printf("make_md5: %s\n", password);
int k = 0;
char* beforeBase64 = malloc(strLen-1);
for(int i = 0; i < strLen-1;i++) {
k = k == strlen(password) ? 0 : k;
int j = (int)(strchr(lockstream,str[i])-lockstream) - lockCount - (int)password[k];
while(j < 0)
j = j + lockLen;
beforeBase64[i] = lockstream[j];
k++;
}
EVP_DecodeBlock((unsigned char *)out, (unsigned char *)beforeBase64, strLen-1);
free(keyBuf);
free(beforeBase64);
return out;
}
int main(int argc, char** argv)
{
if (argc < 2) {
printf("usage: ./a.out test_string\n");
return 0;
}
printf("test_string:%s\n", argv[1]);
char encode_out[1024] = {0};
vcd_encode_crypto(argv[1], encode_out);
printf("encode out: %s\n", encode_out);
char decode_out[1024] = {0};
vcd_decode_crypto(encode_out, decode_out);
printf("decode out: %s\n", decode_out);
return 0;
}
最后欢迎大家一起学习一些其他c/c++技术: