1 Star 0 Fork 1

一叶方舟 / QT-SECURE

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
qecdhmgr.cpp 13.68 KB
一键复制 编辑 原始数据 按行查看 历史
admin 提交于 2023-03-14 14:32 . 2023-3-14
#include "qdhmgr.h"
QECDHMgr::QECDHMgr()
{
}
QString QECDHMgr::GetCurveName()
{
return this->curveName_;
}
bool QECDHMgr::SetCurveName(QString curveName)
{
EC_builtin_curve * buffer = nullptr;
size_t count = EC_get_builtin_curves(nullptr, 0);
if (count <= 0) {
return false;
}
buffer = new EC_builtin_curve[count];
if (EC_get_builtin_curves(buffer, count) != count) {
return false;
}
// Check if the curve is in the list.
for (int i = 0; i < count; ++i) {
const char* shortName = OBJ_nid2sn(buffer[i].nid);
const char* comment = buffer[i].comment;
if (shortName && strlen(shortName) > 0) {
// qDebug() << buffer[i].nid << "|"<< shortName<<"|" << comment;
if(curveName == QString(shortName))
{
curveName_ = curveName;
return true;
}
}
}
return false;
}
bool QECDHMgr::GenerateKeys()
{
ERR_clear_error();
// First, create an OSSL_PARAM_BLD.
QScopedPointer <OSSL_PARAM_BLD , ScopedPointerParamBldDeleter> paramBuild(OSSL_PARAM_BLD_new());
if (!paramBuild.data())
{
return false;
}
// Push the curve name to the OSSL_PARAM_BLD.
if (!OSSL_PARAM_BLD_push_utf8_string(paramBuild.data(), OSSL_PKEY_PARAM_GROUP_NAME, curveName_.toStdString().c_str(), 0)) {
return false;
}
// Convert OSSL_PARAM_BLD to OSSL_PARAM.
QScopedPointer <OSSL_PARAM , ScopedPointerParamDeleter> params(OSSL_PARAM_BLD_to_param(paramBuild.data()));
if (!params.data()) {
return false;
}
// Create the EC key generation context.
QScopedPointer <EVP_PKEY_CTX , ScopedPointerKeyCtxDeleter> ctx(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr));
if (!ctx.data())
{
return false;
}
// Initialize the key generation context.
if (EVP_PKEY_keygen_init(ctx.data()) <= 0) {
return false;
}
// Set the parameters which include the curve name.
if (!EVP_PKEY_CTX_set_params(ctx.data(), params.data())) {
return false;
}
// Generate a key pair.
EVP_PKEY* keyPair = nullptr;
if (EVP_PKEY_generate(ctx.data(), &keyPair) <= 0) {
return false;
}
keyPair_.reset(keyPair);
return true;
}
QString QECDHMgr::GetPrivateKey()
{
ERR_clear_error();
if(keyPair_.data())
{
// The private key is stored as a BIGNUM object.
BIGNUM* privateKey = nullptr;
if (!EVP_PKEY_get_bn_param(keyPair_.data(), OSSL_PKEY_PARAM_PRIV_KEY, &privateKey)) {
return "";
}
// Convert the BIGNUM to a hex string.
QString hexPrivateKey = ConvertBigNumToHex(privateKey);
BN_free(privateKey);
return hexPrivateKey;
}else
{
return "";
}
}
QString QECDHMgr::GetPublicKey()
{
ERR_clear_error();
if(keyPair_.data())
{
// The public key is stored as a byte array.
// Get the array size.
size_t keyLength = 0;
if (!EVP_PKEY_get_octet_string_param(keyPair_.data(), OSSL_PKEY_PARAM_PUB_KEY, nullptr, 0, &keyLength)) {
return "";
}
// Get the key.
unsigned char * publicKey = new unsigned char [keyLength];
if (!EVP_PKEY_get_octet_string_param(keyPair_.data(), OSSL_PKEY_PARAM_PUB_KEY, publicKey, keyLength, &keyLength)) {
return "";
}
// Convert the byte array key to a hex string.
QString hexPublicKey = ConvertDataToHex(QByteArray((char *)publicKey, keyLength));
delete [] publicKey;
publicKey = nullptr;
return hexPublicKey;
}else
{
return "";
}
}
bool QECDHMgr::SetPublicKey(QString hexPublicKey)
{
QScopedPointer <EVP_PKEY , ScopedPointerKeyDeleter> peerPublicKey;
if(!CreatePeerPublicKey(hexPublicKey, &peerPublicKey))
{
return false;
}
keyPair_.reset(peerPublicKey.take());
return true;
}
bool QECDHMgr::SetPrivateKey(QString hexPrivateKey)
{
QScopedPointer <EVP_PKEY , ScopedPointerKeyDeleter> peerPrivateKey;
if(!CreatePeerPrivateKey(hexPrivateKey, &peerPrivateKey))
{
return false;
}
keyPair_.reset(peerPrivateKey.take());
return true;
}
bool QECDHMgr::SetKeyPair(QString hexPublicKey, QString hexPrivateKey)
{
QScopedPointer <EVP_PKEY , ScopedPointerKeyDeleter> peerKeyPair;
if(!CreatePeerKeyPair(hexPublicKey, hexPrivateKey, &peerKeyPair))
{
return false;
}
keyPair_.reset(peerKeyPair.take());
return true;
}
QString QECDHMgr::DeriveSharedSecret(QString hexPeerPublicKey)
{
ERR_clear_error();
// First, you have to create the peer public key object.
// It takes several calls, so it is done in a separate function.
QScopedPointer <EVP_PKEY , ScopedPointerKeyDeleter> peerPublicKey;
if(!CreatePeerPublicKey(hexPeerPublicKey, &peerPublicKey))
{
return "";
}
// Create the derivation context.
QScopedPointer <EVP_PKEY_CTX , ScopedPointerKeyCtxDeleter> derivationCtx(EVP_PKEY_CTX_new(keyPair_.data(), nullptr));
if (!derivationCtx.data()) {
return "";
}
// Initialize the derivation context.
if (EVP_PKEY_derive_init(derivationCtx.data()) <= 0) {
return "";
}
// Set the peer public key object.
if (EVP_PKEY_derive_set_peer(derivationCtx.data(), peerPublicKey.data()) <= 0) {
return "";
}
// Get the shared secret length.
size_t sharedSecretLength = 0;
if (EVP_PKEY_derive(derivationCtx.data(), nullptr, &sharedSecretLength) <= 0) {
return "";
}
if (sharedSecretLength == 0) {
return "";
}
unsigned char * sharedSecret = new unsigned char [sharedSecretLength];
// Derive the shared secret.
if (EVP_PKEY_derive(derivationCtx.data(), sharedSecret, &sharedSecretLength) <= 0) {
return "";
}
// Convert to a hex string.
QString hexSharedSecret = ConvertDataToHex(QByteArray((char *)sharedSecret, sharedSecretLength));
delete [] sharedSecret;
return hexSharedSecret;
}
QString QECDHMgr::GetLastError()
{
unsigned long lastError = ERR_peek_last_error();
if (lastError == 0) {
return "";
}
char errorString[256];
ERR_error_string_n(lastError, errorString, sizeof(errorString));
return errorString;
}
// ***************************** 以下是私有函数 **********************************
QString QECDHMgr::ConvertBigNumToHex(const BIGNUM *bigNum)
{
char* tmpHexBigNum = BN_bn2hex(bigNum);
if (!tmpHexBigNum) {
return "";
}
QString hexBigNum(tmpHexBigNum);
OPENSSL_free(tmpHexBigNum);
return hexBigNum;
}
BIGNUM* QECDHMgr::ConvertHexToBigNum(QString hexBigNum)
{
BIGNUM* bn = nullptr;
if (!BN_hex2bn(&bn, hexBigNum.toStdString().c_str())) {
return nullptr;
}
return bn;
}
QString QECDHMgr::ConvertDataToHex(QByteArray data)
{
static const char hexDigits[] = "0123456789ABCDEF";
QString hex;
hex.reserve(data.size() * 2);
for (unsigned char c : data) {
hex.push_back(hexDigits[c >> 4]);
hex.push_back(hexDigits[c & 15]);
}
return hex;
}
// Converts a hex string to binary data.
QByteArray QECDHMgr::ConvertHexToData(QString hex)
{
QByteArray data;
// Must be an even number!
if (hex.size() & 1) {
return data;
}
auto it = hex.begin();
while (it != hex.end()) {
int hi = GetHexValue((*it++).toLatin1());
int lo = GetHexValue((*it++).toLatin1());
if (hi == -1 || lo == -1) {
data.clear();
return data;
}
data.push_back(hi << 4 | lo);
}
return data;
}
bool QECDHMgr::CreatePeerPublicKey(QString hexPeerPublicKey, QScopedPointer <EVP_PKEY , ScopedPointerKeyDeleter>* peerPublicKey)
{
ERR_clear_error();
// First, we sould create an OSSL_PARAM_BLD with the curve name
// and the raw peer public key.
QScopedPointer <OSSL_PARAM_BLD, ScopedPointerParamBldDeleter> paramBuild(OSSL_PARAM_BLD_new());
if (!paramBuild.data()) {
return false;
}
// Set the curve name.
if (!OSSL_PARAM_BLD_push_utf8_string(paramBuild.data(), OSSL_PKEY_PARAM_GROUP_NAME,curveName_.toStdString().c_str(), 0)) {
return false;
}
// Convert the peer hex public key to raw data.
QByteArray binPeerPublicKey = ConvertHexToData(hexPeerPublicKey);
if (binPeerPublicKey.size() <= 0) {
return false;
}
// Set the raw peer public key.
if (!OSSL_PARAM_BLD_push_octet_string(paramBuild.data(), OSSL_PKEY_PARAM_PUB_KEY, binPeerPublicKey.data(), binPeerPublicKey.size())) {
return false;
}
// Convert the OSSL_PARAM_BLD to OSSL_PARAM.
QScopedPointer <OSSL_PARAM , ScopedPointerParamDeleter> params(OSSL_PARAM_BLD_to_param(paramBuild.data()));
if (!params.data()) {
return false;
}
// Create a EVP_PKEY context.
QScopedPointer <EVP_PKEY_CTX , ScopedPointerKeyCtxDeleter> peerPublicKeyCtx(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr));
if (!peerPublicKeyCtx.data()) {
return false;
}
// Initialize the context.
if (EVP_PKEY_fromdata_init(peerPublicKeyCtx.data()) <= 0) {
return false;
}
// Create the peer public key object.
EVP_PKEY* tmp = nullptr;
if (EVP_PKEY_fromdata(peerPublicKeyCtx.data(), &tmp, EVP_PKEY_PUBLIC_KEY, params.data()) <= 0) {
return false;
}
peerPublicKey->reset(tmp);
return true;
}
bool QECDHMgr::CreatePeerPrivateKey(QString hexPeerPrivateKey, QScopedPointer <EVP_PKEY , ScopedPointerKeyDeleter>* peerPrivateKey)
{
ERR_clear_error();
// First, we sould create an OSSL_PARAM_BLD with the curve name
// and the raw peer public key.
QScopedPointer <OSSL_PARAM_BLD, ScopedPointerParamBldDeleter> paramBuild(OSSL_PARAM_BLD_new());
if (!paramBuild.data()) {
return false;
}
// Set the curve name.
if (!OSSL_PARAM_BLD_push_utf8_string(paramBuild.data(), OSSL_PKEY_PARAM_GROUP_NAME,curveName_.toStdString().c_str(), 0)) {
return false;
}
// Convert the peer hex private key to raw data.
BIGNUM * binPeerPrivateKey = ConvertHexToBigNum(hexPeerPrivateKey);
if(!binPeerPrivateKey)
{
return false;
}
// Set the raw peer private key.
if (!OSSL_PARAM_BLD_push_BN(paramBuild.data(), OSSL_PKEY_PARAM_PRIV_KEY, binPeerPrivateKey)) {
return false;
}
// Convert the OSSL_PARAM_BLD to OSSL_PARAM.
QScopedPointer <OSSL_PARAM , ScopedPointerParamDeleter> params(OSSL_PARAM_BLD_to_param(paramBuild.data()));
if (!params.data()) {
return false;
}
// Create a EVP_PKEY context.
QScopedPointer <EVP_PKEY_CTX , ScopedPointerKeyCtxDeleter> peerPrivateKeyCtx(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr));
if (!peerPrivateKeyCtx.data()) {
return false;
}
// Initialize the context.
if (EVP_PKEY_fromdata_init(peerPrivateKeyCtx.data()) <= 0) {
return false;
}
// Create the peer private key object.
EVP_PKEY* tmp = nullptr;
if (EVP_PKEY_fromdata(peerPrivateKeyCtx.data(), &tmp, EVP_PKEY_KEYPAIR, params.data()) <= 0) {
return false;
}
peerPrivateKey->reset(tmp);
return true;
}
bool QECDHMgr::CreatePeerKeyPair(QString hexPeerPublicKey, QString hexPeerPrivateKey, QScopedPointer<EVP_PKEY, ScopedPointerKeyDeleter> *peerPrivateKey)
{
ERR_clear_error();
// First, we sould create an OSSL_PARAM_BLD with the curve name
// and the raw peer public key.
QScopedPointer <OSSL_PARAM_BLD, ScopedPointerParamBldDeleter> paramBuild(OSSL_PARAM_BLD_new());
if (!paramBuild.data()) {
return false;
}
// Set the curve name.
if (!OSSL_PARAM_BLD_push_utf8_string(paramBuild.data(), OSSL_PKEY_PARAM_GROUP_NAME,curveName_.toStdString().c_str(), 0)) {
return false;
}
// Convert the peer hex private key to raw data.
BIGNUM * binPeerPrivateKey = ConvertHexToBigNum(hexPeerPrivateKey);
if(!binPeerPrivateKey)
{
return false;
}
// Set the raw peer private key.
if (!OSSL_PARAM_BLD_push_BN(paramBuild.data(), OSSL_PKEY_PARAM_PRIV_KEY, binPeerPrivateKey)) {
return false;
}
// Convert the peer hex public key to raw data.
QByteArray binPeerPublicKey = ConvertHexToData(hexPeerPublicKey);
if (binPeerPublicKey.size() <= 0) {
return false;
}
// Set the raw peer public key.
if (!OSSL_PARAM_BLD_push_octet_string(paramBuild.data(), OSSL_PKEY_PARAM_PUB_KEY, binPeerPublicKey.data(), binPeerPublicKey.size())) {
return false;
}
// Convert the OSSL_PARAM_BLD to OSSL_PARAM.
QScopedPointer <OSSL_PARAM , ScopedPointerParamDeleter> params(OSSL_PARAM_BLD_to_param(paramBuild.data()));
if (!params.data()) {
return false;
}
// Create a EVP_PKEY context.
QScopedPointer <EVP_PKEY_CTX , ScopedPointerKeyCtxDeleter> peerPrivateKeyCtx(EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr));
if (!peerPrivateKeyCtx.data()) {
return false;
}
// Initialize the context.
if (EVP_PKEY_fromdata_init(peerPrivateKeyCtx.data()) <= 0) {
return false;
}
// Create the peer private key object.
EVP_PKEY* tmp = nullptr;
if (EVP_PKEY_fromdata(peerPrivateKeyCtx.data(), &tmp, EVP_PKEY_KEYPAIR, params.data()) <= 0) {
return false;
}
peerPrivateKey->reset(tmp);
return true;
}
C++
1
https://gitee.com/yiyefangzhou24/qt-secure.git
git@gitee.com:yiyefangzhou24/qt-secure.git
yiyefangzhou24
qt-secure
QT-SECURE
master

搜索帮助