Conan客户端简单使用示例

Posted fengbingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Conan客户端简单使用示例相关的知识,希望对你有一定的参考价值。

      在https://blog.csdn.net/fengbingchun/article/details/118443862 中对Conan进行了简单介绍,这里调用openssl的接口,写一个简单的test来说明Conan的使用步骤:

      (1).首先添加一个conanfile.txt文件,内容如下:依赖项为openssl最新版1.1.1k

[requires]
openssl/1.1.1k

[generators]
cmake

      (2).依次执行如下命令:

mkdir build
cd build
~/Disk/anaconda3/envs/test_conan/bin/conan install .. -s arch=x86_64 -s compiler=gcc -s compiler.libcxx=libstdc++ -s compiler.version=4.9 -s os=Linux --build=missing

  执行结果如下图所示:openssl生成的库和头文件会存放在~/.conan/data/openssl/1.1.1k/_/_/package/93fdb97b4b95d2b3f87d615ef63cbbfa72870a99目录下。

    在当前build目录下还会生成conanbuildinfo.cmake、conanbuildinfo.txt、conaninfo.txt、 conan.lock、graph_info.json 5个文件:

      conanbuildinfo.cmake:定义了一些宏和变量,指定openssl库和头文件的所在路径等信息,此文件需要在主CMakeLists.txt中被include。

      conanbuildinfo.txt:指定openssl库、头文件、可执行文件所在路径等信息。

      conaninfo.txt:指定编译openssl时的配置信息,及哪些openssl选项是开启的。

      conan.lock:与connaninfo.txt内容类似。

      graph_info.json:与connaninfo.txt内容类似,指示哪些openssl选项是开启的。

      (3).main.cpp文件内容如下:参考https://blog.csdn.net/fengbingchun/article/details/106113185 ,使用对称加密算法AES对字符串进行加解密

#include <string.h>
#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include <openssl/des.h>
#include <openssl/rc4.h>
#include <openssl/md5.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/aes.h>
#include <openssl/hmac.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>

namespace {

static const unsigned char gcm_key[] = { // 32 bytes, Key
	0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,
	0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
	0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
};

static const unsigned char gcm_iv[] = { // 12 bytes, IV(Initialisation Vector)
	0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84
};

// Additional Authenticated Data(AAD): it is not encrypted, and is typically passed to the recipient in plaintext along with the ciphertext
static const unsigned char gcm_aad[] = { // 16 bytes
	0x4d, 0x23, 0xc3, 0xce, 0xc3, 0x34, 0xb4, 0x9b, 0xdb, 0x37, 0x0c, 0x43,
	0x7f, 0xec, 0x78, 0xde
};

std::unique_ptr<unsigned char[]> aes_gcm_encrypt(const char* plaintext, int& length, unsigned char* tag)
{
	EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
	// Set cipher type and mode
	EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);
	// Set IV length if default 96 bits is not appropriate
	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), nullptr);
	// Initialise key and IV
	EVP_EncryptInit_ex(ctx, nullptr, nullptr, gcm_key, gcm_iv);
	// Zero or more calls to specify any AAD
	int outlen;
	EVP_EncryptUpdate(ctx, nullptr, &outlen, gcm_aad, sizeof(gcm_aad));
	unsigned char outbuf[1024];
	// Encrypt plaintext
	EVP_EncryptUpdate(ctx, outbuf, &outlen, (const unsigned char*)plaintext, strlen(plaintext));
	length = outlen;
	std::unique_ptr<unsigned char[]> ciphertext(new unsigned char[length]);
	memcpy(ciphertext.get(), outbuf, length);
	// Finalise: note get no output for GCM
	EVP_EncryptFinal_ex(ctx, outbuf, &outlen);
	// Get tag
	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outbuf);
	memcpy(tag, outbuf, 16);
	// Clean up
	EVP_CIPHER_CTX_free(ctx);
	return ciphertext;
}

std::unique_ptr<unsigned char[]> aes_gcm_decrypt(const unsigned char* ciphertext, int& length, const unsigned char* tag)
{
	EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
	// Select cipher
	EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);
	// Set IV length, omit for 96 bits
	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), nullptr);
	// Specify key and IV
	EVP_DecryptInit_ex(ctx, nullptr, nullptr, gcm_key, gcm_iv);
	int outlen;
	// Zero or more calls to specify any AAD
	EVP_DecryptUpdate(ctx, nullptr, &outlen, gcm_aad, sizeof(gcm_aad));
	unsigned char outbuf[1024];
	// Decrypt plaintext
	EVP_DecryptUpdate(ctx, outbuf, &outlen, ciphertext, length);
	// Output decrypted block
	length = outlen;
	std::unique_ptr<unsigned char[]> plaintext(new unsigned char[length]);
	memcpy(plaintext.get(), outbuf, length);
	// Set expected tag value
	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (void*)tag);
	// Finalise: note get no output for GCM
	int rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
	// Print out return value. If this is not successful authentication failed and plaintext is not trustworthy.
	fprintf(stdout, "Tag Verify %s\\n", rv > 0 ? "Successful!" : "Failed!");
	EVP_CIPHER_CTX_free(ctx);
	return plaintext;
}

} // namespace

int main()
{
	fprintf(stdout, "Start AES GCM 256 Encrypt:\\n");
	const char* plaintext = "1234567890ABCDEFG!@#$%^&*()_+[]{};':,.<>/?|";
	fprintf(stdout, "src plaintext: %s, length: %d\\n", plaintext, strlen(plaintext));
	int length = 0;
	std::unique_ptr<unsigned char[]> tag(new unsigned char[16]);
	std::unique_ptr<unsigned char[]> ciphertext = aes_gcm_encrypt(plaintext, length, tag.get());
	fprintf(stdout, "length: %d, ciphertext: ", length);
	for (int i = 0; i < length; ++i)
		fprintf(stdout, "%02x ", ciphertext.get()[i]);
	fprintf(stdout, "\\nTag: ");
	for (int i = 0; i < 16; ++i)
		fprintf(stdout, "%02x ", tag.get()[i]);
	fprintf(stdout, "\\n");

	fprintf(stdout, "\\nStart AES GCM 256 Decrypt:\\n");
	std::unique_ptr<unsigned char[]> result = aes_gcm_decrypt(ciphertext.get(), length, tag.get());
	fprintf(stdout, "length: %d, decrypted plaintext: ", length);
	for (int i = 0; i < length; ++i)
		fprintf(stdout, "%c", result.get()[i]);
	fprintf(stdout, "\\n");

	if (strncmp(plaintext, (const char*)result.get(), length) == 0) {
		fprintf(stdout, "decrypt success\\n");
		return 0;
	}

	fprintf(stderr, "decrypt fail\\n");
	return -1;
}

      (4).CMakeLists.txt文件内容如下:

cmake_minimum_required(VERSION 3.12)
project(test_openssl)

add_definitions("-std=c++11")

include(${CMAKE_CURRENT_SOURCE_DIR}/build/conanbuildinfo.cmake)
include_directories(${CONAN_INCLUDE_DIRS_OPENSSL})
link_directories(${CONAN_LIB_DIRS_OPENSSL})

add_executable(main main.cpp)
target_link_libraries(main ${CONAN_LIBS_OPENSSL})

      (5).依次执行如下命令:

cmake ..
make
./main

      执行结果如下图所示:

      GitHubhttps://github.com/fengbingchun/Linux_Code_Test

以上是关于Conan客户端简单使用示例的主要内容,如果未能解决你的问题,请参考以下文章

conan入门:conan 引用第三方库示例

conan入门:conan 交叉编译引用第三方库示例

在android中使用带有片段的roboguice的任何简单示例?

处理屏幕旋转上的片段重复(带有示例代码)

Node、Express、Ajax 和 Jade 示例

conan入门:conan 服务配置-密码管理及策略