狂自私

导航

对称加解密的综合例子

cpp

// 对称加解密的综合例子.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 需要这些依赖项:libssl.lib;Ws2_32.lib;libcrypto.lib;CRYPT32.lib
//

#include <iostream>
#include <fstream>
#include "openssl/evp.h"

#include <vector>
#include <initializer_list>

/*加密*/
int do_encrypt_C(const EVP_CIPHER* type, const char* ctype);
/*解密*/
int do_decypt_C(const EVP_CIPHER* type, const char* ctype);

/*加密*/
int do_encrypt_CPP(const EVP_CIPHER* type, const char* ctype);
/*解密*/
int do_decypt_CPP(const EVP_CIPHER* type, const char* ctype);
int main()
{
    do_encrypt_CPP(EVP_desx_cbc(), "dex-cbc");
    do_decypt_CPP(EVP_desx_cbc(), "des-cbc");
}

int do_encrypt_C(const EVP_CIPHER* type, const char* ctype) {
    unsigned char outbuf[1024]{ 0 };
    int outlen{}, tmplen{};
    unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, };
    unsigned char iv[]{ 1,2,3,4,5,6,7,8 };
    char in_text[] = "Hello world!";
    /*
    * 原写法:EVP_CIPHER_CTX ctd;
    * 已经不再被使用的
    */
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

    FILE* out{};
    EVP_CIPHER_CTX_init(ctx);   //初始化对称计算上下文。
    //加密初始化函数,本函数调用具体算法的init回调函数,将外送密钥key转换为内部密钥形式,将初始化向量iv复制到CTX结构中。
    /*
    * EVP_CIPHER_CTX *ctx,      :输入参数,是已经被函数EVP_CIPHER_CTX_init初始化过的算法上下文结构体指针。
    const EVP_CIPHER *cipher,   :输入参数,表示具体的加密函数,它是一个指向EVP_CIPHER结构体的指针,指向一个EVP_CIPHER*类型的函数。在OpenSSL中,对称加密算法的格式都以函数形式提供,其实该函数返回一个该算法的结构体
    ENGINE *impl,               :输入参数,指向ENGINE结构体的指针,表示加密算法的引擎,可以理解为加密算法的提供者,比如是硬件加密卡提供者、软件算法提供者等,如果取值为NULL,就使用默认引擎。
    const unsigned char *key,   :输入参数,表示加密密钥,长度根据不同的加密算法而定。
    const unsigned char *iv     :输入参数,初始向量,当cipher所指的算法为CBC模式的算法才有效,因为CBC模式需要初始向量的输入,长度是对称算法分组长度。
    返回值:如果函数执行成功就返回1,否则返回0。

    值得注意的是,key和iv的长度都是根据不同算法而有默认值的,比如DES算法的key和iv都是8字节长度;3DES算法的key的长度是24字节,iv是8字节;128位的AES算法的key和iv都是16字节。使用时要先根据算法分配好key和iv的长度空间。
    */
    EVP_EncryptInit_ex(ctx, type, nullptr, key, iv);    
    //加密函数,用于多次计算,它调用了具体算法的do_cipher回调函数。
    /*
    * 该函数执行对数据的加密。
    * EVP_CIPHER_CTX *ctx,      :输入参数,指向EVP_CIPHER_CTX的指针,应该已经初始化过了。
    unsigned char *out,         :输出参数,指向存放输出密文的缓冲区指针。
    int *outl,                  :输出参数,输出密文的长度。
    const unsigned char *in,    :输入参数,指向存放明文的缓冲区指针。
    int inl                     :输入参数,要加密的明文长度。
    返回值:如果函数执行成功就返回1,否则返回0。
    */
    if (!(EVP_EncryptUpdate(ctx, outbuf, &outlen, (unsigned char*)in_text, (int)strlen(in_text)))) {
        std::cout << "EVP_EncryptUpdate\n";
        return EXIT_FAILURE;
    }
    //获取加密结果,函数可能涉及填充,它调用了具体算法的do_cipher回调函数。
    /*
    * EVP_CIPHER_CTX *ctx,      :输入参数,EVP_CIPHER_CTX结构体。
     unsigned char *out,        :输出参数,指向输出密文缓冲区的指针。
     int *outl                  :输出参数,指向一个整型变量,该变量存储输出的密文数据长度。
     返回值:如果函数执行成功就返回1,否则返回0。
    */
    if (!(EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))) {
        std::cout << "EVP_EncryptFinal_ex\n";
        return EXIT_FAILURE;
    }
    outlen += tmplen;
    //清除对称算法上下文数据,它调用用户提供的销毁函数清除内存中的内部密钥以及其他数据。
    EVP_CIPHER_CTX_cleanup(ctx);
    out = fopen("./cipher", "wb+");
    fwrite(outbuf, 1, outlen, out);
    fflush(out);
    fclose(out);

    return EXIT_SUCCESS;
}

int do_decypt_C(const EVP_CIPHER* type, const char* ctype) {
    unsigned char inbuf[1024]{};
    unsigned char outbuf[1024]{};
    int outlen{}, inlen{}, tmplen{};
    unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, };
    unsigned char iv[]{ 1,2,3,4,5,6,7,8 };
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    FILE* in{};
    EVP_CIPHER_CTX_init(ctx);   
    ////解密初始化函数。
    //和加密一样,解密时也要先初始化,用于设置密码算法、加密引擎、密钥、初始向量等参数。
    /*
    * EVP_CIPHER_CTX *ctx,      :输入参数;EVP_CIPHER_CTX结构体。
    const EVP_CIPHER *cipher,   :输入参数;指向EVP_CIPHER,表示要使用的解密算法。
    ENGINE *impl,               :输入参数;指向ENGINE,表示解密算法使用的加密引擎。应用程序可以使用自定义的加密引擎,如硬件加密算法等。如果取值为NULL,就使用默认引擎。
    const unsigned char *key,   :输入参数;解密密钥,其长度根据解密算法的不同而不同。
    const unsigned char *iv     :输入参数;初始向量,根据算法的模式而确定是否需要,比如CBC模式是需要iv的。长度同分组长度。
    返回值:如果函数执行成功就返回1,否则返回0。
    */
    EVP_DecryptInit_ex(ctx, type, nullptr, key, iv);

    in = fopen("./cipher", "rb");
    inlen = fread(inbuf, 1, sizeof(inbuf), in);
    fclose(in);

    std::cout << "readlen:" << inlen << '\n';
    //解密函数,用于多次计算,它调用了具体算法的do_cipher回调函数。
    /*
     EVP_CIPHER_CTX *ctx,       :输入参数;EVP_CIPHER_CTX结构体。
     unsigned char *out,        :输出参数;指向解密后存放明文的缓冲区。
     int *outl,                 :输出参数;指向存放明文长度的整型变量。
     const unsigned char *in,   :输入参数;指向存放密文的缓冲区的指针。
     int inl                    :输入参数;指向存放密文的整型变量。
     返回值:如果函数执行成功就返回1,否则返回0。
    */
    if (!(EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen))) {
        std::cout << "EVP_DecryptUpdate\n";
        return EXIT_FAILURE;
    }
    //获取解密结果,函数可能涉及填充,它调用了具体算法的do_cipher回调函数。
    /*
     EVP_CIPHER_CTX *ctx,   :输入参数;EVP_CIPHER_CTX结构体。
     unsigned char *outm,   :输出参数;指向输出的明文缓冲区指针。
     int *outl              :输入参数;指向存储明文长度的整型变量。
    */
    if (!(EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen))) {
        std::cout << "EVP_DecryptFinal_ex\n";
        return EXIT_FAILURE;
    }
    outlen += tmplen;
    //清除对称算法上下文数据,它调用用户提供的销毁函数清除内存中的内部密钥以及其他数据。
    EVP_CIPHER_CTX_cleanup(ctx);
    std::cout << "result:" << outbuf << '\n';

    return EXIT_SUCCESS;
}

int do_encrypt_CPP(const EVP_CIPHER* type, const char* ctype) {
    unsigned char outbuf[1024]{ 0 };
    int outlen{}, tmplen{};
    unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, };
    unsigned char iv[]{ 1,2,3,4,5,6,7,8 };
    char in_text[] = "Hello world!";
    /*
    * 原写法:EVP_CIPHER_CTX ctd;
    * 已经不再被使用的
    */
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

    //FILE* out{};
    EVP_CIPHER_CTX_init(ctx);
    EVP_EncryptInit_ex(ctx, type, nullptr, key, iv);

    if (!(EVP_EncryptUpdate(ctx, outbuf, &outlen, (unsigned char*)in_text, (int)strlen(in_text)))) {
        std::cout << "EVP_EncryptUpdate\n";
        return EXIT_FAILURE;
    }

    if (!(EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))) {
        std::cout << "EVP_EncryptFinal_ex\n";
        return EXIT_FAILURE;
    }
    outlen += tmplen;
    EVP_CIPHER_CTX_cleanup(ctx);
    auto out = std::ofstream("./cipher", std::ios::out | std::ios::binary);
    out.write((char*)outbuf, strlen((char*)outbuf));
    out.close();
    /*out = fopen("./cipher", "wb+");
    fwrite(outbuf, 1, outlen, out);
    fflush(out);
    fclose(out);*/

    return EXIT_SUCCESS;
}

int do_decypt_CPP(const EVP_CIPHER* type, const char* ctype) {
    unsigned char inbuf[1024]{};
    unsigned char outbuf[1024]{};
    int outlen{}, inlen{}, tmplen{};
    unsigned char key[]{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, };
    unsigned char iv[]{ 1,2,3,4,5,6,7,8 };
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    //FILE* in{};
    EVP_CIPHER_CTX_init(ctx);
    EVP_DecryptInit_ex(ctx, type, nullptr, key, iv);
    auto in = std::ifstream("./cipher");
    in.read((char*)inbuf, sizeof(inbuf));
    inlen = strlen((char*)inbuf);
    /*in = fopen("./cipher", "rb");
    inlen = fread(inbuf, 1, sizeof(inbuf), in);
    fclose(in);*/
    in.close();

    std::cout << "readlen:" << inlen << '\n';
    if (!(EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen))) {
        std::cout << "EVP_DecryptUpdate\n";
        return EXIT_FAILURE;
    }
    if (!(EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen))) {
        std::cout << "EVP_DecryptFinal_ex\n";
        return EXIT_FAILURE;
    }
    outlen += tmplen;
    EVP_CIPHER_CTX_cleanup(ctx);
    std::cout << "result:" << outbuf << '\n';

    return EXIT_SUCCESS;
}
View Code

 

posted on 2022-09-14 17:07  狂自私  阅读(41)  评论(0编辑  收藏  举报