【C++随记2】linux系统下简单加密算法实现

1. 安装c++

在 CentOS7 上,可以使用 yum 包管理器来安装 C++11 的开发工具和库。具体步骤如下:

1.1 更新系统软件包到最新版本:

sudo yum update #更新

1.2 安装 C++11 开发工具和库:

sudo yum install gcc-c++ -y
sudo yum install libstdc++-devel -y

以上命令会安装GNU C++编译器和标准C++库的开发文件,包括头文件和库文件。其中,gcc-c++是C++编译器,libstdc+±devel是标准C++库的开发文件。

1.3 检查安装是否成功:

gcc --version
g++ --version
在这里插入图片描述

2. 测试程序

2.1 创建项目目录

在test目录下,创建项目目录secretkey,在该目录下创建src、obj、lib和include分别用来保存.cpp源文件、过程文件.o、生成的动态库文件.so和头文件.h,主函数创建在主目录下。

2.2 创建Makefile编译脚本文件

根据程序文件的名称,创建编译脚本,使用make执行,实现动态库编译
此处避坑,PROJECT=libprint_func.so 后面的名称必须要加上’lib’,否则编译调用函数时,无法找到该动态库文件,即原程序名称为print_func,加上lib生成动态库

#生成的动态库文件名
PROJECT=libprint_func.so 
#使用的编译器,如果用c语言则使用gcc
CC=g++  

#源文件保存路径,使用通配符wildcard在路径src目录下查找.cpp文件,如果用c语言则为*.c
SOURCES=$(wildcard src/*.cpp)   
#patsubst函数用于将文件模式进行替换,$(patsubst 原模式, 目标模式, 文件列表)
OBJECTS=$(patsubst %.cpp,%.o,$(SOURCES))

.PHONY:clean

CFLAG = -Iinclude -fPIC -shared
LD_FLAG = -fPIC -s -Wl,-z,relro,-z,now,-z,noexecstack -fstack-protector-all

$(PROJECT): $(OBJECTS)
    mkdir -p lib
    $(CC)   -shared -o lib/$@ $(patsubst %.o,obj/%.o,$(notdir $(OBJECTS))) $(LD_FLAG)
    @echo "finish $(PROJECT)"

.cpp.o:
    @mkdir -p obj
    $(CC) -c $< $(CFLAG) -o obj/$(patsubst %.cpp,%.o,$(notdir $<))

clean:
    -rm -rf obj lib
    $echo "clean up."

2.3 创建程序文件

分别在src中创建.cpp文件,在include中创建.h文件,在secretkey主目录下创建main.cpp文件,并分别敲入c++代码
transfer.cpp

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<string>

//字符数组,用于随机数匹配
unsigned char Number[10] ={'0','1','2','3','4','5','6','7','8','9'};
unsigned char Letters[52]={'a','b','c','d','e','f','g','h','i','j','k','l','m',
                           'n','o','p','q','r','s','t','u','v','w','x','y','z',
                           'A','B','C','D','E','F','G','H','I','J','K','L','M',
                           'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

//long型转换成字符
bool transferLong2ByteArray(unsigned char* byte, unsigned char length, unsigned long version){
    unsigned long temp = version;
    for(unsigned char i = 0; i < length; ++i){
        unsigned char res = (unsigned char)(temp & 0xff);
        byte[i] = res;
        temp = temp >> 8;
    }
    return true;
}

//字符转换成long型
unsigned long transferByteArrayToLong(unsigned char* byte, unsigned char length)
{
    unsigned long version = 0;
#if 1
    for(unsigned int i = 0; i < length; ++i){
        unsigned long temp = byte[i];
        version |= (temp << i * 8);
    }
#else
    long s = 0;
    long s0 = (byte[0] & 0xff);
    long s1 = (byte[1] & 0xff) << 8;
    long s2 = (byte[2] & 0xff) << 16;
    long s3 = (byte[3] & 0xff << 24);

    version = s0 | s1 | s2 | s3;
#endif
    return version;
}


//数组内随机数处理函数
void generateString(unsigned char * dest, unsigned int len)
{
    unsigned int cnt, randNo;
    srand((unsigned int)time(NULL));
 
    for (cnt = 0; cnt<len; cnt++)
    {
        randNo = rand() % 51;
        *dest = Letters[randNo];
        dest++;
    }
}

//char数组复制处理函数,不固定起始位置
void my_strcpy_array(unsigned char *str, unsigned char *arr, int start, int end)
{
    int num = 0;
    for(num = start; num <= end-1; num++)
    {
        str[num - start] = arr[num];
    }
}

//char数组复制处理函数,固定起始位置
void my_strcpy_array1(unsigned char *str, unsigned char *arr, int len)
{
    int num = 0;
    for(num = 0; num <= len-1; num++)
    {
        str[num] = arr[num];
    }
}

//解密算法函数,字符串输入进行解密,返回long型
void decrypt_func(unsigned char *decrypt, unsigned char *encryptedData, unsigned char *keyData,unsigned char *keyPeriod)
{
    unsigned char kyd[10][5],kyp[10][2];
    int i,j;
    for(i=0; i<10;i++)
    {
        for(j=0; j<5;i++)
        {
            my_strcpy_array(kyd[i],keyData,i*5,i*5+5);
        }
    }
    for(i=0; i<10;i++)
    {
        printf("kyd: %s\n",kyd[i]);
    }
    
}

//加密算法函数
void encrypted_func(unsigned char *encryptedData,unsigned char *keyData,unsigned char *keyPeriod,long data1, long data2)
{
    
    char tmp1[10] = "", tmp2[8] = "";
    sprintf(tmp1, "%d", data1);
    printf("tmp1 = %s\n", tmp1);
    sprintf(tmp2, "%d", data2);
    printf("tmp2 = %s\n", tmp2);
    //想复杂了,在C++的库里可以用上面的方式完美解决long转字符串
    //unsigned long endDate = (unsigned long)IN;
    //unsigned char byte[4] = { 0 };
    //transferLong2ByteArray(byte, 4, endDate);
    //unsigned long finalDate = transferByteArrayToLong(byte, 4);
    //printf("finalDate: %ld\n", finalDate);
    
    //秘钥随机数处理
    unsigned int i = 0, j = 0, randNo = 0;
    srand((unsigned)time(NULL));
    for(i=0; i < 10; i++)
    {
        for(j=0; j<5; j++)
        {
            randNo = rand() % 51;
            keyData[i*5 +j] = Letters[randNo];
        }
    }
    printf("keyData: %s\n", keyData);
    
    //秘钥期限随机数处理
    for(i=0; i < 10; i++)
    {
        for(j=0; j<2; j++)
        {
            randNo = rand() % 51;
            keyPeriod[i*2 +j] = Letters[randNo];
        }
    }
    printf("keyPeriod: %s\n", keyPeriod);
    
    //平台使用期加密
    unsigned char transferKeyData[5];
    unsigned int itmp1 = 0; 
    for(i=0; i<sizeof(tmp1); i++)
    {
        itmp1 = (unsigned int)tmp1[i];
        if(itmp1 == 48){my_strcpy_array(transferKeyData, keyData, 0, 5);}
        else if(itmp1 == 49){my_strcpy_array(transferKeyData, keyData, 5, 10);}
        else if(itmp1 == 50){my_strcpy_array(transferKeyData, keyData, 10, 15);}
        else if(itmp1 == 51){my_strcpy_array(transferKeyData, keyData, 15, 20);}
        else if(itmp1 == 52){my_strcpy_array(transferKeyData, keyData, 20, 25);}
        else if(itmp1 == 53){my_strcpy_array(transferKeyData, keyData, 25, 30);}
        else if(itmp1 == 54){my_strcpy_array(transferKeyData, keyData, 30, 35);}
        else if(itmp1 == 55){my_strcpy_array(transferKeyData, keyData, 35, 40);}
        else if(itmp1 == 56){my_strcpy_array(transferKeyData, keyData, 40, 45);}
        else if(itmp1 == 57){my_strcpy_array(transferKeyData, keyData, 45, 50);}
        my_strcpy_array1(encryptedData + i*5, transferKeyData, 5);
    }
    //秘钥使用期加密
    unsigned char keyPeriodData[5];
    unsigned int itmp2 = 0; 
    for(i=0; i<sizeof(tmp2); i++)
    {
        itmp2 = (unsigned int)tmp2[i];
        if(itmp2 == 48){my_strcpy_array(keyPeriodData, keyPeriod, 0, 2);}
        else if(itmp2 == 49){my_strcpy_array(keyPeriodData, keyPeriod, 2, 4);}
        else if(itmp2 == 50){my_strcpy_array(keyPeriodData, keyPeriod, 4, 6);}
        else if(itmp2 == 51){my_strcpy_array(keyPeriodData, keyPeriod, 6, 8);}
        else if(itmp2 == 52){my_strcpy_array(keyPeriodData, keyPeriod, 8, 10);}
        else if(itmp2 == 53){my_strcpy_array(keyPeriodData, keyPeriod, 10, 12);}
        else if(itmp2 == 54){my_strcpy_array(keyPeriodData, keyPeriod, 12, 14);}
        else if(itmp2 == 55){my_strcpy_array(keyPeriodData, keyPeriod, 14, 16);}
        else if(itmp2 == 56){my_strcpy_array(keyPeriodData, keyPeriod, 16, 18);}
        else if(itmp2 == 57){my_strcpy_array(keyPeriodData, keyPeriod, 18, 20);}
        my_strcpy_array1(encryptedData + 50 + i*2, keyPeriodData, 2);
    }
    printf("encryptedData: %s\n", encryptedData);
    
}

long print_func(long endTime, long keyTime)
{
    long t_currentTime;
    long t_endTime = (long)endTime;
    long t_keyTime = (long)keyTime;
    time_t timer0;
    int i = 0;
    unsigned char retEncrypted[70];
    unsigned char retkeyData[50];
    unsigned char retkeyPeriod[20];
    unsigned char retdecrypt[10];
    
    //数据加密
    encrypted_func(retEncrypted, retkeyData, retkeyPeriod, t_keyTime, t_endTime);
    printf("encrypted_func: %s--%s--%s\n", retEncrypted, retkeyData, retkeyPeriod);
    
    //数据解密
    decrypt_func(retdecrypt, retEncrypted, retkeyData, retkeyPeriod);
    printf("retdecrypt data: %s\n", retdecrypt);
    
    struct tm* pPeriodTime = localtime(&t_endTime);
    printf("Limit date:%d-%d-%d", pPeriodTime->tm_year + 1900, pPeriodTime->tm_mon + 1, pPeriodTime->tm_mday);
    printf(" %d:%d:%d\n",pPeriodTime->tm_hour,pPeriodTime->tm_min,pPeriodTime->tm_sec);
    
    timer0 = time(NULL);
    t_currentTime = (long)timer0;
    
    struct tm* plocaltime = localtime(&timer0);
    printf("Current date:%d-%d-%d", plocaltime->tm_year + 1900, plocaltime->tm_mon + 1, plocaltime->tm_mday);
    printf(" %d:%d:%d\n",plocaltime->tm_hour,plocaltime->tm_min,plocaltime->tm_sec);
    
    if (t_currentTime > t_endTime)
    {
        return 0;
    }
    else
    {
        printf("System data: [%lld]\n", t_currentTime);
        return t_currentTime;
    }
    
}

transfer.h

long print_func(long keyTime, long endTime);

main.cpp

#include<cstdio>
#include "transfer.h"

int main()
{
    unsigned long endDate = 1698681600;
    unsigned long keyDate = 20231031;

    unsigned long ret = print_func(endDate,keyDate);
    if(ret == 0)
    {
        printf("Expired the period!\n");
    }
    else
    {
        printf("Get data: %ld\n", ret);
    }

    return 0;
}

2.4 编译并执行

1.编译动态库文件,进入到目录中,执行make命令
cd /test/secretkey/
make
在这里插入图片描述

分别在obj文件夹中生成了transfer.o文件,在lib文件夹中生成了libprint_func.so文件,中间文件已被清理
2. 编译主函数文件main.cpp,编译成功后,会在secretkey目录下生成demo可执行文件。
g++ -o demo main.cpp -lprint_func -Llib -Iinclude -Wall
g++ -o testEncrypted testEncrypted.cpp -lencrypted -Llib -Iinclude -Wall
g++ -o testDecrypted testDecrypted.cpp -ldecrypted -Llib -Iinclude -Wall
3.在目录/test/secretkey/下执行可执行文件demo,查看输出结果。
./demo
执行报错:
在这里插入图片描述

此处报错是因为动态库.so文件未被找到,这时需要查看demo依赖的共享库,查看命令为:
ldd demo
在这里插入图片描述

可以看到共享库中并没有libprint_func.so动态库,此时需要进行解决处理

2.5 动态库无法找到解决方案

临时解决
  使用命令:export LD_LIBRARY_PATH=库路径,将当前目录加入环境变量,但是终端退出了就无效了。(适用于代码测试)
LD_LIBRARY_PATH介绍:
1、作用
①指定查找共享库(动态链接库)时除了默认路径之外的其他路径
②该路径在默认路径之前查找

2、设置方法
用export命令来设置值
例如:
export LD_LIBRARY_PATH=./lib #设置mylib文件夹路径为我们动态库所在的路径
echo $LD_LIBRARY_PATH #打印该环境变量

永久解决
  将export LD_LIBRARY_PATH=./mylib写入家目录下.bashrc文件中,这样就可以永久设置了。
  修改了bashrc文件后,需要将终端关掉再次打开,该文件才能生效。
永久解决(正规写法)
步骤:
需要找动态连接器的配置文件 – /etc/ld.so.conf
动态库的路径写到配置文件中 – 绝对路径,例如:/home/myproject/mylib
终端使用命令更新:sudo ldconfig -v

2.6 执行应用程序

再次输入 ./demo,执行应用程序,正常运行并输出结果。
在这里插入图片描述

3. 算法说明

讲一下为何用g++而不是gcc,因为g++有更加全面的标准库,很多类型转换做的比gcc要更加全面方便使用,也会省很多的代码去写专用函数转换。

3.1 unsigned char 数组与 long 类型互转

参考链接:https://www.cnblogs.com/wanghao-boke/p/17482291.html

#include<cstdio>

typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
typedef unsigned char uint8_t;

bool transferLong2ByteArray(uint8_t* byte, uint8_t length, uint64_t version){
    uint64_t temp = version;
    for(uint8_t i = 0; i < length; ++i){
        uint8_t res = (uint8_t)(temp & 0xff);
        byte[i] = res;
        temp = temp >> 8;
    }
    return true;
}

uint64_t transferByteArrayToLong(uint8_t* byte, uint8_t length)
{
    uint64_t version = 0;
#if 1
    for(int i = 0; i < length; ++i){
        uint64_t temp = byte[i];
        version |= (temp << i * 8);
    }
#else
    long s = 0;
    long s0 = (byte[0] & 0xff);
    long s1 = (byte[1] & 0xff) << 8;
    long s2 = (byte[2] & 0xff) << 16;
    long s3 = (byte[3] & 0xff << 24);

    version = s0 | s1 | s2 | s3;
#endif
    return version;
}

int main()
{
    uint32_t version = 0x000710;
    uint64_t longVersion = (uint64_t)version;

    uint8_t byte[4] = {0};
    transferLong2ByteArray(byte, 4, longVersion);

    uint64_t finalVersion = transferByteArrayToLong(byte, 4);
    printf("vrsion %ld\n", finalVersion);

    return 0;
}

3.2 随机字符匹配

unsigned char Letters[52]={'a','b','c','d','e','f','g','h','i','j','k','l','m',
                           'n','o','p','q','r','s','t','u','v','w','x','y','z',
                           'A','B','C','D','E','F','G','H','I','J','K','L','M',
                           'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
                           
//数组内随机数处理函数
void generateString(unsigned char * dest, unsigned int len)
{
        unsigned int cnt, randNo;
        srand((unsigned int)time(NULL));
     
        for (cnt = 0; cnt<len; cnt++)
        {
        randNo = rand() % 51;
        *dest = Letters[randNo];
        dest++;
        }
}

3.3 char数组间复制

//char数组复制处理函数,不固定起始位置
void my_strcpy_array(unsigned char *str, unsigned char *arr, int start, int end)
{
    int num = 0;
    for(num = start; num <= end-1; num++)
    {
        str[num - start] = arr[num];
    }
}

//char数组复制处理函数,固定起始位置
void my_strcpy_array1(unsigned char *str, unsigned char *arr, int len)
{
    int num = 0;
    for(num = 0; num <= len-1; num++)
    {
        str[num] = arr[num];
    }
}
  • 20
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值