Windows+VS2019环境各密码算法库(openssl\GMP\ZLib)的环境配置及用法总结

罗法
2023-12-01

GMP

要点:首先VS中只能使用.lib文件作静态库,网上用.a的纯属**

安装教程+编译完成的文件

文件:上述文件还是会有点问题,在此我自己编译了一套,用起来还不错。度娘网盘 提取码lefi

环境

首先将gmp.h及libgmp-10.lib放到同一文件夹下,记为GMPLib

  1. 工程右键→属性→c/c++→常规→附加包含目录:GMPLib(gmp.h所在目录)
  2. 工程右键→属性→链接器→常规→附加库目录:GMPLib(libgmp-10.lib所在目录)
  3. 工程右键→属性→链接器→输入→附加依赖项:libgmp-10.lib
  4. 若你的电脑中没有GMP的dll库,还需将其中的libgmp-10.dll文件放在你的可执行exe文件的同一目录下。

注:gmpxx库同理,只不过换成了libgmpxx-4.lib\dll文件。

使用

#include <stdio.h>
#include <gmp.h>
const int MAXN = 1e5 + 5;
typedef mpz_t bint;

char sa[2020], sb[2020];

int main()
{
	mpz_t a,b,t;	//mpz_t 为GMP内置大数类型
	scanf("%s", sa);
	scanf("%s", sb);
	mpz_init_set_str(a, sa, 10); //大数a初始化为字符串sa代表的数字
	mpz_init_set_str(b, sb, 10);
	mpz_init(t);    //大数t使用前要进行初始化,以便动态分配空间
	//mpz_ui_pow_ui(t, 2, 100);	//GMP所有函数基本都是以mpz打头
	int i;
	for(i=1;i<=100;i++)
		mpz_mul(t, a, b);
	gmp_printf("a * b = %Zd\n", t);   //输出大数,大数的格式化标志为%Zd
	mpz_clears(a,b,t,NULL); //清除,最后以NULL结尾
	return 0;
}

ZLIB

要点:此处使用单一静态库,环境配置中与上述有所不同,需要添加3个宏定义

安装教程

环境

  1. 包含头文件

    属性–C/C+±-常规–附加包含目录(添加包含.h文件的目录)

  2. 定义宏

    属性–C/C+±-预处理器–预处理器定义:添加3个宏: ZLIB_WINAPI;ASMV;ASMINF

  3. 项目包含.lib文件所在的目录:

    属性–链接器–常规–附加库目录

  4. 项目包含.lib文件

    属性–链接器–输入–附加依赖项(libstat.lib)

使用

#include "zconf.h"
#include "zlib.h"
#include <string.h>
#include <Windows.h>
// The one and only application object

using namespace std;

#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
#  include <fcntl.h>
#  include <io.h>
#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
#  define SET_BINARY_MODE(file)
#endif

#define CHUNK 16384
int def(FILE* source, FILE* dest, int level)
{
    int ret, flush;
    unsigned have;
    z_stream strm;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];
    /*allocate defalte state*/
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    ret = deflateInit(&strm, level);
    if (ret != Z_OK)
        return ret;

    do
    {
        strm.avail_in = fread(in, 1, CHUNK, source);
        if (ferror(source))
        {
            (void)deflateEnd(&strm);
            return Z_ERRNO;
        }
        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
        strm.next_in = in;
        do
        {
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = deflate(&strm, flush);
            have = CHUNK - strm.avail_out;
            if (fwrite(out, 1, have, dest) != have || ferror(dest))
            {
                (void)deflateEnd(&strm);
                return Z_ERRNO;
            }
            //The way we tell that deflate() has no more output is by seeing that it did not fill the output buffer,
            //leaving avail_out greater than zero.
        } while (strm.avail_out == 0);
    } while (flush != Z_FINISH);
    (void)deflateEnd(&strm);
    return Z_OK;
}

int inf(FILE* source, FILE* dest)
{
    int ret;
    unsigned have;
    z_stream strm;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);
    if (ret != Z_OK)
        return ret;
    do
    {
        strm.avail_in = fread(in, 1, CHUNK, source);
        if (ferror(source))
        {
            (void)inflateEnd(&strm);
            return Z_ERRNO;
        }
        if (0 == strm.avail_in)
            break;
        strm.next_in = in;
        do
        {
            strm.avail_out = CHUNK;
            strm.next_out = out;

            ret = inflate(&strm, Z_NO_FLUSH);
            switch (ret)
            {
            case Z_NEED_DICT:
                ret = Z_DATA_ERROR;
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                (void)inflateEnd(&strm);
                return ret;
            }
            have = CHUNK - strm.avail_out;
            if (fwrite(out, 1, have, dest) != have || ferror(dest))
            {
                (void)inflateEnd(&strm);
                return Z_ERRNO;
            }
        } while (strm.avail_out == 0);
    } while (ret != Z_STREAM_END);
    (void)inflateEnd(&strm);
    return ret = Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

void zerr(int ret)
{
    fputs("zpipe: ", stderr);
    switch (ret) {
    case Z_ERRNO:
        if (ferror(stdin))
            fputs("error reading stdin/n", stderr);
        if (ferror(stdout))
            fputs("error writing stdout/n", stderr);
        break;
    case Z_STREAM_ERROR:
        fputs("invalid compression level/n", stderr);
        break;
    case Z_DATA_ERROR:
        fputs("invalid or incomplete deflate data/n", stderr);
        break;
    case Z_MEM_ERROR:
        fputs("out of memory/n", stderr);
        break;
    case Z_VERSION_ERROR:
        fputs("zlib version mismatch!/n", stderr);
    }
}

OPENSSL

要点:安装比较简单

安装:

  1. 官网下载一个安装包,例如Win32 OpenSSL v1.1.1g.exe
  2. 无脑安装,中间有一步选择lib复制路径,要改一下,改成复制到openssl安装路径

环境:
为方便统一使用,此处我将主要文件集中在一起,记为Envior文件夹

  1. 将openssl安装路径(C:\Program Files (x86)\OpenSSL-Win32)中的include\openssl文件夹整个复制到Envior

  2. 将openssl安装路径中的lib文件夹下的libssl_static.lib及libcrypto_static.lib复制到Envior

  3. 包含头文件

    属性–C/C+±-常规–附加包含目录(添加目录Envior)

  4. 项目包含.lib文件所在的目录:

    属性–链接器–常规–附加库目录(添加目录Envior)

  5. 项目包含.lib文件

    属性–链接器–输入–附加依赖项(libssl_static.lib;libcrypto_static.lib;ws2_32.lib)

使用:

#include <openssl/md5.h>
#include <string.h>
#include <stdio.h>

void MD5(char* input,unsigned char* output) //MD5求摘要
{
    MD5_CTX ctx;
    
    memset(output, 0, sizeof(output));
    MD5_Init(&ctx);
    MD5_Update(&ctx, input, strlen(input) );
    MD5_Final(output, &ctx);
    /*
    int i = 0;
    for (i = 0; i < 16; i < i++) //输出
    {
        printf("%02X", output[i]);
    }
    printf("\n");
    */
}

#include <openssl/aes.h> //AES-CBC加密
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
unsigned char* str2hex(char* str) {//注释1
    unsigned char* ret = NULL;
    int str_len = strlen(str);
    int i = 0;
    assert((str_len % 2) == 0);
    ret = (unsigned char*)malloc(str_len / 2);
    for (i = 0; i < str_len; i = i + 2) {
        sscanf(str + i, "%2hhx", &ret[i / 2]);
    }
    return ret;
}
unsigned char* padding_buf(unsigned char* buf, int size, int* final_size) {//注释2
    unsigned char* ret = NULL;
    int pidding_size = AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE);
    int i;
    *final_size = size + pidding_size;
    ret = (unsigned char*)malloc(size + pidding_size);
    memcpy(ret, buf, size);
    if (pidding_size != 0) {
        for (i = size; i < (size + pidding_size); i++) {
            ret[i] = 0;
        }
    }
    return ret;
}
void printf_buff(unsigned char* buff, int size) {
    int i = 0;
    for (i = 0; i < size; i++) {
        printf("%02X ", buff[i]);
        if ((i + 1) % 8 == 0) {
            printf("\n");
        }
    }
    printf("\n\n\n\n");
}
char s[300];
void encrpyt_buf(unsigned char* raw_buf, unsigned  char** encrpy_buf, int len) {
    AES_KEY aes;
    strcpy(s, "8cc72b05705d5c46f412af8cbed55aad");
    s[32] = '\0';
    unsigned char* key = str2hex(s);
    strcpy(s, "667b02a85c61c786def4521b060265e8");
    unsigned char* iv = str2hex(s);
    AES_set_encrypt_key(key, 128, &aes);//注释3
    AES_cbc_encrypt(raw_buf, *encrpy_buf, len, &aes, iv, AES_ENCRYPT);
    free(key);
    free(iv);
}
void decrpyt_buf(unsigned char* raw_buf, unsigned char** encrpy_buf, int len) {
    AES_KEY aes;
    strcpy(s, "8cc72b05705d5c46f412af8cbed55aad");
    unsigned char* key = str2hex(s);
    strcpy(s, "667b02a85c61c786def4521b060265e8");
    unsigned char* iv = str2hex(s);
    AES_set_decrypt_key(key, 128, &aes);
    AES_cbc_encrypt(raw_buf, *encrpy_buf, len, &aes, iv, AES_DECRYPT);
    free(key);
    free(iv);
}
int main(int argn, char* argv[]) {
    unsigned char* raw_buf = NULL;
    unsigned char* after_padding_buf = NULL;
    int padding_size = 0;
    unsigned char* encrypt_buf = NULL;
    unsigned char* decrypt_buf = NULL;
    // 1
    raw_buf = (unsigned char*)malloc(17);
    memcpy(raw_buf, "life's a struggle", 17);
    printf("------------------raw_buf\n");
    printf_buff(raw_buf, 17);
    // 2
    after_padding_buf = padding_buf(raw_buf, 17, &padding_size);
    printf("------------------after_padding_buf\n");
    printf_buff(after_padding_buf, padding_size);
    // 3
    encrypt_buf = (unsigned char*)malloc(padding_size);
    encrpyt_buf(after_padding_buf, &encrypt_buf, padding_size);
    printf("------------------encrypt_buf\n");
    printf_buff(encrypt_buf, padding_size);
    // 4
    decrypt_buf = (unsigned char*)malloc(padding_size);
    decrpyt_buf(encrypt_buf, &decrypt_buf, padding_size);
    printf("------------------decrypt_buf\n");
    printf_buff(decrypt_buf, padding_size);
    free(raw_buf);
    free(after_padding_buf);
    free(encrypt_buf);
    free(decrypt_buf);
    return 0;
}

GMSSL

要点:GMSSL是Openssl的国密算法扩展分支,可以在官方github上直接下载源码包并编译安装,基本用法秉承openSSL。

安装:32位版GmSSL度娘网盘提取码xcrp

环境:
为方便统一使用,此处我将主要文件集中在一起,记为Envior文件夹

  1. 将安装路径(GmSSL)中的include\openssl文件夹整个复制到Envior

  2. 将安装路径(GmSSL)中的lib文件夹复制到Envior

  3. 包含头文件

    属性–C/C+±-常规–附加包含目录(添加目录Envior)

  4. 项目包含.lib文件所在的目录:

    属性–链接器–常规–附加库目录(添加目录Envior\lib)

  5. 项目包含.lib文件

    属性–链接器–输入–附加依赖项(libcrypto.lib;libssl.lib;ws2_32.lib)

使用:
官方文档

#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>

int main(int arc, char* argv[])
{
	/* Load the human readable error strings for libcrypto */
	ERR_load_crypto_strings();

	/* Load all digest and cipher algorithms */
	OpenSSL_add_all_algorithms();

	/* Load config file, and other important initialisation */
	OPENSSL_config(NULL);

	/* ... Do some crypto stuff here ... */

	/* Clean up */

	/* Removes all digests and ciphers */
	EVP_cleanup();

	/* if you omit the next, a small leak may be left when you make use of the BIO (low level API) for e.g. base64 transformations */
	CRYPTO_cleanup_all_ex_data();

	/* Remove error strings */
	ERR_free_strings();

	return 0;
}

USBKEY(CSP接口)

使用飞天诚信的ePass2000Auto

要点:

  1. CSP API是微软规定的一系列函数接口,而UsbKey设备则提供了这些接口的实现。
  2. ePass2000Auto作为一个UsbKey设备,作用为安全地存储数字证书及公私钥对,同时其库(e2acsp11.lib)及中间件(安装程序为eP2Kauto.exe)中实现了CSP接口的一系列函数,通过这些函数便可完成读取证书、加解密等操作了。
  3. 函数文档为ePass2000Auto_Developer_Guide_C.pdf中的CSP相关部分,示例程序位于PKI/Samples/CryptoAPI中。
  4. 所有操作从函数CryptAcquireContext开始,它用于初始化上下文并寻找CSP环境。
BOOLEAN CryptAcquireContext
(  HCRYPTPROV *phProv, //[out]所获取的csp的句柄
   LPCTSTR pszContainer, //[in]指定在所要寻找的CSP中所寻找的密钥容器的名字
   LPCTSTR pszProvider, //[in]指定所寻找的CSP的名字
   DWORD   dwProvType, //[in]请求的CSP的类型
   DWORD  dwFlags) //[in]标记请求的CSP的用途

安装:

  1. 中间件安装程序PKI\Redist\eP2Kauto.exe是双击后自动安装的,没有弹窗。安装位置位于C:\Program Files (x86)\EnterSafe,呈现为一个证书管理工具。
  2. UsbKey管理器是直接双击启动的,管理员管理工具:PKI\Utilities\mgr2kAutoAdm.exe

环境:

  1. 包含头文件

    属性–C/C+±-常规–附加包含目录(添加目录PKI\Include)

  2. 项目包含.lib文件所在的目录:

    属性–链接器–常规–附加库目录(添加目录PKI\Lib)

  3. 项目包含.lib文件

    属性–链接器–输入–附加依赖项(crypt32.lib;e2acsp11.lib)

  4. 忽略特定默认库

    属性–链接器–输入–忽略特定默认库(libcmt.lib)

  5. 其它仍出错的,则仿照示例程序EnumCerts配置

 类似资料: