DES加解密类


目录

1、前言

2、分析实现

3、补充优化

4、鸡毛蒜皮

5、贴个代码


1、前言

算是第一个开发任务了,C++写一个DES 加解密类用来解密序列号,加解密适用ecb/cbc模式,最好调用OpenSSL库。

DES是一种对称分组加密算法,只是用它加解密的话,我认为不需要理解得特别深刻,只要知道以下几点就好了:

(1)分组:每八字节为一组,利用密钥进行加密,最后将密文拼接;

(2)对称:加解密使用同一种算法,在openssl中使用的是同一个函数,只是参数不同;

(3)主要有ecb(电子密码)和cbc(密码分组)两种模式,两种模式是密钥产生方式不同,ecb对分组八字节明文组密钥相同,cbc循环产生密钥,也就是对分组八字节明文密钥不一定相同;

(4)明文长度不满足八字节整数倍要求,需要padding,使用末尾补零的方式。

2、分析实现

(1)类组成:

写一个des加解密类,首先从大局观来看这个类的组成:

 其实内容很简单,主要就是加解密的四个函数以及加解密的整合。

(2)类分解:

简单介绍一下各个函数的成分:

a.构造函数+析构函数:

两个构造函数,一个默认构造,其中包含默认密钥;另一个构造可以类外指定密钥。

b.ecb加密函数:

输入明文,调用openssl中的DES_ecb_encrypt函数进行加密,输出密文。

c.ecb解密函数:

输入密文,调用openssl中的DES_ecb_encrypt函数进行解密,输出明文。

d.cbc加密函数:

输入明文,调用openssl中的DES_ncbc_encrypt函数进行解密,输出密文。

e.cbc解密函数:

输入密文,调用openssl中的DES_ncbc_encrypt函数进行解密,输出明文。

f.des加密函数:

输入明文,输出密文,用户可指定模式。

g.des解密函数:

输入密文,输出明文,用户可指定模式。

—————本来想在这里贴个代码的,但是发现代码太占地儿了,所以决定贴在最后了—————

3、补充优化

(1)实现了DES加解密类,在实际业务应用中,需要从文件中读取处理再写入文件,大概如下图:

所以还要再添加四个global函数:

a.从文件中读取字符串;

b.字符串转01比特串;

c.01比特串转字符串;

d.字符串写入文件;

————————————同样,实现代码贴在最后————————————————————

(2)目前是写到了这里,我考虑以下几个优化方向:

a.我要将加密的文件传给云端,这个加密文件是不是应该包含加密模式信息(ecb/cbc);

b.异常处理;

c.这个字符串和比特串的转换写的还比较鸡肋,从网上借鉴的,得再重写一下,用bitset看看;

4、鸡毛蒜皮

————————————以下语言会比较混乱————————————————————

——20230328——

万事开头难:
1、网上资料太多了,讲的内容差异也比较大,需要慢慢挑,很容易花了眼;

2、道心也不坚定,总是觉得能用就好了,没必要搞清楚理论,所以半拉瓶子晃啊晃的;

3、第一天感觉就是摸鱼摸鱼再摸鱼,没啥进展->:)

4、快下班了,我有一个大胆的想法,直接读OpenSSL里的des.h库,看网上的讲解太难受了。

——20230229——

今天转换策略

1、让AI帮我写个代码;(不大行,跑都跑不起来)

2、看看OpenSSL的des.h;

先看实现再看原理。

咱们先装个openssl库:

(1)装库:

哭死真的,装个库类似爹了

windows下VS2017使用openssl库的环境搭建https://www.jianshu.com/p/12b748bdedd2 LNK2019错误搞死我了,结果是链接器没配,我以为是openssl库安装的问题,来来回回装了好几次,哭死!openssl安装1.1.1,别安装3.0,那玩意儿用不起来!

哭死,写出来了,亲娘啊!

-——20230331——

让我测试一下des加密的正确性,比对在线des加密解密结果,我登了四个网站,各个网站加密结果都不一样,而且是base64编码,我输出的是Unicode乱码,人都麻了,后边儿又把结果进行base64编码,跟其中一个网站的结果接近,把那个网站贴过来。编解码这块儿太搞了......

在线des加解密https://www.mklab.cn/utils/des

5、贴个代码

代码实现都是从网上各处借鉴的,感谢万能网络,感谢前辈大佬!

理论:

DES加密算法实现https://zhuanlan.zhihu.com/p/94208042

实践:

C++ 使用openssl库实现 DES 加密——CBC模式 && RSA加密——公加私解——私加公解https://www.cnblogs.com/azbane/p/10178729.html

OPENSSL库的使用-DES篇https://blog.csdn.net/m0_46577050/article/details/121711502

DES加密算法及其openssl实现https://blog.csdn.net/weixin_43255133/article/details/83018608?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-9-83018608-blog-121711502.235%5Ev27%5Epc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.6&utm_relevant_index=12

字符串转二进制https://www.techiedelight.com/zh/convert-string-to-binary-in-cpp/

#include<iostream>
#include<openssl/des.h>
#include<string>
#include<vector>
#include<stdlib.h>
#include<stdio.h>
#include<exception>

//#define DES_ECB 0
//#define DES_CBC 1

static int DES_ECB = 0;
static int DES_CBC = 1;

class DES {
public:
    /**
     * 构造函数,传入加密密钥
     * @param key 加密密钥,长度为8字节
     */
    DES(const std::string& key) {
        //转换字符串为DES_cblock
        memset(keyEncrypt, 0, 8);

        //补齐密钥
        if (key.length() <= 8)
            memcpy(keyEncrypt, key.c_str(), key.length());
        else
            memcpy(keyEncrypt, key.c_str(), 8);

        // 将密钥转换为DES_key_schedule结构体
        DES_set_key_unchecked(&keyEncrypt, &key_schedule_);
    }

    /**
     * DES加密函数(ecb模式 padding 0)
     * @param plaintext 明文
     * @return 密文
     */
    std::string ecb_encrypt(const std::string& plaintext) {
        const_DES_cblock inputblock;//输入的8字节
        memset(inputblock, 0, 8);
        DES_cblock outputblock;//输出的8字节
        memset(outputblock, 0, 8);

        std::vector<unsigned char> vecciphertext;//存放加密的密文

        // 创建一个与明文长度相同的字符串,用于存放密文
        
        unsigned char tmp[8];

        // 调用OpenSSL库的DES_ecb_encrypt函数进行加密,循环加密,每8字节一次
        for (int i = 0; i < plaintext.length() / 8; ++i)
        {
            memcpy(inputblock, plaintext.c_str() + i * 8, 8);
            DES_ecb_encrypt(&inputblock, &outputblock,  &key_schedule_, DES_ENCRYPT);  //加密
            memcpy(tmp, outputblock, 8);

            //将加密的八字节加入容器
            for (int j = 0; j < 8; j++)
                vecciphertext.push_back(tmp[j]);
        }
            //明文
            if (plaintext.length() % 8 != 0)
            {
                size_t tmp1 = plaintext.length() / 8 * 8;
                size_t tmp2 = plaintext.length() - tmp1;
                memset(inputblock, 0, 8);
                memcpy(inputblock, plaintext.c_str() + tmp1, tmp2);
                // 加密函数    
                DES_ecb_encrypt(&inputblock, &outputblock, &key_schedule_, DES_ENCRYPT);
                memcpy(tmp, outputblock, 8);

                for (int j = 0; j < 8; j++)
                    vecciphertext.push_back(tmp[j]);
            }
           
        std::string ciphertext;
        //std::string ciphertext(plaintext.size(), 0);
        //ciphertext.clear();
        ciphertext.assign(vecciphertext.begin(), vecciphertext.end());
        return ciphertext;
    }

    /**
    * DES解密函数(ecb模式)
    * @param ciphertext 密文 
    * @return 密文
    */
    std::string ecb_decrypt(const std::string& ciphertext)
    {
        const_DES_cblock inputblock;
        DES_cblock outputblock;
        std::vector<unsigned char> vecplaintext;
        unsigned char tmp[8];

        for (int i = 0; i < ciphertext.length() / 8; i++)
        {
            memcpy(inputblock, ciphertext.c_str() + i * 8, 8);
            DES_ecb_encrypt(&inputblock, &outputblock, &key_schedule_, DES_DECRYPT);
            memcpy(tmp, outputblock, 8);

            for (int j = 0; j < 8; j++)
                vecplaintext.push_back(tmp[j]);
        }

        if (ciphertext.length() % 8 != 0)
        {
            size_t tmp1 = ciphertext.length() / 8 * 8;
            size_t tmp2 = ciphertext.length() - tmp1;
            memset(inputblock, 0, 8);
            memcpy(inputblock, ciphertext.c_str() + tmp1, tmp2);
            // 解密函数    
            DES_ecb_encrypt(&inputblock, &outputblock, &key_schedule_, DES_DECRYPT);
            memcpy(tmp, outputblock, 8);

            for (int j = 0; j < 8; j++)
                vecplaintext.push_back(tmp[j]);
        }

        std::string plaintext; // 明文   
        //std::string plaintext(ciphertext.size(), 0);
        //plaintext.clear();
        plaintext.assign(vecplaintext.begin(), vecplaintext.end());

        return plaintext;
    }

    /**
     * DES加密函数(cbc模式 padding 0)
     * @param plaintext 明文
     * @return 密文
     */
    std::string cbc_encrypt(const std::string& plaintext)
    {
        //初始化IV向量   
        DES_cblock  ivec;
        memcpy(ivec, keyEncrypt, sizeof(keyEncrypt));

        // 循环加密,每8字节一次    
        const_DES_cblock inputblock;
        DES_cblock outputblock;
        std::vector<unsigned char> vecciphertext;
        unsigned char tmp[8];

        for (int i = 0; i < plaintext.length() / 8; i++)
        {
            memcpy(inputblock, plaintext.c_str() + i * 8, 8);
            DES_ncbc_encrypt(inputblock, outputblock, 8, &key_schedule_, &ivec, DES_ENCRYPT);  //加密
            memcpy(tmp, outputblock, 8);

            for (int j = 0; j < 8; j++)
                vecciphertext.push_back(tmp[j]);

            //重置ivec
            memcpy(ivec, outputblock, 8);
        }

        if (plaintext.length() % 8 != 0)
        {
            size_t tmp1 = plaintext.length() / 8 * 8;
            size_t tmp2 = plaintext.length() - tmp1;
            memset(inputblock, 0, 8);
            memcpy(inputblock, plaintext.c_str() + tmp1, tmp2);
            // 加密函数    
            DES_ncbc_encrypt(inputblock, outputblock, 8, &key_schedule_, &ivec, DES_ENCRYPT);  //加密 
            memcpy(tmp, outputblock, 8);

            for (int j = 0; j < 8; j++)
                vecciphertext.push_back(tmp[j]);
        }

        std::string ciphertext;
        ciphertext.assign(vecciphertext.begin(), vecciphertext.end());
        return ciphertext;
    }

    /**
   * DES解密函数(ecb模式)
   * @param ciphertext 密文 
   * @return 密文
   */
    std::string cbc_decrypt(const std::string& ciphertext)
    {
        //初始化IV向量   
        DES_cblock  ivec;
        memcpy(ivec, keyEncrypt, sizeof(keyEncrypt));

        // 循环解密,每8字节一次    
        const_DES_cblock inputblock;
        DES_cblock outputblock;
        std::vector<unsigned char> vecplaintext;
        unsigned char tmp[8];

        for (int i = 0; i < ciphertext.length() / 8; i++)
        {
            memcpy(inputblock, ciphertext.c_str() + i * 8, 8);
            DES_ncbc_encrypt(inputblock, outputblock, 8, &key_schedule_, &ivec, DES_DECRYPT);  //解密
            memcpy(tmp, outputblock, 8);

            for (int j = 0; j < 8; j++)
                vecplaintext.push_back(tmp[j]);
        }
     

        if (ciphertext.length() % 8 != 0)
        {
            size_t tmp1 = ciphertext.length() / 8 * 8;
            size_t tmp2 = ciphertext.length() - tmp1;
            memset(inputblock, 0, tmp2);
            memcpy(inputblock, ciphertext.c_str() + tmp1, tmp2);
            DES_ncbc_encrypt(inputblock, outputblock, long(tmp2), &key_schedule_, &ivec, DES_DECRYPT);  //解密
            memcpy(tmp, outputblock, tmp2);
            for (int j = 0; j < 8; j++)
                vecplaintext.push_back(tmp[j]);
        }
        std::string plaintext;
        plaintext.assign(vecplaintext.begin(), vecplaintext.end());
        return plaintext;


    }

    std::string DESencrypt(const std::string& plaintext, int mode)
    {
        switch (mode)
        {
        case 0:return ecb_encrypt(plaintext);
        case 1:return cbc_encrypt(plaintext);
        }
        std::cerr << "模式选择错了!" << std::endl;
        exit(1);

    }
    std::string DESdecrypt(const std::string& ciphertext, int mode)
    {
        switch (mode)
        {
        case 0:return ecb_decrypt(ciphertext);
        case 1:return cbc_decrypt(ciphertext);
        }
        std::cerr <<  "模式选择错了!" << std::endl;
        exit(1);
    }

private:
    DES_cblock keyEncrypt; //密钥
    DES_key_schedule key_schedule_; // 存放加密密钥的结构体
};


int main()
{
    std::string key = "jzysg";
    DES des(key);
    std::string plaintext = "上班太快乐了!";
    std::cout << "输入明文为:" << plaintext << std::endl;

    //ecb 模式
    std::string ecb_ciphertext = des.DESencrypt(plaintext,DES_ECB);
    std::cout << "ecb加密密文为:" << ecb_ciphertext << std::endl;
    std::string ecb_decrpyttext = des.DESdecrypt(ecb_ciphertext,3);
    std::cout << "ecb解密明文为:" << ecb_decrpyttext << std::endl;

   //cbc模式
    std::string cbc_ciphertext = des.DESencrypt(plaintext,DES_CBC);
    std::cout << "cbc加密密文为:" << cbc_ciphertext << std::endl;
    std::string cbc_decrpyttext = des.DESdecrypt(cbc_ciphertext,DES_CBC);
    std::cout << "cbc解密明文为:" << cbc_decrpyttext << std::endl;

    //std::string ecb_ciphertext = des.ecb_encrypt(plaintext);
    //std::cout << "ecb加密密文为:" << ecb_ciphertext << std::endl;
    //std::string ecb_decrpyttext = des.ecb_decrypt(ecb_ciphertext);
    //std::cout << "ecb解密明文为:" << ecb_decrpyttext << std::endl;
    //std::string cbc_ciphertext = des.cbc_encrypt(plaintext);
    //std::cout << "cbc加密密文为:" << cbc_ciphertext << std::endl;
    //std::string cbc_decrpyttext = des.cbc_decrypt(cbc_ciphertext);
    //std::cout << "cbc解密明文为:" << cbc_decrpyttext << std::endl;
    
 
}

#include "global_func.h"

std::string readFileinfotoString(const std::string& filename)
{
    std::ifstream ifile(filename, std::ios::binary);
    std::ostringstream buf;
    char ch;
    while (buf && ifile.get(ch))
        buf.put(ch);
    return buf.str();
}


void writeStringtoFile(const std::string& s, const std::string& write_filename)
{
    std::ofstream os(write_filename, std::ios_base::out);     
    os.open(write_filename,std::ios::binary);
    os << s;   
    os.close();
}


std::string byte2bit(const std::string& byte)
{
    size_t length = byte.length();
    std::string bit(length * 8, 0);
    for (int i = 0; i < length; i++) {
        for (int j = 0; j < 8; j++) {
            bit[i * 8 + j] = (byte[i] >> (7 - j)) & 1;
        }
    }
    return bit;
}


std::string bit2byte(const std::string& bit)
{
    size_t length = bit.length() / 8;
    std::string byte(length, 0);
    for (int i = 0; i < length; i++)
    {
        byte[i] = 0;
        for (int j = 0; j < 8; j++)
            byte[i] = (byte[i] << 1) + bit[i * 8 + j];
    }
    return byte;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值