OpenSSL 3.1.1 ECC 加密、解密、签名、验签(国密 sm2、sm3)

这篇具有很好参考价值的文章主要介绍了OpenSSL 3.1.1 ECC 加密、解密、签名、验签(国密 sm2、sm3)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

OpenSSL 3.1.1 ECC 加密、解密、签名、验签(国密 sm2、sm3)

openssl 3 默认废弃了 旧版本 (opessl 1.x) 的部分api 导致部分旧ecc 代码无法使用(可以通过配置编译选项打开)
,这里展示如何使用新接口用ECC 进行加密解密。

新接口是真的方便,基本上你都不需要懂啥密码学知识,对我们这种密码白痴来说太好了

头文件
生成密钥对
导出公钥&导入公钥
公钥加密
私钥解密
私钥签名
公钥验签
工具函数
所有代码(后来改过)

头文件

小小的封装了一下文章来源地址https://www.toymoban.com/news/detail-755046.html


#include "openssl/crypto.h"
#include "openssl/types.h"
#include "openssl/x509.h"
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/pem.h>


class sm2PrivateKey;

 struct EVP_CUNSTOM{
        EVP_PKEY * pkey=NULL;
        ~EVP_CUNSTOM(){
            if(pkey!=NULL){
                EVP_PKEY_free(pkey);
            }
        }
    };

class sm2PublicKey{
    public:
    sm2PublicKey()=default;

    sm2PublicKey(const sm2PublicKey & other){
        m_pkey=other.m_pkey;
    }

    sm2PublicKey(const std::string & pub_str);

    sm2PublicKey(const unsigned char * pub_str,size_t len);

    std::string Encrypt(const std::string  & message,std::string & error);
	
    bool SignatureVerification(const std::string & signature,const std::string & message,std::string & error);


    std::string GetPublicString();

    std::string GetPublicStringBase64();
private:
   
    std::shared_ptr<EVP_CUNSTOM> m_pkey=nullptr;//使用shared_ptr 防止拷贝构造的时候造成内存泄漏和意外释放
};


class sm2PrivateKey{
    public:

    sm2PrivateKey();

    sm2PrivateKey(const std::string & priv_str);

    sm2PublicKey CreatePublic();

    std::string Decrypt(const std::string & encoded,std::string & error);

    std::string Signature(const std::string & message ,std::string & error);

    std::string GetPrivateString();

private:

    std::shared_ptr<EVP_CUNSTOM>  M_PKEY=nullptr;
};

生成密钥对

sm2PrivateKey::sm2PrivateKey(){
    EVP_PKEY *ret = NULL;

    EVP_PKEY_CTX *pkctx = NULL;

    pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL);//创建sm2 上下文
    if(pkctx==NULL){
        errorL("EVP_PKEY_CTX_new_id");
        return;
    }
    int retV=1;
    retV=EVP_PKEY_keygen_init(pkctx);//初始化sm2 上下文

    if (retV <= 0) {
       errorL("EVP_PKEY_keygen_init:" << GetErrorStr());
       EVP_PKEY_CTX_free(pkctx);
       return ;
    }


    retV=EVP_PKEY_keygen(pkctx, &ret);//生成密钥对
     if (retV <= 0) {
        errorL("EVP_PKEY_keygen:" << GetErrorStr());
        EVP_PKEY_CTX_free(pkctx);
        return ;
    }
    EVP_CUNSTOM * cst=new EVP_CUNSTOM{ret};
    M_PKEY=std::shared_ptr<EVP_CUNSTOM>(cst);
    EVP_PKEY_CTX_free(pkctx);
}

导出公钥和导入公钥

sm2PublicKey sm2PrivateKey::CreatePublic(){
    unsigned char *buffer=nullptr;
    int retV=i2d_PUBKEY(M_PKEY.get()->pkey, &buffer);//导出
     if (retV <= 0) {
        errorL("i2d_PUBKEY:" <<GetErrorStr());
        return sm2PublicKey{};
    }
    //buffer 里的是公钥二进制
    sm2PublicKey pub(buffer,retV);
    //OPENSSL_free(buffer);
    return pub;
}

sm2PublicKey::sm2PublicKey(const unsigned char * pub_str,size_t len){
    EVP_PKEY * pkey_t=NULL;
    //pkey_t=d2i_PublicKey(EVP_PKEY_SM2,NULL, &pub_str, len);
    pkey_t=d2i_PUBKEY(NULL, &pub_str, len);//导入
    std::string error;
    if(pkey_t==NULL){
        error=GetErrorStr();
        errorL(error);
        return;
    }
    EVP_CUNSTOM *cst=new EVP_CUNSTOM{pkey_t};
    m_pkey=std::shared_ptr<EVP_CUNSTOM>(cst);
}

公钥加密

std::string sm2PublicKey::Encrypt(const std::string &message,std::string &error) {
    std::string encodedstr;
     EVP_PKEY_CTX *pkctx = NULL;
    int retV=1;
    if (!(pkctx = EVP_PKEY_CTX_new(m_pkey.get()->pkey, NULL))) {//生成上下文
        error=GetErrorStr();
        errorL("EVP_PKEY_CTX_new:" << error);
         EVP_PKEY_CTX_free(pkctx);
         return "";
    }
    retV=EVP_PKEY_encrypt_init(pkctx);//加密初始化
    if (retV <= 0) {
        error=GetErrorStr();
       errorL("EVP_PKEY_encrypt_init:" <<error);
        EVP_PKEY_CTX_free(pkctx);
        return "";
    }

    size_t outbuflen=0;
    unsigned char * outbuf=NULL;
    retV=EVP_PKEY_encrypt(pkctx, NULL, &outbuflen, 
    		(const unsigned char *)message.c_str(), message.size());//加密 (传NULL 仅获取密文长度)
    if (retV <= 0) {
        error=GetErrorStr();
        errorL("EVP_PKEY_encrypt:" << error  );
        EVP_PKEY_CTX_free(pkctx);
        return "";
    }
    if(outbuflen==0){
        errorL("EVP_PKEY_encrypt:" << "no memery");
        EVP_PKEY_CTX_free(pkctx);
        return "";
    }

    outbuf=new unsigned char[outbuflen];

    retV=EVP_PKEY_encrypt(pkctx, outbuf, &outbuflen,
    		 (const unsigned char *)message.c_str(), message.size());//加密
    if (retV <= 0) {
        error=GetErrorStr();
        errorL("EVP_PKEY_encrypt:" << error  );
        EVP_PKEY_CTX_free(pkctx);
        delete[] outbuf;
        return "";
    }
    encodedstr=std::string((const char *)outbuf,outbuflen);//获取结果
    delete[] outbuf;
    EVP_PKEY_CTX_free(pkctx);
    return encodedstr;
}

私钥解密

std::string sm2PrivateKey::Decrypt(const std::string &encoded,
                                   std::string &error) {
    std::string decodedstr;
    EVP_PKEY_CTX *pkctx = NULL;
    unsigned char * outbuf=NULL;
    size_t outlen=0;

    int retV = 1;
    if (!(pkctx = EVP_PKEY_CTX_new(M_PKEY.get()->pkey, NULL))) {//创建EVP 上下文
        error = GetErrorStr();
        errorL("EVP_PKEY_CTX_new:" << error);
        EVP_PKEY_CTX_free(pkctx);
        return "";
    }
    retV = EVP_PKEY_decrypt_init(pkctx);// 解密初始化
    if (retV <= 0) {
        error = GetErrorStr();
        errorL("EVP_PKEY_decrypt_init:" << error);
        EVP_PKEY_CTX_free(pkctx);
        return "";
    }
    retV=EVP_PKEY_decrypt(pkctx, NULL, &outlen, 
    	(const unsigned char *)encoded.c_str(), encoded.size());//解密
    if(retV<=0){
        error = GetErrorStr();
        errorL("EVP_PKEY_encrypt_init:" << error);
        EVP_PKEY_CTX_free(pkctx);
        return "";
    }

    if(outlen==0){
        errorL("EVP_PKEY_decrypt:" << error);
        EVP_PKEY_CTX_free(pkctx);
        return "";
    }

    outbuf=new unsigned char[outlen];

    retV=EVP_PKEY_decrypt(pkctx, outbuf, &outlen, 
    (const unsigned char *)encoded.c_str(), encoded.size());//解密
    if(retV<=0){
        error = GetErrorStr();
        errorL("EVP_PKEY_encrypt_init:" << error);
        EVP_PKEY_CTX_free(pkctx);
        delete[] outbuf;
        return "";
    }

    decodedstr=std::string((const char *)outbuf,outlen);
    delete[] outbuf;

    EVP_PKEY_CTX_free(pkctx);
    return decodedstr;
}

私钥签名

std::string sm2PrivateKey::Signature(const std::string & message ,std::string & error){
    std::string signatured;
    EVP_MD_CTX *mdctx = NULL;
    unsigned char * outbuf=NULL;
    size_t outbuflen=0;
    int retV=0;
    if(!(mdctx = EVP_MD_CTX_create())){//创建摘要上下文
        error=GetErrorStr();
        errorL("EVP_MD_CTX_create:" << error);
        return "";
    }
    retV=EVP_DigestSignInit(mdctx, NULL, EVP_sm3(),//使用sm3 摘要算法
    	 NULL, M_PKEY.get()->pkey);//签名初始化
     if (retV <= 0) {
        error = GetErrorStr();
        errorL("EVP_DigestSignInit:" << error);
        EVP_MD_CTX_free(mdctx);
        return "";
    }


    retV=EVP_DigestSignUpdate(mdctx, message.c_str(), message.size());//更新签名内容
    if (retV <= 0) {
        error = GetErrorStr();
        errorL("EVP_DigestSignUpdate:" << error);
        EVP_MD_CTX_free(mdctx);
        return "";
    }

     retV= EVP_DigestSignFinal(mdctx, NULL, &outbuflen);//获取签名长度
     if (retV <= 0) {
        error = GetErrorStr();
        errorL("EVP_DigestSignFinal:" << error);
        EVP_MD_CTX_free(mdctx);
        return "";
    }

    outbuf=new unsigned char[outbuflen];

    retV= EVP_DigestSignFinal(mdctx, outbuf, &outbuflen);//获取签名结果
     if (retV <= 0) {
        error = GetErrorStr();
        errorL("EVP_DigestSignFinal:" << error);
        EVP_MD_CTX_free(mdctx);
        return "";
    }

    signatured=std::string((const char *)outbuf,outbuflen);
    delete[] outbuf;
    return signatured;
}

公钥验签

bool sm2PublicKey::SignatureVerification(const std::string &signature, const std::string &message, std::string &error){
    std::string signatured;
    EVP_MD_CTX *mdctx = NULL;
    int retV=0;
    if(!(mdctx = EVP_MD_CTX_create())){//创建摘要上下文
        error=GetErrorStr();
        errorL("EVP_MD_CTX_create:" << error);
        return false;
    }
    retV=EVP_DigestVerifyInit(mdctx, NULL, EVP_sm3(), NULL, m_pkey.get()->pkey);//验签初始化
    if(retV <=0){
        error=GetErrorStr();
        errorL("EVP_DigestVerifyInit:" << error);
        EVP_MD_CTX_free(mdctx);
        return false;
    }

    retV=EVP_DigestVerifyUpdate(mdctx, message.c_str() , message.size());//更新验签内容
     if(retV <=0){
        error=GetErrorStr();
        EVP_MD_CTX_free(mdctx);
        errorL("EVP_DigestVerifyUpdate:" << error);
        return false;
    }
    retV=EVP_DigestVerifyFinal(mdctx, (const unsigned char *)signature.c_str(), signature.size());//验证签名
     if(retV <=0){
        error=GetErrorStr();
        EVP_MD_CTX_free(mdctx);
        errorL("EVP_DigestVerifyFinal:" << error);
        return false;
    }
    EVP_MD_CTX_free(mdctx);
    return true;
}

工具函数


#define RED_t "\033[31m"
#define YELLOW_t "\033[33m"
#define GREEN_t "\033[32m"
#define WRITE "\033[0m"

#define errorL(msg) \
	std::cout << RED_t <<"Error:["<< __FILE__  << ":"<< __LINE__ << "]:"<< msg << WRITE <<std::endl;
#define debugL(msg) \
	std::cout << YELLOW_t <<"debug:["<< __FILE__ << ":"<< __LINE__ << "]:"<< msg << WRITE << std::endl;
#define infoL(msg) \
	std::cout << GREEN_t <<"infor:["<< __FILE__ << ":" << __LINE__ << "]:"<< msg << WRITE << std::endl;


std::string GetErrorStr(){
    unsigned long er=0;

    char erbuf[512]={0};
    
    size_t erlen=512;

    er=ERR_get_error();
    ERR_error_string_n(er,erbuf,erlen);
    return std::string(erbuf,erlen);
}

所有代码

// ssl.h
#include <openssl/types.h>
#include <cstddef>
#include <memory>
#ifndef _MY_SSL_
#include <openssl/evp.h>
#include <string>
class sm2PrivateKey;

struct EVP_CUNSTOM {
	EVP_PKEY* pkey = NULL;
	~EVP_CUNSTOM() {
		if (pkey != NULL) {
			EVP_PKEY_free(pkey);
		}
	}
};

class sm2PublicKey {
public:
	sm2PublicKey() = default;

	sm2PublicKey(const sm2PublicKey& other) {
		m_pkey = other.m_pkey;
	}

	sm2PublicKey(const std::string& pub_str);

	sm2PublicKey(const unsigned char* pub_str, size_t len);

	std::string Encrypt(const std::string& message, std::string& error);

	bool SignatureVerification32(const std::string& signature, const std::string& message, std::string& error);

	bool SignatureVerification(const std::string& signature, const std::string& message, std::string& error);


	std::string GetPublicString();
private:

	std::shared_ptr<EVP_CUNSTOM> m_pkey = nullptr;
};


class sm2PrivateKey {
public:

	sm2PrivateKey();

	

	static sm2PrivateKey CreateWithPEM(const std::string& pem);

	sm2PublicKey CreatePublic();

	std::string GetPEM();

	std::string Decrypt(const std::string& encoded, std::string& error);

	std::string Signature32(const std::string& message, std::string& error);

	std::string Signature(const std::string& message, std::string& error);
private:
	sm2PrivateKey(EVP_CUNSTOM* st) {
		if (st == nullptr) {
			return;
		}
		M_PKEY = std::shared_ptr<EVP_CUNSTOM>(st);
	}
	std::shared_ptr<EVP_CUNSTOM>  M_PKEY = nullptr;


};


//ssl.cpp




#include "ssl.h"
#include <openssl/crypto.h>
#include <openssl/types.h>
#include <openssl/x509.h>
#include <cstddef>
#include <cstring>
#include "debug.h"
#include <memory>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <string>

std::string GetErrorStr() {
	unsigned long er = 0;

	char erbuf[512] = { 0 };

	size_t erlen = 512;

	er = ERR_get_error();
	ERR_error_string_n(er, erbuf, erlen);
	return std::string(erbuf, erlen);
}

sm2PublicKey::sm2PublicKey(const unsigned char* pub_str, size_t len) {
	EVP_PKEY* pkey_t = NULL;
	pkey_t = d2i_PUBKEY(NULL, &pub_str, len);
	std::string error;
	if (pkey_t == NULL) {
		error = GetErrorStr();
		errorL(error);
		return;
	}
	EVP_CUNSTOM* cst = new EVP_CUNSTOM{ pkey_t };
	m_pkey = std::shared_ptr<EVP_CUNSTOM>(cst);
}

sm2PublicKey::sm2PublicKey(const std::string& pub_str) {
	EVP_PKEY* pkey_t = NULL;
	unsigned char* c_str = new unsigned char[pub_str.size()];
	memcpy(c_str, (const void*)pub_str.c_str(), pub_str.size());
	pkey_t = d2i_PUBKEY(NULL, (const unsigned char**)&c_str, pub_str.size());
	std::string error;
	if (pkey_t == NULL) {
		error = GetErrorStr();
		errorL(error);
		return;
	}
	EVP_CUNSTOM* cst = new EVP_CUNSTOM{ pkey_t };
	m_pkey = std::shared_ptr<EVP_CUNSTOM>(cst);
	delete[] c_str;
}

std::string sm2PublicKey::Encrypt(const std::string& message,
	std::string& error) {
	std::string encodedstr;
	EVP_PKEY_CTX* pkctx = NULL;
	int retV = 1;
	if (!(pkctx = EVP_PKEY_CTX_new(m_pkey.get()->pkey, NULL))) {
		error = GetErrorStr();
		errorL("EVP_PKEY_CTX_new:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}
	retV = EVP_PKEY_encrypt_init(pkctx);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_encrypt_init:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}

	size_t outbuflen = 0;
	unsigned char* outbuf = NULL;
	retV = EVP_PKEY_encrypt(pkctx, NULL, &outbuflen,
		(const unsigned char*)message.c_str(),
		message.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_encrypt:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}
	if (outbuflen == 0) {
		errorL("EVP_PKEY_encrypt:%s", "no memery");
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}

	outbuf = new unsigned char[outbuflen];

	retV = EVP_PKEY_encrypt(pkctx, outbuf, &outbuflen,
		(const unsigned char*)message.c_str(),
		message.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_encrypt:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		delete[] outbuf;
		return "";
	}
	encodedstr = std::string((const char*)outbuf, outbuflen);
	delete[] outbuf;
	EVP_PKEY_CTX_free(pkctx);
	return encodedstr;
}

bool sm2PublicKey::SignatureVerification32(const std::string& signature,
	const std::string& message,
	std::string& error) {

	EVP_PKEY_CTX* pkctx = NULL;
	unsigned char* outbuf = NULL;
	size_t outlen = 0;
	int retV = 1;
	if (!(pkctx = EVP_PKEY_CTX_new(m_pkey.get()->pkey, NULL))) {
		error = GetErrorStr();
		errorL("EVP_PKEY_CTX_new:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return false;
	}

	retV = EVP_PKEY_verify_init(pkctx);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_verify_init:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return false;
	}

	retV = EVP_PKEY_verify(
		pkctx, (const unsigned char*)signature.c_str(), signature.size(),
		(const unsigned char*)message.c_str(), message.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_sign:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return false;
	}
	EVP_PKEY_CTX_free(pkctx);
	return true;
}

bool sm2PublicKey::SignatureVerification(const std::string& signature,
	const std::string& message,
	std::string& error) {
	std::string signatured;
	EVP_MD_CTX* mdctx = NULL;
	int retV = 0;
	if (!(mdctx = EVP_MD_CTX_create())) {
		error = GetErrorStr();
		errorL("EVP_MD_CTX_create:%s", error);
		return false;
	}
	retV =
		EVP_DigestVerifyInit(mdctx, NULL, EVP_sm3(), NULL, m_pkey.get()->pkey);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_DigestVerifyInit:%s", error);
		EVP_MD_CTX_free(mdctx);
		return false;
	}

	retV = EVP_DigestVerifyUpdate(mdctx, message.c_str(), message.size());
	if (retV <= 0) {
		error = GetErrorStr();
		EVP_MD_CTX_free(mdctx);
		errorL("EVP_DigestVerifyUpdate:%s", error);
		return false;
	}
	retV = EVP_DigestVerifyFinal(
		mdctx, (const unsigned char*)signature.c_str(), signature.size());
	if (retV <= 0) {
		error = GetErrorStr();
		EVP_MD_CTX_free(mdctx);
		errorL("EVP_DigestVerifyFinal:%s", error);
		return false;
	}
	EVP_MD_CTX_free(mdctx);
	return true;
}

std::string sm2PublicKey::GetPublicString() {
	unsigned char* buffer = nullptr;
	int retV = i2d_PUBKEY(m_pkey.get()->pkey, &buffer);
	if (retV <= 0) {
		errorL("i2d_PUBKEY:%s", GetErrorStr());
		return "";
	}
	std::string ret((const char*)buffer, retV);
	OPENSSL_free(buffer);
	return ret;
}

sm2PrivateKey::sm2PrivateKey() {
	EVP_PKEY* ret = NULL;

	EVP_PKEY_CTX* pkctx = NULL;

	pkctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL);
	if (pkctx == NULL) {
		errorL("EVP_PKEY_CTX_new_id");
		return;
	}
	int retV = 1;
	retV = EVP_PKEY_keygen_init(pkctx);

	if (retV <= 0) {
		errorL("EVP_PKEY_keygen_init:%s", GetErrorStr());
		EVP_PKEY_CTX_free(pkctx);
		return;
	}

	retV = EVP_PKEY_keygen(pkctx, &ret);
	if (retV <= 0) {
		errorL("EVP_PKEY_keygen:%s", GetErrorStr());
		EVP_PKEY_CTX_free(pkctx);
		return;
	}
	EVP_CUNSTOM* cst = new EVP_CUNSTOM{ ret };
	M_PKEY = std::shared_ptr<EVP_CUNSTOM>(cst);
	EVP_PKEY_CTX_free(pkctx);
}



sm2PrivateKey sm2PrivateKey::CreateWithPEM(const std::string& pem)
{
	EVP_PKEY* pkey = nullptr;
	BIO* bio = BIO_new_mem_buf((const void*)pem.c_str(), pem.size());
	if (bio == nullptr) {
		errorL("BIO_new_mem_buf error!");
		BIO_free(bio);
	}

	pkey = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL);
	if (!pkey) {
		errorL("PEM_read_bio_PrivateKey error!");
	}
	BIO_free(bio);
	EVP_CUNSTOM* cst = new EVP_CUNSTOM{ pkey };
	return sm2PrivateKey(cst);
}

sm2PublicKey sm2PrivateKey::CreatePublic() {
	unsigned char* buffer = nullptr;
	int retV = i2d_PUBKEY(M_PKEY.get()->pkey, &buffer);
	if (retV <= 0) {
		errorL("i2d_PUBKEY:%s", GetErrorStr());
		return sm2PublicKey{};
	}
	sm2PublicKey pub(buffer, retV);
	OPENSSL_free(buffer);
	return pub;
}

std::string sm2PrivateKey::GetPEM()
{
	

	BIO* bio = BIO_new(BIO_s_mem());
	if (bio == nullptr) {
		errorL("BIO_new_mem_buf error!");
		BIO_free(bio);
		return "";
	}
	if (1 != PEM_write_bio_PrivateKey(bio, M_PKEY->pkey, NULL, NULL, 0, NULL, NULL)) {
		errorL("PEM_write_bio_PrivateKey error!");
		BIO_free(bio);
		return "";
	}

	BUF_MEM* bptr;

	BIO_get_mem_ptr(bio, &bptr);
	BIO_set_close(bio, BIO_NOCLOSE); /* So BIO_free() leaves BUF_MEM alone */
	BIO_free(bio);

	std::string ret(bptr->data, bptr->length);
	BUF_MEM_free(bptr);
	return ret;
}

std::string sm2PrivateKey::Decrypt(const std::string& encoded,
	std::string& error) {
	std::string decodedstr;
	EVP_PKEY_CTX* pkctx = NULL;
	unsigned char* outbuf = NULL;
	size_t outlen = 0;

	int retV = 1;
	if (!(pkctx = EVP_PKEY_CTX_new(M_PKEY.get()->pkey, NULL))) {
		error = GetErrorStr();
		errorL("EVP_PKEY_CTX_new:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}
	retV = EVP_PKEY_decrypt_init(pkctx);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_decrypt_init:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}
	retV = EVP_PKEY_decrypt(pkctx, NULL, &outlen,
		(const unsigned char*)encoded.c_str(),
		encoded.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_encrypt_init:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}

	if (outlen == 0) {
		errorL("EVP_PKEY_decrypt:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}

	outbuf = new unsigned char[outlen];

	retV = EVP_PKEY_decrypt(pkctx, outbuf, &outlen,
		(const unsigned char*)encoded.c_str(),
		encoded.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_encrypt_init:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		delete[] outbuf;
		return "";
	}

	decodedstr = std::string((const char*)outbuf, outlen);
	delete[] outbuf;

	EVP_PKEY_CTX_free(pkctx);
	return decodedstr;
}

std::string sm2PrivateKey::Signature32(const std::string& message,
	std::string& error) {

	std::string signatured;

	EVP_PKEY_CTX* pkctx = NULL;
	unsigned char* outbuf = NULL;
	size_t outlen = 0;
	int retV = 1;
	if (message.size() != 32) {
		error = "size not eq 32";
		return "";
	}
	if (!(pkctx = EVP_PKEY_CTX_new(M_PKEY.get()->pkey, NULL))) {
		error = GetErrorStr();
		errorL("EVP_PKEY_CTX_new:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}

	retV = EVP_PKEY_sign_init(pkctx);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_sign_init:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}
	debugL("msglen:%s", message.size());
	retV =
		EVP_PKEY_sign(pkctx, NULL, &outlen,
			(const unsigned char*)message.c_str(), message.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_sign:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		return "";
	}
	debugL(outlen);
	outbuf = new unsigned char[outlen];
	retV =
		EVP_PKEY_sign(pkctx, outbuf, &outlen,
			(const unsigned char*)message.c_str(), message.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_PKEY_sign:%s", error);
		EVP_PKEY_CTX_free(pkctx);
		delete[] outbuf;
		return "";
	}
	signatured = std::string((const char*)outbuf, outlen);
	EVP_PKEY_CTX_free(pkctx);
	return signatured;
}

std::string sm2PrivateKey::Signature(const std::string& message,
	std::string& error) {
	std::string signatured;
	EVP_MD_CTX* mdctx = NULL;
	unsigned char* outbuf = NULL;
	size_t outbuflen = 0;
	int retV = 0;
	if (!(mdctx = EVP_MD_CTX_create())) {
		error = GetErrorStr();
		errorL("EVP_MD_CTX_create:%s", error);
		return "";
	}
	retV = EVP_DigestSignInit(mdctx, NULL, EVP_sm3(), NULL, M_PKEY.get()->pkey);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_DigestSignInit:%s", error);
		EVP_MD_CTX_free(mdctx);
		return "";
	}

	retV = EVP_DigestSignUpdate(mdctx, message.c_str(), message.size());
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_DigestSignUpdate:%s", error);
		EVP_MD_CTX_free(mdctx);
		return "";
	}

	retV = EVP_DigestSignFinal(mdctx, NULL, &outbuflen);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_DigestSignFinal:%s", error);
		EVP_MD_CTX_free(mdctx);
		return "";
	}

	outbuf = new unsigned char[outbuflen];

	retV = EVP_DigestSignFinal(mdctx, outbuf, &outbuflen);
	if (retV <= 0) {
		error = GetErrorStr();
		errorL("EVP_DigestSignFinal:%s", error);
		EVP_MD_CTX_free(mdctx);
		return "";
	}

	signatured = std::string((const char*)outbuf, outbuflen);
	delete[] outbuf;
	return signatured;
}
#endif

到了这里,关于OpenSSL 3.1.1 ECC 加密、解密、签名、验签(国密 sm2、sm3)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 国密SM2前端加密解密示例

    目录 一、 安装sm2依赖 二、编写代码 1、data中绑定数据 2、公钥加密 3、私钥解密 4、按钮绑定一下,数据可见一下 三、完整代码 要改变的数据phone和过程数据copyphone,公钥publicKey和私钥privateKey 具体生成测试公钥私钥可参照SM2加解密 C1为65字节第1字节为压缩标识,这里固定为

    2024年02月03日
    浏览(70)
  • 前端sm2国密加密解密

    1.下载国密包 2.获取后端的公钥 注sm-crypto使用BC库加解密前端密钥与后端密钥是两队,非常规的base64密钥 前端公钥需要在前面加04占位否则无法解密 3.前端使用公钥进行加密 生成的加密串加04方便后端解密 4.前端使用私钥解密

    2024年02月11日
    浏览(66)
  • 国密sm2公钥加密 私钥解密java代码实现

    目录 一、引入jar包 二、生成秘钥对,加解密工具类

    2024年02月11日
    浏览(72)
  • 国密SM2算法(JS加密,C#、Java解密)

    常见的渗透测试会将网站登录时密码使用明文传输视为风险。推荐使用国密算法或者RSA算法对密码进行加密传输。 RSA加密(JS加密,C#、Java解密)请参考《RSA对称加密(JS加密,C#、Java解密)》​​​​​​ 本文描述国密SM2算法的实现。 一、工作原理 前端js使用公钥进行加密

    2024年02月02日
    浏览(55)
  • 国密SM2算法的加密签名消息语法封装解析p7格式signedData

    前文可参考:SM2算法的加密签名消息语法规范(三)如何构造signedData_天对地,雨对风的博客-CSDN博客系列。 这里直接讲openssl asn1解析和封装的部分代码。 国密 p7格式标准,参考:GMT0010-2012 1、p7 签名结构:  编写结构体GMTSignedData.h 注意:SM2_SignedData_st结构中的sign类型修改为

    2024年02月11日
    浏览(45)
  • 医保移动支付加密解密请求工具封装【国密SM2SM4】

    医保移动支付加密解密请求工具封装 定点医药机构向地方移动支付中心发起费用明细上传、支付下单、医保退费等交易时需要发送密文,由于各大医疗机构厂商的开发语各不相同,可能要有java的、c#的、python的、pb的、nodjs的、php的、还可能有Delphi的等。。。。很多开发语言

    2024年01月21日
    浏览(89)
  • 国密SM2/SM3算法

    分类 1、SM1是一种分组加密算法 对称加密算法中的分组加密算法,其分组长度、秘钥长度都是128bit,算法安全保密强度跟 AES 相当,但是算法不公开,仅以IP核的形式存在于芯片中,需要通过加密芯片的接口进行调用。 采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙

    2024年02月05日
    浏览(65)
  • java实现国密SM4的加密和解密方式(即时通讯的消息对话加密采用SM2还是SM4)

    1.对于即时通讯的消息对话加密采用SM2还是SM4更合适? 对于即时通讯的消息对话加密,建议采用SM4对称加密算法,而不是SM2非对称加密算法。 SM2主要用于数字签名和密钥交换,其加密速度比SM4慢,而且SM2不太适合对长消息进行加密,因为它只能对比较短的数据块进行加密,这

    2024年02月07日
    浏览(82)
  • 国密算法 SM2 公钥加密 数字签名 密钥交换 全网最高效的开源python代码

    此前发布过SM2、SM3、SM4、ZUC等文章,以及开源的完整python代码。近些天看到一篇电子科大兰同学的硕士毕业论文(兰修文. ECC计算算法的优化及其在SM2实现中的运用[D]. 成都: 电子科技大学, 2019),文中采用预计算加速SM2椭圆曲线基点点乘,将这个思路用python代码实现后,实测

    2024年02月09日
    浏览(49)
  • 国密算法SM2、SM3的使用

    1. SM2是非对称加密算法         它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替换RSA/DH/ECDSA/ECDH等国际算法。可以满足电子认证服务系统等应用需求,由国家密码管理局于2010年12月17号发布。 2.SM3是一种密码杂凑

    2024年02月06日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包