Skip to content

Commit

Permalink
Merge pull request #36 from HLRichardson-Git/release/0.6.2
Browse files Browse the repository at this point in the history
Version 0.6.2: ECDSA/ ECDH interface and Workflow enhancements
  • Loading branch information
HLRichardson-Git authored Nov 3, 2024
2 parents ea65650 + 3fe5d3a commit 18e2b87
Show file tree
Hide file tree
Showing 21 changed files with 226 additions and 136 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CI Test Workflow

on:
push:
branches:
- main
- release/*
pull_request:
branches:
- main
- release/*

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Install dependencies
run: sudo apt-get install -y cmake g++ libgmp-dev

- name: Set up Google Test
run: |
mkdir -p build
cd build
cmake -DGESTALT_BUILD_TESTS=ON -DGESTALT_FETCH_GOOGLETEST=ON ..
make
- name: Run Tests
run: |
cd build
ctest --output-on-failure
7 changes: 3 additions & 4 deletions AUTHORS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Gestalt was designed and developed by Hunter RIchardson.
Gestalt was designed and developed by Hunter Richardson.

### Current Maintainers

Expand All @@ -10,7 +10,6 @@ Gestalt was designed and developed by Hunter RIchardson.

## Thanks

Special thanks to the following extraordinary individuals, without whom
Gestalt would not be possible:
Special thanks to the following extraordinary individuals, without whom Gestalt would not be possible:

*
* Morteza Mirzaei | mirzaim
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,19 @@ int main() {

```cpp
#include <gestalt/ecdsa.h>
#include <gestalt/sha2.h>
#include <iostream>

int main() {
std::string privateKey = "0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721";
ECDSA ecdsa(StandardCurve::P256, privateKey);

std::string message = "Hello, Gestalt!";
std::string messageHash = hashSHA256(message);

Signature signature = ecdsa.signMessage(messageHash);
bool signatureStatus = ecdsa.verifySignature(messageHash, signature);
Signature signature = ecdsa.signMessage(message, HashAlgorithm::SHA256);

ECDSAPublicKey peerPublicKey("0x60fed4ba255a9d31c961eb74c6356d68c049b8923b61fa6ce669622e60f29fb6",
"0x7903fe1008b8bc99a41ae9e95628bc64f2f1b20c2d7e9f5177a3c294d4462299");
bool signatureStatus = ecdsa.verifySignature(message, peerPublicKey, signature, HashAlgorithm::SHA256);

if (signatureStatus) std::cout << "Valid!" << std::endl;

Expand Down
9 changes: 2 additions & 7 deletions include/gestalt/ecdh.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@

class ECDH : public ECC {
private:

Point peerPublicKey;

std::string keyToString(const Point& point) const;

friend class ECDH_Test;
Expand All @@ -44,8 +41,6 @@ class ECDH : public ECC {

~ECDH() {}

Point givePublicKey() const;
void getPublicKey(const Point& givenPublicKey);
std::string computeSharedSecret();
std::string computeSharedSecret(const Point& peerPublicKey);
ECDHPublicKey getPublicKey() const { return keyPair.getPublicKey(); };
std::string computeSharedSecret(const ECDHPublicKey& peerPublicKey);
};
21 changes: 17 additions & 4 deletions include/gestalt/ecdsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,26 @@

#pragma once

#include <functional>
#include "../src/ecc/ecc.h"

enum class HashAlgorithm {
None, // No hash function
SHA1,
SHA224,
SHA256,
SHA384,
SHA512
};

class ECDSA : public ECC {
private:

void prepareMessage(const std::string& messageHash, mpz_t& result);
bool isInvalidSignature(Signature S);

Signature generateSignature(const mpz_t& e, mpz_t& k);
std::function<std::string(const std::string&)> getHashFunction(HashAlgorithm hashAlg);

friend class ECDSA_Test;
public:
Expand All @@ -47,7 +58,9 @@ class ECDSA : public ECC {

~ECDSA() {}

Signature signMessage(const std::string& messageHash);
Signature signMessage(const std::string& messageHash, BigInt& K);
bool verifySignature(const std::string& messageHash, const Signature signature);
};
ECDSAPublicKey getPublicKey() const { return keyPair.publicKey; };

Signature signMessage(const std::string& message, HashAlgorithm hashAlg = HashAlgorithm::None);
Signature signMessage(const std::string& message, BigInt& K, HashAlgorithm hashAlg = HashAlgorithm::None);
bool verifySignature(const std::string& message, const ECDSAPublicKey& peerPublicKey, const Signature& signature, HashAlgorithm hashAlg = HashAlgorithm::None);
};
1 change: 1 addition & 0 deletions src/aes/aes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/

#include <string>
#include <cstring>
#include <iostream>

#include <gestalt/aes.h>
Expand Down
1 change: 1 addition & 0 deletions src/aes/aesCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
*/

#include <sstream>
#include <cstring>

#include "aesCore.h"
#include "aesConstants.h"
Expand Down
12 changes: 6 additions & 6 deletions src/ecc/ecc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,12 @@ bool ECC::isPointOnCurve(Point P) {
return (isInDomainRange(P.x)) && (isInDomainRange(P.y));
}

std::string ECC::isValidPublicKey(const Point P) {
if (!isPointOnCurve(P)) return "Error: Given Public Key is not on the curve.";
if (isIdentityPoint(P)) return "Error: Given Public Key is the Identity element.";
std::string ECC::isValidPublicKey(const ECDSAPublicKey P) {
if (!isPointOnCurve(P.getPublicKey())) return "Error: Given Public Key is not on the curve.";
if (isIdentityPoint(P.getPublicKey())) return "Error: Given Public Key is the Identity element.";

// Check n*P = identity
Point result = scalarMultiplyPoints(ellipticCurve.n, P);
Point result = scalarMultiplyPoints(ellipticCurve.n, P.getPublicKey());
if (!isIdentityPoint(result)) {
return "Error: Given Public key multiplied by curve modulus is not Identity Element.";
}
Expand All @@ -202,7 +202,7 @@ std::string ECC::isValidKeyPair(const KeyPair& K) {

// Check d*G = pubKey
Point result = scalarMultiplyPoints(K.privateKey, ellipticCurve.generator);
if (mpz_cmp(result.x, K.publicKey.x) != 0 || mpz_cmp(result.y, K.publicKey.y) != 0) {
if (mpz_cmp(result.x, K.publicKey.getPublicKey().x) != 0 || mpz_cmp(result.y, K.publicKey.getPublicKey().y) != 0) {
return "Error: Pair-wise consistency check failed.";
}

Expand Down Expand Up @@ -246,7 +246,7 @@ void ECC::setKeyPair(const std::string& givenKey) {
stringToGMP(givenKey, n);

KeyPair result(n, scalarMultiplyPoints(n, ellipticCurve.generator));
if(isIdentityPoint(result.publicKey)) throw
if(isIdentityPoint(result.publicKey.getPublicKey())) throw
std::invalid_argument("Error: Given Private Key derives identity public key.");

mpz_clear(n);
Expand Down
12 changes: 8 additions & 4 deletions src/ecc/ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#pragma once

#include "eccObjects.h"
#include "standardCurves.h"

class ECC {
private:
Expand All @@ -41,22 +40,27 @@ class ECC {
bool isInDomainRange(const mpz_t k);
bool isIdentityPoint(Point P);
bool isPointOnCurve(Point P);
std::string isValidPublicKey(const Point P);
std::string isValidPublicKey(const ECDSAPublicKey P);
std::string isValidKeyPair(const KeyPair& K);

friend class ECDSA;
friend class ECDH;
friend class ECC_Test;
public:

ECC(StandardCurve curve = StandardCurve::secp256k1) : ellipticCurve(getCurveParams(curve)) {}
ECC(StandardCurve curve = StandardCurve::secp256k1) : ellipticCurve(getCurveParams(curve)) {
keyPair.publicKey.setCurve(curve);
}

~ECC() {}

KeyPair generateKeyPair();

void setKeyPair(const KeyPair& newKeyPair);
void setKeyPair(const std::string& strKey);
void setCurve(StandardCurve curveType) { ellipticCurve = getCurveParams(curveType); }
void setCurve(StandardCurve curveType) {
ellipticCurve = getCurveParams(curveType);
keyPair.publicKey.setCurve(curveType);
}
KeyPair getKeyPair() const { return keyPair; }
};
64 changes: 61 additions & 3 deletions src/ecc/eccObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
#pragma once

//#include "standardCurves.h"

#include <string>
#include <gmp.h>

Expand Down Expand Up @@ -94,19 +96,73 @@ class Point {
Point setPoint(const std::string& strX, const std::string& strY) { return Point(strX, strY); };
};

#include "standardCurves.h"

class PublicKey {
private:
Point point;
StandardCurve curve;

StandardCurve guessCurve(const Point& point) {
size_t sizeInBytes = (mpz_sizeinbase(point.x, 2) + 7) / 8;
if (sizeInBytes == 32) {
return StandardCurve::P256;
} else if (sizeInBytes == 48) {
return StandardCurve::P384;
} else if (sizeInBytes == 66) {
return StandardCurve::P521;
} else {
return StandardCurve::secp256k1;
}
}

public:
// Constructors
PublicKey() : curve(StandardCurve::P256) {}
PublicKey(const std::string& strX, const std::string& strY) : point(Point(strX, strY)) {
curve = guessCurve(point);
}
PublicKey(const Point& publicKey) : point(publicKey) {
curve = guessCurve(publicKey);
}
PublicKey(const Point& publicKey, const StandardCurve& curve) : point(publicKey), curve(curve) {}

// Accessors
Point getPublicKey() const { return point; }
StandardCurve getPublicKeyCurve() const { return curve; }

void setCurve(const StandardCurve& givenCurve) { curve = givenCurve; }
};

class ECDSAPublicKey : public PublicKey{
public:
ECDSAPublicKey() : PublicKey() {}
ECDSAPublicKey(const std::string& strX, const std::string& strY) : PublicKey(strX, strY) {}
ECDSAPublicKey(const Point& point) : PublicKey(point) {}
ECDSAPublicKey(const Point& point, const StandardCurve& curve) : PublicKey(point, curve) {}
};

class ECDHPublicKey : public PublicKey{
public:
ECDHPublicKey() : PublicKey() {}
ECDHPublicKey(const std::string& strX, const std::string& strY) : PublicKey(strX, strY) {}
ECDHPublicKey(const Point& point) : PublicKey(point) {}
ECDHPublicKey(const Point& point, const StandardCurve& curve) : PublicKey(point, curve) {}
};

class KeyPair {
public:
mpz_t privateKey;
Point publicKey;
ECDSAPublicKey publicKey;

KeyPair() { mpz_init(privateKey); }
KeyPair(const mpz_t& gmpPriv, const Point& strPub) {
KeyPair(const mpz_t& gmpPriv, const ECDSAPublicKey& strPub) {
mpz_init(privateKey);
mpz_set(privateKey, gmpPriv);
publicKey = strPub;
}

KeyPair(const std::string& strPriv, const Point& strPub) {
KeyPair(const std::string& strPriv, const ECDSAPublicKey& strPub) {
mpz_init(privateKey);
stringToGMP(strPriv, privateKey);
publicKey = strPub;
Expand All @@ -123,6 +179,8 @@ class KeyPair {
}

~KeyPair() { mpz_clear(privateKey); }

Point getPublicKey() const { return publicKey.getPublicKey(); };
};

class Signature {
Expand Down
25 changes: 3 additions & 22 deletions src/ecc/ecdh/ecdh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,13 @@

#include <gestalt/ecdh.h>

Point ECDH::givePublicKey() const {
return keyPair.publicKey;
}

void ECDH::getPublicKey(const Point& givenPublicKey) {
std::string validationError = isValidPublicKey(givenPublicKey);
if (!validationError.empty()) {
throw std::invalid_argument(validationError);
}
peerPublicKey = givenPublicKey;
}

std::string ECDH::computeSharedSecret() {
Point sharedPoint = scalarMultiplyPoints(keyPair.privateKey, peerPublicKey);
if(isIdentityPoint(sharedPoint)) throw std::invalid_argument("Error: Computed shared value is Identity element.");
fieldElementToInteger(sharedPoint.x, sharedPoint.x);
return keyToString(sharedPoint);
}

std::string ECDH::computeSharedSecret(const Point& givenPeerPublicKey) {
std::string validationError = isValidPublicKey(givenPeerPublicKey);
std::string ECDH::computeSharedSecret(const ECDHPublicKey& givenPeerPublicKey) {
std::string validationError = isValidPublicKey(givenPeerPublicKey.getPublicKey());
if (!validationError.empty()) {
throw std::invalid_argument(validationError);
}

Point sharedPoint = scalarMultiplyPoints(keyPair.privateKey, givenPeerPublicKey);
Point sharedPoint = scalarMultiplyPoints(keyPair.privateKey, givenPeerPublicKey.getPublicKey());
if(isIdentityPoint(sharedPoint)) throw std::invalid_argument("Error: Computed shared value is Identity element.");
fieldElementToInteger(sharedPoint.x, sharedPoint.x);
return keyToString(sharedPoint);
Expand Down
Loading

0 comments on commit 18e2b87

Please sign in to comment.