#pragma once #include "DataView.hpp" #include #include namespace odhtdb { const int PUBLIC_KEY_NUM_BYTES = 32; const int PRIVATE_KEY_NUM_BYTES = 64; const int SIGNED_HASH_SIZE = 64; class InvalidSignatureKeySize : public std::runtime_error { public: InvalidSignatureKeySize(const std::string &errMsg) : std::runtime_error(errMsg) {} }; class SignatureGenerationException : public std::runtime_error { public: SignatureGenerationException(const std::string &errMsg) : std::runtime_error(errMsg) {} }; class DataSignException : public std::runtime_error { public: DataSignException(const std::string &errMsg) : std::runtime_error(errMsg) {} }; class UnsignException : public std::runtime_error { public: UnsignException(const std::string &errMsg) : std::runtime_error(errMsg) {} virtual ~UnsignException(){} }; class UnsignInvalidSizeException : public UnsignException { public: UnsignInvalidSizeException(const std::string &errMsg) : UnsignException(errMsg) {} }; class UnsignWrongKeyException : public UnsignException { public: UnsignWrongKeyException(const std::string &errMsg) : UnsignException(errMsg) {} }; namespace Signature { class PublicKey { friend class KeyPair; public: const static PublicKey ZERO; PublicKey(); // Throws InvalidSignatureKeySize if size is not PUBLIC_KEY_NUM_BYTES PublicKey(const char *data, size_t size); PublicKey(const PublicKey &other); PublicKey& operator=(const PublicKey &other); char* getData() { return data; } const char* getData() const { return data; } size_t getSize() const { return PUBLIC_KEY_NUM_BYTES; } // Throws UnsignWrongKeyException if signed message was not signed using the matching private key of this public key. // Throws UnsignInvalidSizeException if signed message is too small (< SIGNED_HASH_SIZE). // Both exceptions are derived from UnsignException std::string unsign(const DataView &signedMessage) const; size_t operator()() const; bool operator==(const PublicKey &other) const; bool operator!=(const PublicKey &other) const; std::string toString() const; private: char data[PUBLIC_KEY_NUM_BYTES]; }; struct PublicKeyHasher { size_t operator()(const PublicKey &publicKey) const { return publicKey(); } }; template using MapPublicKey = std::unordered_map; class PrivateKey { friend class KeyPair; public: const static PrivateKey ZERO; PrivateKey(); // Throws InvalidSignatureKeySize if size is not PRIVATE_KEY_NUM_BYTES PrivateKey(const char *data, size_t size); PrivateKey(const PrivateKey &other); PrivateKey& operator=(const PrivateKey &other); char* getData() { return data; } const char* getData() const { return data; } size_t getSize() const { return PRIVATE_KEY_NUM_BYTES; } bool operator==(const PrivateKey &other) const; bool operator!=(const PrivateKey &other) const; // Throws DataSignException if signing data failed for whatever reason. This wont happen unless there is an issue with the private key std::string sign(const DataView &dataToSign) const; std::string toString() const; private: char data[PRIVATE_KEY_NUM_BYTES]; }; class KeyPair { public: // Generate a new key pair, Throws SignatureGenerationException if generation of private/public key pair fails (should never happen) KeyPair(); // Create a key pair from existing public and private key KeyPair(const PublicKey &publicKey, const PrivateKey &privateKey); KeyPair(const KeyPair &other); const PublicKey& getPublicKey() const { return publicKey; } const PrivateKey& getPrivateKey() const { return privateKey; } private: PublicKey publicKey; PrivateKey privateKey; }; } }