#include "../include/odhtdb/Signature.hpp" #include "../include/odhtdb/Hash.hpp" #include "../include/odhtdb/bin2hex.hpp" #include #include using namespace std; namespace odhtdb { namespace Signature { const PublicKey PublicKey::ZERO("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", PUBLIC_KEY_NUM_BYTES); PublicKey::PublicKey() { memset(data, 0, PUBLIC_KEY_NUM_BYTES); } PublicKey::PublicKey(const char *_data, size_t size) { if(size != PUBLIC_KEY_NUM_BYTES) { string errMsg = "Expected public key size to be "; errMsg += to_string(PUBLIC_KEY_NUM_BYTES); errMsg += " bytes, was: "; errMsg += to_string(size); throw InvalidSignatureKeySize(errMsg); } memmove(data, _data, PUBLIC_KEY_NUM_BYTES); } PublicKey::PublicKey(const PublicKey &other) { memmove(data, other.data, PUBLIC_KEY_NUM_BYTES); } PublicKey& PublicKey::operator=(const PublicKey &other) { memmove(data, other.data, PUBLIC_KEY_NUM_BYTES); return *this; } string PublicKey::unsign(const DataView &signedMessage) const { if(signedMessage.size < SIGNED_HASH_SIZE) throw UnsignInvalidSizeException("Signed message is too small (corrupt or malicious signed message)"); string result; result.resize(signedMessage.size - SIGNED_HASH_SIZE); if(crypto_sign_ed25519_open((unsigned char*)&result[0], nullptr, (const unsigned char*)signedMessage.data, signedMessage.size, (unsigned char*)data) < 0) throw UnsignWrongKeyException("Message was not signed with matching private key"); return result; } size_t PublicKey::operator()() const { return fnvHash((const unsigned char*)data, PUBLIC_KEY_NUM_BYTES); } bool PublicKey::operator==(const PublicKey &other) const { return memcmp(data, other.data, PUBLIC_KEY_NUM_BYTES) == 0; } bool PublicKey::operator!=(const PublicKey &other) const { return !operator==(other); } string PublicKey::toString() const { return bin2hex(data, PUBLIC_KEY_NUM_BYTES); } const PrivateKey PrivateKey::ZERO("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", PRIVATE_KEY_NUM_BYTES); PrivateKey::PrivateKey() { memset(data, 0, PRIVATE_KEY_NUM_BYTES); } PrivateKey::PrivateKey(const char *_data, size_t size) { if(size != PRIVATE_KEY_NUM_BYTES) { string errMsg = "Expected private key size to be "; errMsg += to_string(PRIVATE_KEY_NUM_BYTES); errMsg += " bytes, was: "; errMsg += to_string(size); throw InvalidSignatureKeySize(errMsg); } memmove(data, _data, PRIVATE_KEY_NUM_BYTES); } PrivateKey::PrivateKey(const PrivateKey &other) { memmove(data, other.data, PRIVATE_KEY_NUM_BYTES); } PrivateKey& PrivateKey::operator=(const PrivateKey &other) { memmove(data, other.data, PRIVATE_KEY_NUM_BYTES); return *this; } bool PrivateKey::operator==(const PrivateKey &other) const { return memcmp(data, other.data, PRIVATE_KEY_NUM_BYTES) == 0; } bool PrivateKey::operator!=(const PrivateKey &other) const { return !operator==(other); } string PrivateKey::sign(const DataView &dataToSign) const { string result; result.resize(crypto_sign_ed25519_BYTES + dataToSign.size); unsigned long long resultSize; if(crypto_sign_ed25519((unsigned char*)&result[0], &resultSize, (unsigned char*)dataToSign.data, dataToSign.size, (unsigned char*)data) < 0) throw DataSignException("Failed to sign data. Is private key invalid?"); if(resultSize != result.size()) throw DataSignException("Failed to sign data. The signed data is not of expected size (bug)"); return result; } string PrivateKey::toString() const { return bin2hex(data, PRIVATE_KEY_NUM_BYTES); } KeyPair::KeyPair() { if(crypto_sign_ed25519_keypair((unsigned char*)publicKey.data, (unsigned char*)privateKey.data) < 0) throw SignatureGenerationException("Failed to generate signature keypair"); } KeyPair::KeyPair(const PublicKey &_publicKey, const PrivateKey &_privateKey) : publicKey(_publicKey), privateKey(_privateKey) { } KeyPair::KeyPair(const KeyPair &other) { memmove(publicKey.data, other.publicKey.data, PUBLIC_KEY_NUM_BYTES); memmove(privateKey.data, other.privateKey.data, PRIVATE_KEY_NUM_BYTES); } } }