openssl的使用(c/c++)_openssl 使用 c++ pkcs7-程序员宅基地

技术标签: c语言  html5  linux  开源工具  

目录

环境部署

一、openssl RSA加解密、 使用接口生成秘钥

2、使用openssl对文件进行签名认证

3、aes加解密



环境部署

关于openssl的部署比较简单,在之前wifi功能移植中有过说明,或者网上大把详细步骤

一、openssl RSA加解密、 使用接口生成秘钥

命令行的方式生成证书: https://blog.csdn.net/gengxiaoming7/article/details/78505107
参考文章:https://blog.csdn.net/qq_30667875/article/details/105427943

我的具体实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <fstream>

using namespace std;

#define LOG_INFO(fmt,args...)   ({printf("info: %s(%d) %s:",__FILE__, __LINE__, __func__);printf(fmt"\r\n" ,##args);})
#define LOG_ERROR(fmt,args...)   ({printf("error: %s(%d) %s:",__FILE__, __LINE__, __func__);printf(fmt"\r\n" ,##args);})


#define RSA_OPENSSLKEY "./rsa_private_key.pem"
#define RSA_PUBLICKEY "./rsa_public_key.pem"

#define KEY_LENGTH  2048 

//生成秘钥
void GenerateRSAKey(std::string & out_pub_key, std::string & out_pri_key);

//传入秘钥内容进行加解密
std::string RsaPriEncrypt(const std::string &clear_text, std::string &pri_key);
std::string RsaPubDecrypt(const std::string & cipher_text, const std::string & pub_key);


//通过读秘钥文件的方式进行加解密
std::string RsaPriEncryptFile(const std::string &clear_text);
std::string RsaPubDecryptFile(const std::string & cipher_text);


int main(int argc, char* argv[])
{
		char *p_str="qaq1234567abcdef";

		std::string encrypt_text;
		std::string decrypt_text;
		
		std::string encryptFile_text;
		std::string decryptFile_text;

		std::string pub_key;
		std::string pri_key;
		GenerateRSAKey(pub_key, pri_key);
		LOG_INFO("public key:\n");
		LOG_INFO("%s\n", pub_key.c_str());
		LOG_INFO("private key:\n");
		LOG_INFO("%s\n", pri_key.c_str());


		// 直接使用秘钥信息的方式加解密
		// 私钥加密-公钥解密
		encrypt_text = RsaPriEncrypt(p_str, pri_key);
		LOG_INFO("encrypt: len=%d\n", encrypt_text.length());
		LOG_INFO("decrypt: %s\n", encrypt_text.c_str());
		decrypt_text = RsaPubDecrypt(encrypt_text, pub_key);
		LOG_INFO("decrypt: len=%d\n", decrypt_text.length());
		LOG_INFO("decrypt: %s\n", decrypt_text.c_str());

		printf("==================================\n");
		
		// 通过读秘钥文件的方式加解密
		encryptFile_text = RsaPriEncryptFile(p_str);
		LOG_INFO("encrypt: len=%d\n", encryptFile_text.length());
		LOG_INFO("encrypt: %s\n", encryptFile_text.c_str());
		decryptFile_text = RsaPubDecryptFile(encryptFile_text);
		LOG_INFO("decrypt: len=%d\n", decryptFile_text.length());
		LOG_INFO("decrypt: %s\n", decryptFile_text.c_str());



		return 0;
}

void GenerateRSAKey(std::string & out_pub_key, std::string & out_pri_key)
{
		size_t pri_len = 0; // 私钥长度
		size_t pub_len = 0; // 公钥长度
		char *pri_key = nullptr; // 私钥
		char *pub_key = nullptr; // 公钥

		// 生成密钥对
		RSA *keypair = RSA_generate_key(KEY_LENGTH, RSA_3, NULL, NULL);

		BIO *pri = BIO_new(BIO_s_mem());
		BIO *pub = BIO_new(BIO_s_mem());

		// 生成私钥
		PEM_write_bio_RSAPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
		// 注意------生成第1种格式的公钥
		//PEM_write_bio_RSAPublicKey(pub, keypair);
		// 注意------生成第2种格式的公钥(此处代码中使用这种)
		PEM_write_bio_RSA_PUBKEY(pub, keypair);

		// 获取长度  
		pri_len = BIO_pending(pri);
		pub_len = BIO_pending(pub);

		// 密钥对读取到字符串  
		pri_key = (char *)malloc(pri_len + 1);
		pub_key = (char *)malloc(pub_len + 1);

		BIO_read(pri, pri_key, pri_len);
		BIO_read(pub, pub_key, pub_len);

		pri_key[pri_len] = '\0';
		pub_key[pub_len] = '\0';

		out_pub_key = pub_key;
		out_pri_key = pri_key;

		// 将公钥写入文件
		std::ofstream pub_file(RSA_PUBLICKEY, std::ios::out);
		if (!pub_file.is_open())
		{
				perror("pub key file open fail:");
                goto ERROR;
				return;
		}
		pub_file << pub_key;
		pub_file.close();

		// 将私钥写入文件
		std::ofstream pri_file(RSA_OPENSSLKEY, std::ios::out);
		if (!pri_file.is_open())
		{
				perror("pri key file open fail:");
                goto ERROR;
				return;
		}
		pri_file << pri_key;
		pri_file.close();

ERROR:
		// 释放内存
		RSA_free(keypair);
		BIO_free_all(pub);
		BIO_free_all(pri);

		free(pri_key);
		free(pub_key);
}

std::string RsaPriEncrypt(const std::string &clear_text, std::string &pri_key)
{
		std::string encrypt_text;
		BIO *keybio = BIO_new_mem_buf((unsigned char *)pri_key.c_str(), -1);
		RSA* rsa = RSA_new();
		rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
		if (!rsa)
		{
				BIO_free_all(keybio);
				return std::string("");
		}

		// 获取RSA单次可以处理的数据的最大长度
		int len = RSA_size(rsa);

		// 申请内存:存贮加密后的密文数据
		char *text = new char[len + 1];
		memset(text, 0, len + 1);

		// 对数据进行私钥加密(返回值是加密后数据的长度)
		int ret = RSA_private_encrypt(clear_text.length(), (const unsigned char*)clear_text.c_str(), (unsigned char*)text, rsa, RSA_PKCS1_PADDING);
		if (ret >= 0) {
				encrypt_text = std::string(text, ret);
		}

		// 释放内存  
		delete text;
		BIO_free_all(keybio);
		RSA_free(rsa);

		return encrypt_text;
}

std::string RsaPubDecrypt(const std::string & cipher_text, const std::string & pub_key)
{
		std::string decrypt_text;
		BIO *keybio = BIO_new_mem_buf((unsigned char *)pub_key.c_str(), -1);
		RSA *rsa = RSA_new();

		// 注意--------使用第1种格式的公钥进行解密
		//rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);
		// 注意--------使用第2种格式的公钥进行解密(我们使用这种格式作为示例)
		rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
		if (!rsa)
		{
				unsigned long err = ERR_get_error(); //获取错误号
				char err_msg[1024] = { 0 };
				ERR_error_string(err, err_msg); // 格式:error:errId:库:函数:原因
				printf("err msg: err:%ld, msg:%s\n", err, err_msg);
				BIO_free_all(keybio);
				return decrypt_text;
		}

		int len = RSA_size(rsa);
		char *text = new char[len + 1];
		memset(text, 0, len + 1);
		// 对密文进行解密
		int ret = RSA_public_decrypt(cipher_text.length(), (const unsigned char*)cipher_text.c_str(), (unsigned char*)text, rsa, RSA_PKCS1_PADDING);
		if (ret >= 0) {
				decrypt_text.append(std::string(text, ret));
		}

		// 释放内存  
		delete text;
		BIO_free_all(keybio);
		RSA_free(rsa);

		return decrypt_text;
}

std::string RsaPriEncryptFile(const std::string &clear_text)
{
	std::string encrypt_text;
	RSA *prikey = RSA_new();
	BIO *priio;
	
	priio = BIO_new_file(RSA_OPENSSLKEY, "rb");
    prikey = PEM_read_bio_RSAPrivateKey(priio, &prikey, NULL, NULL);
	if (!prikey)
	{
		BIO_free(priio);
		return std::string("");
	}
	int len = RSA_size(prikey);
	char *text = new char[len + 1];
	memset(text, 0, len + 1);
	
	int ret = RSA_private_encrypt(clear_text.length(), (const unsigned char*)clear_text.c_str(), (unsigned char*)text, prikey, RSA_PKCS1_PADDING);
	if (ret >= 0) {
		encrypt_text = std::string(text, ret);
	}
	delete text;
	RSA_free(prikey);
    BIO_free(priio);
	
	return encrypt_text;
}

std::string RsaPubDecryptFile(const std::string & cipher_text)
{
	std::string decrypt_text;
	RSA *pubkey = RSA_new();
	BIO *pubio;
	pubio = BIO_new_file(RSA_PUBLICKEY, "rb");
    pubkey = PEM_read_bio_RSA_PUBKEY(pubio, &pubkey, NULL, NULL);
	if (!pubkey)
	{
		unsigned long err = ERR_get_error(); //获取错误号
		char err_msg[1024] = { 0 };
		ERR_error_string(err, err_msg); // 格式:error:errId:库:函数:原因
		printf("err msg: err:%ld, msg:%s\n", err, err_msg);
		BIO_free(pubio);
		return decrypt_text;
	}
	
	int len = RSA_size(pubkey);
	char *text = new char[len + 1];
	memset(text, 0, len + 1);
	
	int ret = RSA_public_decrypt(cipher_text.length(), (const unsigned char*)cipher_text.c_str(), (unsigned char*)text, pubkey, RSA_PKCS1_PADDING);
	if (ret >= 0) {
		decrypt_text.append(std::string(text, ret));
	}
	
	delete text;
	RSA_free(pubkey);
    BIO_free(pubio);
	
	return decrypt_text;
}

记得编译时加上 -lssl -lcrypto

2、使用openssl对文件进行签名认证

命令行方式:

message.sign:签名文件

source_ile:目标文件

sha1:摘要算法 使用openssl dgst - 可以看到支持的列表


使用私钥对升级包进行签名
openssl dgst -sha1 -out message.sign -sign rsa_private_key.pem source_file

使用公钥验证签名
openssl dgst -sha1 -verify rsa_public_key.pem -signature message.sign source_file

代码实现

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>

#define  SIGN_PATH			"./.message.sign"  //签名文件
#define  SOURCE_PATH		"./source_file"    //源文件

#define PUBLIC_KEY_PASH		"./pub_key.pem"    //公钥

static EVP_PKEY *PEM_read_PublicKey(FILE *fp)
{
	BIO *b;
	EVP_PKEY *ret;

	if ((b = BIO_new(BIO_s_file())) == NULL)
	{
		//PEMerr(PEM_F_PEM_READ_PRIVATEKEY, ERR_R_BUF_LIB);
		return(0);
	}
	BIO_set_fp(b, fp, BIO_NOCLOSE);
	ret = PEM_read_bio_PUBKEY(b, NULL, NULL, NULL);
	BIO_free(b);
	return(ret);
}

static EVP_PKEY* Read_PublicKey(char* p_KeyPath)
{
	FILE *fp = NULL;
	char szKeyPath[1024];
	EVP_PKEY *pubRsa = NULL;

	/*	打开密钥文件 */
	if (NULL == (fp = fopen(p_KeyPath, "r")))
	{
		return NULL;
	}
	/*	获取私密钥 */
	pubRsa = PEM_read_PublicKey(fp);
	if (NULL == pubRsa)
	{
		fclose(fp);
		return NULL;
	}
	fclose(fp);

	return pubRsa;
}

int VerifyUpgrade(char *sign_data, int sign_len)
{
	printf("sign_len = %d\n", sign_len);
	
	int nRet = 0;
	EVP_PKEY *pKey;
	EVP_MD_CTX* pMdCtx = NULL;
	EVP_PKEY_CTX* pKeyCtx = NULL;
	
	/*初始化验签函数*/
	pKey = Read_PublicKey(PUBLIC_KEY_PASH);
	if (!pKey)
	{
		printf("Read_PublicKey failed!\n");
		return -1;
	}
	
	pMdCtx = EVP_MD_CTX_create();
	if (NULL == pMdCtx)
	{
		printf("EVP_MD_CTX_create failed!\n");
		EVP_PKEY_free(pKey);
		pKey = NULL;
		return -1;
	}

	nRet = EVP_DigestVerifyInit(pMdCtx, &pKeyCtx, EVP_sha256(), NULL, pKey);
	if (nRet <= 0)
	{
		printf("EVP_DigestVerifyInit failed!\n");
		EVP_PKEY_free(pKey);
		pKey = NULL;
		EVP_MD_CTX_destroy(pMdCtx);
		pMdCtx = NULL;
		return -1;
	}
	
	FILE *fp = NULL;
	char p_pBuf[512];
	fp = fopen(SOURCE_PATH, "r");
	while (feof(fp) == 0)
	{
		int i = fread(p_pBuf, 1, 512, fp);
		EVP_DigestVerifyUpdate(pMdCtx, p_pBuf, i);
	}

	
	/*验签*/
	nRet = EVP_DigestVerifyFinal(pMdCtx, (unsigned char *)sign_data, sign_len);
	if (nRet <= 0)
	{
		printf("EVP_DigestVerifyFinal failed !!! nRet = %d \n", nRet);
		EVP_PKEY_free(pKey);
		pKey = NULL;
		EVP_MD_CTX_destroy(pMdCtx);
		pMdCtx = NULL;
		fclose(fp);
		printf("========================= Verify Failed ========================\n");
		return -1;
	}
	fclose(fp);

	printf("========================= Verify Success ========================\n");
	
	return 0;
}

int main()
{
	int sign_len = 0;
	char *p_sign_data = NULL;

	struct stat statbuf;
	stat(SIGN_PATH, &statbuf);
	sign_len = statbuf.st_size;
	
	p_sign_data = (char *)malloc(sign_len);
	memset(p_sign_data, 0, sign_len);
	FILE *sign_fp = fopen(SIGN_PATH, "r");
	if (sign_fp)
	{
		fread(p_sign_data, 1, sign_len, sign_fp);
	}
	
	VerifyUpgrade(p_sign_data, sign_len);
	
	free(p_sign_data);
	
	return 0;
}

3、aes加解密

命令行方式:

1、ecb

echo -n "AA:BB:CC:11:22:33" | openssl enc -aes-128-ecb -K 78346c3932774542754d32656e345273 | xxd -p -c 64

AA:BB:CC:11:22:33 要加密的字符串

xxd让加密后的内容以十六进制的方式显示,方便查看

2、cbc

echo -n "test" | openssl enc -aes-128-cbc -K 69249e45dd8f1088c6ce8ec74b027035 -iv 69249e45dd8f1088c6ce8ec74b027035 | xxd

代码实现:(这里实现的是cbc,ecb大同小异)

命令行指定的key和iv是十六进制数,为了能跟命令行的输出结果一致,这里简单赋了一下值

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <openssl/evp.h>
#include <openssl/aes.h>


static unsigned char sAesIV[] = "69249e45dd8f1088c6ce8ec74b027035";
static unsigned char sAesKey[] = "69249e45dd8f1088c6ce8ec74b027035";

int AES_ENC(char *_InData, int InLen, char *OutData, int *OutLen)
{
	unsigned char key[16] = {}, iv[16] = { 0 };
	key[0] = 0x69;
	key[1] = 0x24;
	key[2] = 0x9e;
	key[3] = 0x45;
	key[4] = 0xdd;
	key[5] = 0x8f;
	key[6] = 0x10;
	key[7] = 0x88;
	key[8] = 0xc6;
	key[9] = 0xce;
	key[10] = 0x8e;
	key[11] = 0xc7;
	key[12] = 0x4b;
	key[13] = 0x02;
	key[14] = 0x70;
	key[15] = 0x35;
	
	iv[0] = 0x69;
	iv[1] = 0x24;
	iv[2] = 0x9e;
	iv[3] = 0x45;
	iv[4] = 0xdd;
	iv[5] = 0x8f;
	iv[6] = 0x10;
	iv[7] = 0x88;
	iv[8] = 0xc6;
	iv[9] = 0xce;
	iv[10] = 0x8e;
	iv[11] = 0xc7;
	iv[12] = 0x4b;
	iv[13] = 0x02;
	iv[14] = 0x70;
	iv[15] = 0x35;
	
	
	EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
	EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, 1);
	
	int len = 0;
	EVP_CipherUpdate(ctx, (unsigned char*)OutData, &len, (unsigned char*)_InData, InLen);
	*OutLen = len;
	EVP_CipherFinal_ex(ctx, (unsigned char*)OutData + len, &len);
	*OutLen += len;
	EVP_CIPHER_CTX_free(ctx);
	
	return 0;
}

int AES_DEC(char *_InData, int InLen, char *OutData, int *OutLen)
{
	unsigned char key[16] = {}, iv[16] = { 0 };
	key[0] = 0x69;
	key[1] = 0x24;
	key[2] = 0x9e;
	key[3] = 0x45;
	key[4] = 0xdd;
	key[5] = 0x8f;
	key[6] = 0x10;
	key[7] = 0x88;
	key[8] = 0xc6;
	key[9] = 0xce;
	key[10] = 0x8e;
	key[11] = 0xc7;
	key[12] = 0x4b;
	key[13] = 0x02;
	key[14] = 0x70;
	key[15] = 0x35;
	
	iv[0] = 0x69;
	iv[1] = 0x24;
	iv[2] = 0x9e;
	iv[3] = 0x45;
	iv[4] = 0xdd;
	iv[5] = 0x8f;
	iv[6] = 0x10;
	iv[7] = 0x88;
	iv[8] = 0xc6;
	iv[9] = 0xce;
	iv[10] = 0x8e;
	iv[11] = 0xc7;
	iv[12] = 0x4b;
	iv[13] = 0x02;
	iv[14] = 0x70;
	iv[15] = 0x35;
	
	EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
	EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, 0);
	
	int len = 0;
	EVP_CipherUpdate(ctx, (unsigned char*)OutData, &len, (unsigned char*)_InData, InLen);
	*OutLen = len;
	EVP_CipherFinal_ex(ctx, (unsigned char*)OutData + len, &len);
	*OutLen += len;
	EVP_CIPHER_CTX_free(ctx);
	
	return 0;
	
}

int main()
{
	char Source[128] = "test";
	char EncData[128] = {};
	char DecData[128] = {};
	int EncLen = 0;
	int DecLen = 0;
	
	AES_ENC(Source, (int)strlen(Source), EncData, &EncLen);
	for (int i = 0; i < EncLen; ++i)
		printf("%02x ", EncData[i]);
	printf("\n");
	
	AES_DEC(EncData, (int)strlen(EncData), DecData, &DecLen);
	for (int i = 0; i < DecLen; ++i)
		printf("%x ", DecData[i]);
	printf("\n");
	
	return 0;
}

注意:

openssl默认是PKCS7填充的数据,AES-128AES-192AES-256 的数据块长度分别为 128/8=16bytes192/8=24bytes256/8=32bytes。

当我们拿到一串PKCS7填充的数据时,取其最后一个字符paddingChar,此字符的ASCII码的十进制ord(paddingChar)即为填充的数据长度paddingSize,读取真实数据时去掉填充长度即可得到原始的数据

命令行输出结果

 代码输出结果

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_59665492/article/details/121624813

智能推荐

数学建模--三维图像绘制的Python实现_python画三维立体图-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏22次。数学建模--三维图像绘制的Python实现_python画三维立体图

ESP32-网络开发实例-扫描可用WiFi网络及WiFi信号强度检测_esp32 wifi信号强度-程序员宅基地

文章浏览阅读3.5k次。扫描可用WiFi网络及WiFi信号强度检测NodeMCU-32S 最强的ESP32 开发板非盗版或副厂的CH340 WiFi 蓝牙ESP-32 可用Arduino IDEESP32-S 是一款通用型WiFi-BT-BLE MCU模组,功能强大,用途广泛,可以用于低功耗传感器网络和要求极高的任务,例如语音编码、音频流和MP3解码等。此款模组的核心是ESP32芯片,具有可扩展、自适应的特点。两个CPU核可以被单独控制或上电。时钟频率的调节范围为80 MHz到240 MHz。用户可以切断CPU的电源,利用低_esp32 wifi信号强度

STM32片上外设时钟使能、失能和复位的区别-程序员宅基地

文章浏览阅读4.1k次,点赞5次,收藏28次。置顶/星标公众号,不错过每一条消息! 今天分享的关于时钟知识,可能很多人没有在意过。这也是之前有朋友问过的问题,这里就简单给大家普及一下吧。1RCC时钟说明在STM..._时钟复位和时钟使能

最强下载器idm_idm_v6.38.7.2-程序员宅基地

文章浏览阅读1.5k次,点赞3次,收藏6次。下载:IDM v6.38.7.2 中文绿色特别版https://eli08.118pan.com/b1064872密码:ye79下载: IDM 6.39.7.3https://eli08.118pan.com/b1064872密码:ye79下载好后先点击绿化,然后在点击后缀exe文件进入软件后设置一下这里要改为:softxm;netdisk这里最好设置为4这要就差不多了..._idm_v6.38.7.2

JetBrains产品字体大小调整_jetbrains字体大小设置-程序员宅基地

文章浏览阅读894次。JetBrains产品字体大小调整,如:IDEA,Pycharm的字体大小调整_jetbrains字体大小设置

随便推点

高通安卓Q显示屏不同角度旋转竖屏横屏切换_高通副屏旋转-程序员宅基地

文章浏览阅读1.2k次,点赞3次,收藏12次。由于项目需要,使用了竖屏当横屏用,所以需要将系统显示旋转90度,我们目前平台是基于高通QCM6125安卓10.0系统。为了方便以后其他角度的旋转,添加了persist.panel.orientation 属性来控制角度。开机动画frameworks/base/cmds/bootanimation/BootAnimation.cpp@@ -279,11 +279,36 @@ status_t BootAnimation::readyToRun() { if (status) _高通副屏旋转

鸿蒙系统电视能装APP吗,简单一招,无师自通!教你在智能电视上安装第三方APP软件!...-程序员宅基地

文章浏览阅读4.6k次。如今智能电视也能使用大部分手机APP,但不少电视自带的应用商城是搜索不到你想要的APP的,这时候必须通过“特殊手段”才能达到目的,这篇文章笔点酷玩不罗嗦,给大家介绍非常简单的一招,在99%的智能电视系统上都能成功实现安装第三方APP的目的!这个办法的第一个难点在于手机与电视互联,简单讲只需手机下载一个第三方软件,名字叫做“悟空遥控器”,这个APP已经出品多年,其他相关功能的APP都没有它好用,它的..._鸿蒙电视怎么下载app

reportng之测试报告升级美化-程序员宅基地

文章浏览阅读120次。背景:偶然看到一个人的自动化框架的测试报告好漂亮,心痒痒,今天弄了一下午,还是不行,结果到现在就现在,我特么成功了,不为什么Mark一下:本地化修改获取源码,修改reportng.properties文件,reportng.properties中的内容是键值对,修改后面的值为中文即可。其他视情况做改变。passed=通过修改测试结果顺序需要修改TestResultCompa..._reportng测试报告美化

学友来函001:移动开发前景如何?_移动开发前景csdn-程序员宅基地

文章浏览阅读6.9k次。乐知学堂学友来函系列为学员们提出的典型热点问题,我们的教师和学习顾问都给出了精心的回答,乐知学堂会定期发布学友来函,希望能够为更多的学习者解除学习中的困惑。———————————————————————————————————————————————————————学员:徐豫锋 时间:2008-11-29 随着手机的普及,利用手机移动上网已经越来越普及,应用也越来越多。问_移动开发前景csdn

基于深度正则化的少镜头图像三维高斯溅射优化-程序员宅基地

文章浏览阅读696次,点赞20次,收藏23次。In this paper, we present a method to optimize Gaussian splatting with a limited number of images while avoiding overfitting. Representing a 3D scene by combining numerous Gaussian splats has yielded outstanding visual quality. However, it tends to overfit

Pulsar 2.4 CentOS 7.3 安装及使用_pulsar 2.4.2架包支持服务版本-程序员宅基地

文章浏览阅读1.1k次。下载安装包http://pulsar.apache.org/en/download/使用tar -zxvf解压下载的资源包,目录结构如下显示目录:本地单点运行,使用命令./pulsar standalone即可,这里使用默认配置,暴露端口为6650测试消息发送消息 命令./pulsar-client produce my-topic --messages ..._pulsar 2.4.2架包支持服务版本

推荐文章

热门文章

相关标签