mirror of
https://github.com/QuasarApp/Heart.git
synced 2025-05-11 17:09:41 +00:00
added tests for ecdsa auth
This commit is contained in:
parent
622302a3ff
commit
5ff6c3ef96
180
Heart/AbstractSpace/authecdsa.cpp
Normal file
180
Heart/AbstractSpace/authecdsa.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
//#
|
||||
//# Copyright (C) 2021-2022 QuasarApp.
|
||||
//# Distributed under the GPLv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
|
||||
#include "authecdsa.h"
|
||||
|
||||
#include <openssl/ec.h> // for EC_GROUP_new_by_curve_name, EC_GROUP_free, EC_KEY_new, EC_KEY_set_group, EC_KEY_generate_key, EC_KEY_free
|
||||
#include <openssl/ecdsa.h> // for ECDSA_do_sign, ECDSA_do_verify
|
||||
#include <openssl/obj_mac.h> // for NID_secp192k1
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QIODevice>
|
||||
#include <QVector>
|
||||
|
||||
namespace QH {
|
||||
|
||||
AuthECDSA::AuthECDSA() {
|
||||
|
||||
}
|
||||
|
||||
QByteArray bignumToArray(const BIGNUM* num) {
|
||||
int length = BN_bn2mpi(num, nullptr);
|
||||
QVector<unsigned char> data(length);
|
||||
BN_bn2mpi(num, data.data());
|
||||
QByteArray result;
|
||||
result.insert(0, reinterpret_cast<char*>(data.data()), data.length());
|
||||
return result;
|
||||
}
|
||||
|
||||
BIGNUM* bignumFromArray(const QByteArray& array) {
|
||||
return BN_mpi2bn(reinterpret_cast<const unsigned char*>(array.data()), array.length(), nullptr);
|
||||
}
|
||||
|
||||
QByteArray extractPrivateKey(EC_KEY* ec_key) {
|
||||
const BIGNUM* ec_priv = EC_KEY_get0_private_key(ec_key);
|
||||
int length = BN_bn2mpi(ec_priv, nullptr);
|
||||
QVector<unsigned char> data(length);
|
||||
data.insert(0, length);
|
||||
BN_bn2mpi(ec_priv, data.data());
|
||||
QByteArray result;
|
||||
result.insert(0, reinterpret_cast<char*>(data.data()), data.length());
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray extractPublicKey(EC_KEY* key, EC_GROUP* group) {
|
||||
|
||||
QByteArray data;
|
||||
point_conversion_form_t form = EC_GROUP_get_point_conversion_form(group);
|
||||
|
||||
unsigned char* pub_key_buffer;
|
||||
size_t length = EC_KEY_key2buf(key, form, &pub_key_buffer, nullptr);
|
||||
|
||||
if (length <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
data.insert(0, reinterpret_cast<const char*>(pub_key_buffer), length);
|
||||
|
||||
OPENSSL_free(pub_key_buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool AuthECDSA::makeKeys(QByteArray &pubKey, QByteArray &privKey) {
|
||||
|
||||
EC_KEY *eckey= nullptr;
|
||||
EC_GROUP *ecgroup = nullptr;
|
||||
|
||||
|
||||
auto free = [&eckey, &ecgroup] () {
|
||||
if (ecgroup)
|
||||
EC_GROUP_free(ecgroup);
|
||||
|
||||
if (eckey)
|
||||
EC_KEY_free(eckey);
|
||||
};
|
||||
|
||||
eckey = EC_KEY_new();
|
||||
if (!eckey)
|
||||
return false;
|
||||
|
||||
ecgroup = EC_GROUP_new_by_curve_name(NID_secp256k1);
|
||||
|
||||
if (!ecgroup) {
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
const int success = 1;
|
||||
if ( success != EC_KEY_set_group(eckey, ecgroup)) {
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( success != EC_KEY_generate_key(eckey)) {
|
||||
free();
|
||||
return false;
|
||||
}
|
||||
|
||||
pubKey = extractPublicKey(eckey, ecgroup);
|
||||
privKey = extractPrivateKey(eckey);
|
||||
|
||||
return pubKey.length() && privKey.length();
|
||||
}
|
||||
|
||||
QByteArray AuthECDSA::signMessage(const QByteArray &inputData,
|
||||
const QByteArray &key) const {
|
||||
|
||||
auto hash = QCryptographicHash::hash(inputData, QCryptographicHash::Sha256);
|
||||
|
||||
EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
|
||||
BIGNUM* priv = BN_mpi2bn(reinterpret_cast<const unsigned char*>(key.data()),
|
||||
key.length(), nullptr);
|
||||
EC_KEY_set_private_key(eckey, priv);
|
||||
BN_free(priv);
|
||||
|
||||
ECDSA_SIG *signature = ECDSA_do_sign(reinterpret_cast<const unsigned char*>(hash.data()),
|
||||
hash.length(), eckey);
|
||||
EC_KEY_free(eckey);
|
||||
|
||||
const BIGNUM * R, *S;
|
||||
ECDSA_SIG_get0(signature, &R, &S);
|
||||
|
||||
QByteArray result;
|
||||
QDataStream stream(&result, QIODevice::WriteOnly);
|
||||
|
||||
stream << bignumToArray(R);
|
||||
stream << bignumToArray(S);
|
||||
|
||||
ECDSA_SIG_free(signature);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AuthECDSA::checkSign(const QByteArray &inputData,
|
||||
const QByteArray &signature,
|
||||
const QByteArray &key) const {
|
||||
|
||||
// extract key from raw array;
|
||||
EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||
const EC_GROUP* ec_group = EC_KEY_get0_group(eckey);
|
||||
EC_POINT* ec_point = EC_POINT_new(ec_group);
|
||||
EC_POINT_oct2point(ec_group, ec_point,
|
||||
reinterpret_cast<const unsigned char*>(key.data()),
|
||||
key.length(), nullptr);
|
||||
EC_KEY_set_public_key(eckey, ec_point);
|
||||
EC_POINT_free(ec_point);
|
||||
|
||||
// extract signature from raw array
|
||||
|
||||
BIGNUM * R, *S;
|
||||
QDataStream stream(signature);
|
||||
|
||||
QByteArray rR,rS;
|
||||
stream >> rR;
|
||||
stream >> rS;
|
||||
R = bignumFromArray(rR);
|
||||
S = bignumFromArray(rS);
|
||||
|
||||
ECDSA_SIG *sig = ECDSA_SIG_new();
|
||||
ECDSA_SIG_set0(sig, R, S);
|
||||
|
||||
auto hash = QCryptographicHash::hash(inputData, QCryptographicHash::Sha256);
|
||||
|
||||
int verify_status = ECDSA_do_verify(reinterpret_cast<const unsigned char*>(hash.data()),
|
||||
hash.length(), sig, eckey);
|
||||
|
||||
ECDSA_SIG_free(sig);
|
||||
|
||||
return verify_status == 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
45
Heart/AbstractSpace/authecdsa.h
Normal file
45
Heart/AbstractSpace/authecdsa.h
Normal file
@ -0,0 +1,45 @@
|
||||
//#
|
||||
//# Copyright (C) 2021-2022 QuasarApp.
|
||||
//# Distributed under the GPLv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
|
||||
#ifndef AUTHECDSA_H
|
||||
#define AUTHECDSA_H
|
||||
|
||||
#include "abstractdata.h"
|
||||
#include <asynckeysauth.h>
|
||||
|
||||
namespace QH {
|
||||
|
||||
/**
|
||||
* @brief The AuthECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library.
|
||||
*/
|
||||
class AuthECDSA: public QH::AsyncKeysAuth
|
||||
{
|
||||
|
||||
public:
|
||||
AuthECDSA();
|
||||
|
||||
/**
|
||||
* @brief makeKeys This static method generate the public and private keys of the ECDSA.
|
||||
* @param pubKey This is result public key.
|
||||
* @param privKey This is result private key.
|
||||
* @return true if keys generated successful.
|
||||
*/
|
||||
static bool makeKeys(QByteArray &pubKey, QByteArray &privKey);
|
||||
|
||||
// AsyncKeysAuth interface
|
||||
protected:
|
||||
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override;
|
||||
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // AUTHECDSA_H
|
62
HeartTests/AbstractSpace/ecdsaauthtest.cpp
Normal file
62
HeartTests/AbstractSpace/ecdsaauthtest.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2022-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
#include "ecdsaauthtest.h"
|
||||
#include "authecdsa.h"
|
||||
#include <QtTest>
|
||||
|
||||
/*
|
||||
* test class
|
||||
*/
|
||||
class ECDSA: public QH::AuthECDSA {
|
||||
|
||||
public:
|
||||
ECDSA(const QByteArray &publicKey, const QByteArray &privKey) {
|
||||
setPublicKey(publicKey);
|
||||
_priv = privKey;
|
||||
}
|
||||
|
||||
// AsyncKeysAuth interface
|
||||
protected:
|
||||
QByteArray getPrivateKey() const override {
|
||||
return _priv;
|
||||
};
|
||||
|
||||
private:
|
||||
QByteArray _priv;
|
||||
|
||||
};
|
||||
|
||||
ECDSAAuthTest::ECDSAAuthTest() {
|
||||
|
||||
}
|
||||
|
||||
ECDSAAuthTest::~ECDSAAuthTest() {
|
||||
|
||||
}
|
||||
|
||||
void ECDSAAuthTest::test() {
|
||||
QByteArray pub, priv;
|
||||
|
||||
QVERIFY(QH::AuthECDSA::makeKeys(pub, priv));
|
||||
|
||||
QVERIFY(pub.length() && priv.length());
|
||||
|
||||
ECDSA edsa(pub, priv);
|
||||
|
||||
QVERIFY(!edsa.isValid());
|
||||
|
||||
QVERIFY(!edsa.auth(60));
|
||||
|
||||
QVERIFY(edsa.prepare());
|
||||
QVERIFY(edsa.isValid());
|
||||
|
||||
QVERIFY(edsa.auth(60));
|
||||
QVERIFY(!edsa.auth(0));
|
||||
|
||||
|
||||
}
|
24
HeartTests/AbstractSpace/ecdsaauthtest.h
Normal file
24
HeartTests/AbstractSpace/ecdsaauthtest.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2022-2022 QuasarApp.
|
||||
* Distributed under the lgplv3 software license, see the accompanying
|
||||
* Everyone is permitted to copy and distribute verbatim copies
|
||||
* of this license document, but changing it is not allowed.
|
||||
*/
|
||||
|
||||
#ifndef ECDSAAUTHTEST_H
|
||||
#define ECDSAAUTHTEST_H
|
||||
|
||||
#include "test.h"
|
||||
#include "testutils.h"
|
||||
|
||||
class ECDSAAuthTest: public Test, protected TestUtils
|
||||
{
|
||||
public:
|
||||
ECDSAAuthTest();
|
||||
~ECDSAAuthTest();
|
||||
|
||||
void test();
|
||||
|
||||
};
|
||||
|
||||
#endif // ECDSAAUTHTEST_H
|
@ -12,6 +12,7 @@
|
||||
#include "abstractnodetest.h"
|
||||
#include <shedullertest.h>
|
||||
#include <bigdatatest.h>
|
||||
#include <ecdsaauthtest.h>
|
||||
#endif
|
||||
#if HEART_BUILD_LVL >= 1
|
||||
#include <basenodetest.h>
|
||||
@ -42,6 +43,7 @@ private slots:
|
||||
TestCase(abstractNodeTest, AbstractNodeTest)
|
||||
TestCase(bigDataTest, BigDataTest);
|
||||
TestCase(shedullerTest, ShedullerTest);
|
||||
TestCase(ecdsaAuthTest, ECDSAAuthTest);
|
||||
#endif
|
||||
#if HEART_BUILD_LVL >= 1
|
||||
TestCase(baseNodeTest, BaseNodeTest)
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f7ee5cd272d6e49d27b557e3fa481e54fe27e519
|
||||
Subproject commit 9cc9e77babc5cbf2f46276caff3783c273764556
|
Loading…
x
Reference in New Issue
Block a user