diff options
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | include/signer/noscrypt_signer.hpp | 16 | ||||
-rw-r--r-- | src/cryptography/noscrypt_cipher.cpp | 109 | ||||
-rw-r--r-- | src/cryptography/noscrypt_cipher.hpp (renamed from include/cryptography/noscrypt_cipher.hpp) | 68 | ||||
-rw-r--r-- | src/cryptography/nostr_secure_rng.cpp | 46 | ||||
-rw-r--r-- | src/cryptography/nostr_secure_rng.hpp | 51 | ||||
-rw-r--r-- | src/internal/noscrypt_logger.hpp | 43 | ||||
-rw-r--r-- | src/signer/noscrypt_signer.cpp | 273 |
8 files changed, 325 insertions, 285 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b875512..889f19d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ include_directories(${uuid_v4_SOURCE_DIR}) FetchContent_Declare( libnoscrypt GIT_REPOSITORY git@github.com:VnUgE/noscrypt.git - GIT_TAG fb3608b9455b3e0956e401e6254da13cebd71558 + GIT_TAG v0.1.5 ) FetchContent_MakeAvailable(libnoscrypt) @@ -86,7 +86,6 @@ set(HEADERS ${INCLUDE_DIR}/nostr.hpp ${CLIENT_INCLUDE_DIR}/web_socket_client.hpp ${CLIENT_INCLUDE_DIR}/websocketpp_client.hpp - ${CRYPTOGRAPHY_INCLUDE_DIR}/noscrypt_cipher.hpp ${DATA_INCLUDE_DIR}/data.hpp ${SERVICE_INCLUDE_DIR}/nostr_service_base.hpp ${SIGNER_INCLUDE_DIR}/signer.hpp @@ -102,6 +101,7 @@ set(SIGNER_SOURCE_DIR ./src/signer) set(SOURCES ${CLIENT_SOURCE_DIR}/websocketpp_client.cpp ${CRYPTOGRAPHY_SOURCE_DIR}/noscrypt_cipher.cpp + ${CRYPTOGRAPHY_SOURCE_DIR}/nostr_secure_rng.cpp ${DATA_SOURCE_DIR}/event.cpp ${DATA_SOURCE_DIR}/filters.cpp ${SERVICE_SOURCE_DIR}/nostr_service_base.cpp diff --git a/include/signer/noscrypt_signer.hpp b/include/signer/noscrypt_signer.hpp index 85188fa..0a7d0fd 100644 --- a/include/signer/noscrypt_signer.hpp +++ b/include/signer/noscrypt_signer.hpp @@ -146,12 +146,6 @@ private: #pragma region Cryptography /** - * @brief Reseeds OpenSSL's pseudo-random number generator, using `/dev/random` as the seed, if - * possible. - */ - void _reseedRandomNumberGenerator(uint32_t bufferSize = 32); - - /** * @brief Encrypts a string according to the standard specified in NIP-04. * @param input The string to be encrypted. * @return The resulting encrypted string, or an empty string if the input could not be @@ -182,16 +176,6 @@ private: std::string _decryptNip44(const std::string input); #pragma endregion - - #pragma region Logging - - inline void _logNoscryptInitResult(NCResult initResult) const; - - inline void _logNoscryptSecretValidationResult(NCResult secretValidationResult) const; - - inline void _logNoscryptPubkeyGenerationResult(NCResult pubkeyGenerationResult) const; - - #pragma endregion }; } // namespace signer } // namespace nostr diff --git a/src/cryptography/noscrypt_cipher.cpp b/src/cryptography/noscrypt_cipher.cpp index ae9aaf0..2d5d671 100644 --- a/src/cryptography/noscrypt_cipher.cpp +++ b/src/cryptography/noscrypt_cipher.cpp @@ -2,49 +2,16 @@ #include <plog/Log.h> #include <openssl/evp.h> -#include <openssl/rand.h> -#include "cryptography/noscrypt_cipher.hpp" +#include "nostr_secure_rng.hpp" +#include "noscrypt_cipher.hpp" +#include "../internal/noscrypt_logger.hpp" -using namespace nostr::cryptography; using namespace std; +using namespace nostr::cryptography; -static void _printNoscryptError(NCResult result, const std::string funcName, int lineNum) -{ - uint8_t argPosition; - - switch (NCParseErrorCode(result, &argPosition)) - { - case E_NULL_PTR: - PLOG_ERROR << "noscrypt - error: A null pointer was passed in " << funcName << "(" << argPosition << ") at line " << lineNum; - break; - - case E_INVALID_ARG: - PLOG_ERROR << "noscrypt - error: An invalid argument was passed in " << funcName << "(" << argPosition << ") at line " << lineNum; - break; - - case E_INVALID_CONTEXT: - PLOG_ERROR << "noscrypt - error: An invalid context was passed in " << funcName << "(" << argPosition << ") on line " << lineNum; - break; - - case E_ARGUMENT_OUT_OF_RANGE: - PLOG_ERROR << "noscrypt - error: An argument was out of range in " << funcName << "(" << argPosition << ") at line " << lineNum; - break; - - case E_OPERATION_FAILED: - PLOG_ERROR << "noscrypt - error: An operation failed in " << funcName << "(" << argPosition << ") at line " << lineNum; - break; - - default: - PLOG_ERROR << "noscrypt - error: An unknown error " << result << " occurred in " << funcName << "(" << argPosition << ") at line " << lineNum; - break; - } - -} - -#define LOG_NC_ERROR(result) _printNoscryptError(result, __func__, __LINE__) -NoscryptCipher::NoscryptCipher(uint32_t version, uint32_t mode) : +NoscryptCipher::NoscryptCipher(NoscryptCipherVersion version, NoscryptCipherMode mode) : _cipher(version, mode) { /* @@ -54,7 +21,7 @@ NoscryptCipher::NoscryptCipher(uint32_t version, uint32_t mode) : * operation. */ - if ((mode & NC_UTIL_CIPHER_MODE) == NC_UTIL_CIPHER_MODE_ENCRYPT) + if (mode == NoscryptCipherMode::CIPHER_MODE_ENCRYPT) { //Resize the vector to the size of the current cipher this->_ivBuffer.resize(this->_cipher.ivSize()); @@ -82,10 +49,10 @@ std::string NoscryptCipher::update( //Safely convert the string to a vector of bytes (allocates and copies, so maybe speed up later) const vector<uint8_t> inputBuffer(input.begin(), input.end()); -result = this->_cipher.setInput(inputBuffer); + result = this->_cipher.setInput(inputBuffer); if (result != NC_SUCCESS) { - LOG_NC_ERROR(result); + NC_LOG_ERROR(result); return string(); } @@ -97,25 +64,17 @@ result = this->_cipher.setInput(inputBuffer); * Keep in mind, this will automatically work for nip44 and nip04, either the * AES iv or the ChaCha nonce. */ - if ((this->_cipher.flags() & NC_UTIL_CIPHER_MODE) == NC_UTIL_CIPHER_MODE_ENCRYPT) + if (this->_cipher.mode() == NoscryptCipherMode::CIPHER_MODE_ENCRYPT) { - int code = RAND_bytes( - this->_ivBuffer.data(), - this->_ivBuffer.size() //Size set in constructor - ); - - if (code <= 0) - { - PLOG_ERROR << "Failed to generate a nonce or IV for encryption."; - return string(); - } + //A secure random initialization vector is needed for encryption operations + NostrSecureRng::fill(this->_ivBuffer); } //Performs the operation (either encryption or decryption) result = this->_cipher.update(libContext, localKey, remoteKey); if (result != NC_SUCCESS) { - LOG_NC_ERROR(result); + NC_LOG_ERROR(result); return string(); } @@ -127,7 +86,7 @@ result = this->_cipher.setInput(inputBuffer); NCResult outputSize = this->_cipher.outputSize(); if (outputSize <= 0) { - LOG_NC_ERROR(outputSize); + NC_LOG_ERROR(outputSize); return string(); } @@ -137,7 +96,7 @@ result = this->_cipher.setInput(inputBuffer); result = this->_cipher.readOutput(output); if (result != outputSize) { - LOG_NC_ERROR(result); + NC_LOG_ERROR(result); return string(); } @@ -148,36 +107,40 @@ string NoscryptCipher::naiveEncodeBase64(const std::string& str) { // Compute base64 size and allocate a string buffer of that size. const size_t encodedSize = NoscryptCipher::base64EncodedSize(str.size()); - unsigned char* encodedData = new unsigned char[encodedSize]; + + auto encodedData = make_unique<uint8_t>(encodedSize); // Encode the input string to base64. - EVP_EncodeBlock(encodedData, (const unsigned char*)str.data(), str.size()); + EVP_EncodeBlock( + encodedData.get(), + reinterpret_cast<const uint8_t*>(str.c_str()), + str.size() + ); // Construct the encoded string from the buffer. - string encodedStr((char*)encodedData); - - // Zero out the buffer and delete the pointer. - memset(encodedData, 0, encodedSize); - delete [] encodedData; - - return encodedStr; + return string( + reinterpret_cast<char*>(encodedData.get()), + encodedSize + ); } string NoscryptCipher::naiveDecodeBase64(const string& str) { // Compute the size of the decoded string and allocate a buffer of that size. const size_t decodedSize = NoscryptCipher::base64DecodedSize(str.size()); - unsigned char* decodedData = new unsigned char[decodedSize]; + + auto decodedData = make_unique<uint8_t>(decodedSize); // Decode the input string from base64. - EVP_DecodeBlock(decodedData, (const unsigned char*)str.data(), str.size()); + EVP_DecodeBlock( + decodedData.get(), + reinterpret_cast<const uint8_t*>(str.c_str()), + str.size() + ); // Construct the decoded string from the buffer. - string decodedStr((char*)decodedData); - - // Zero out the buffer and delete the pointer. - memset(decodedData, 0, decodedSize); - delete [] decodedData; - - return decodedStr; + return string( + reinterpret_cast<char*>(decodedData.get()), + decodedSize + ); }; diff --git a/include/cryptography/noscrypt_cipher.hpp b/src/cryptography/noscrypt_cipher.hpp index 3337240..04bdbf2 100644 --- a/include/cryptography/noscrypt_cipher.hpp +++ b/src/cryptography/noscrypt_cipher.hpp @@ -4,11 +4,25 @@ #include <noscrypt.h> #include <noscryptutil.h> +#include "../internal/noscrypt_logger.hpp" namespace nostr { namespace cryptography { + +enum NoscryptCipherMode : uint32_t +{ + CIPHER_MODE_ENCRYPT = NC_UTIL_CIPHER_MODE_ENCRYPT, + CIPHER_MODE_DECRYPT = NC_UTIL_CIPHER_MODE_DECRYPT, +}; + +enum NoscryptCipherVersion : uint32_t +{ + NIP04 = NC_ENC_VERSION_NIP04, + NIP44 = NC_ENC_VERSION_NIP44, +}; + class NoscryptCipherContext { private: @@ -16,30 +30,30 @@ private: public: - NoscryptCipherContext(uint32_t version, uint32_t mode) + NoscryptCipherContext(NoscryptCipherVersion version, NoscryptCipherMode mode) { - /* - * Create a new cipher context with the specified - * version and mode that will live for the duration of the - * instance. - * - * The user is expected to use the noscryptutil mode for - * setting encryption/decryption modes. - * - * The cipher will zero out the memory when it is freed. - * - * For decryption, by default the mac is verified before - * decryption occurs. - * - * NOTE: The ciper is set to reusable mode, so encrypt/decrypt - * can be called multiple times although it's not recommended, - * its just the more predictable way for users to handle it. - */ - - _cipher = NCUtilCipherAlloc( - version, - mode | NC_UTIL_CIPHER_ZERO_ON_FREE | NC_UTIL_CIPHER_REUSEABLE - ); + /* + * Create a new cipher context with the specified + * version and mode that will live for the duration of the + * instance. + * + * The user is expected to use the noscryptutil mode for + * setting encryption/decryption modes. + * + * The cipher will zero out the memory when it is freed. + * + * For decryption, by default the mac is verified before + * decryption occurs. + * + * NOTE: The ciper is set to reusable mode, so encrypt/decrypt + * can be called multiple times although it's not recommended, + * its just the more predictable way for users to handle it. + */ + + _cipher = NCUtilCipherAlloc( + (uint32_t)version, + ((uint32_t)mode) | NC_UTIL_CIPHER_ZERO_ON_FREE | NC_UTIL_CIPHER_REUSEABLE + ); //TODO, may fail to allocate memory. } @@ -95,6 +109,12 @@ public: return (uint32_t)result; } + NoscryptCipherMode mode() const + { + //Mode bit is lsb so just mask off the rest of the flags and convert back to enum + return (NoscryptCipherMode)(flags() & NC_UTIL_CIPHER_MODE); + } + NCResult readOutput(std::vector<uint8_t>& output) const { return NCUtilCipherReadOutput(_cipher, output.data(), (uint32_t)output.size()); @@ -125,7 +145,7 @@ private: std::vector<uint8_t> _ivBuffer; public: - NoscryptCipher(uint32_t version, uint32_t mode); + NoscryptCipher(NoscryptCipherVersion version, NoscryptCipherMode mode); /* * @brief Performs the cipher operation on the input data. Depending on the mode diff --git a/src/cryptography/nostr_secure_rng.cpp b/src/cryptography/nostr_secure_rng.cpp new file mode 100644 index 0000000..9d92514 --- /dev/null +++ b/src/cryptography/nostr_secure_rng.cpp @@ -0,0 +1,46 @@ +#include <plog/Init.h> +#include <plog/Log.h> + +#include <openssl/evp.h> +#include <openssl/rand.h> +#include <openssl/crypto.h> + +#include "nostr_secure_rng.hpp" + +using namespace std; +using namespace nostr::cryptography; + +void NostrSecureRng::fill(void* buffer, size_t length) +{ + if (RAND_bytes((uint8_t*)buffer, length) != 1) + { + //TODO throw runtime exception + PLOG_ERROR << "Failed to generate random bytes"; + } +} + +inline void NostrSecureRng::fill(vector<uint8_t>& buffer) +{ + fill(buffer.data(), buffer.size()); +} + +void NostrSecureRng::reseed(uint32_t bufferSize) +{ + int rc = RAND_load_file("/dev/random", bufferSize); + + if (rc != bufferSize) + { + PLOG_WARNING << "Failed to reseed the RNG with /dev/random, falling back to /dev/urandom."; + RAND_poll(); + } +} + +void NostrSecureRng::zero(void* buffer, size_t length) +{ + OPENSSL_cleanse(buffer, length); +} + +inline void NostrSecureRng::zero(vector<uint8_t>& buffer) +{ + zero(buffer.data(), buffer.size()); +}
\ No newline at end of file diff --git a/src/cryptography/nostr_secure_rng.hpp b/src/cryptography/nostr_secure_rng.hpp new file mode 100644 index 0000000..7fa340e --- /dev/null +++ b/src/cryptography/nostr_secure_rng.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include <memory> + +namespace nostr +{ +namespace cryptography +{ + +class NostrSecureRng +{ +private: + +public: + + /** + * @brief Fills the given buffer with secure random bytes. + * @param buffer The buffer to fill with random bytes. + * @param length The number of bytes to fill. + */ + static void fill(void* buffer, size_t length); + + /* + * @brief Fills the given vector with secure random bytes. + * @param buffer The vector to fill with random bytes. + */ + static inline void fill(std::vector<uint8_t>& buffer); + + /* + * @brief Reseeds the RNG with random bytes from /dev/random. + * @param bufferSize The number of bytes to read from /dev/random. + * @remark Falls back to /dev/urandom if /dev/random is not available. + */ + static void reseed(uint32_t bufferSize = 32); + + /* + * @brief Securley zeroes out the given buffer. + * @param buffer A pointer to the buffer to zero out. + * @param length The number of bytes to zero out. + */ + static void zero(void* buffer, size_t length); + + /* + * @brief Securley zeroes out the given vector. + * @param buffer The vector to zero out. + */ + static inline void zero(std::vector<uint8_t>& buffer); +}; + +} // namespace cryptography +} // namespace nostr diff --git a/src/internal/noscrypt_logger.hpp b/src/internal/noscrypt_logger.hpp new file mode 100644 index 0000000..b767b81 --- /dev/null +++ b/src/internal/noscrypt_logger.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include <plog/Log.h> +#include <noscrypt.h> + +/* +* @brief Logs an error message with the function name and line number where the +* error occurred. This is useful for debugging and logging errors in the Noscrypt +* library. +*/ +#define NC_LOG_ERROR(result) _printNoscryptError(result, __func__, __LINE__) + +static inline void _printNoscryptError(NCResult result, const std::string funcName, int lineNum) +{ + uint8_t argPosition; + + switch (NCParseErrorCode(result, &argPosition)) + { + case E_NULL_PTR: + PLOG_ERROR << "noscrypt - error: A null pointer was passed in " << funcName << "(" << argPosition << ") at line " << lineNum; + break; + + case E_INVALID_ARG: + PLOG_ERROR << "noscrypt - error: An invalid argument was passed in " << funcName << "(" << argPosition << ") at line " << lineNum; + break; + + case E_INVALID_CONTEXT: + PLOG_ERROR << "noscrypt - error: An invalid context was passed in " << funcName << "(" << argPosition << ") on line " << lineNum; + break; + + case E_ARGUMENT_OUT_OF_RANGE: + PLOG_ERROR << "noscrypt - error: An argument was out of range in " << funcName << "(" << argPosition << ") at line " << lineNum; + break; + + case E_OPERATION_FAILED: + PLOG_ERROR << "noscrypt - error: An operation failed in " << funcName << "(" << argPosition << ") at line " << lineNum; + break; + + default: + PLOG_ERROR << "noscrypt - error: An unknown error " << result << " occurred in " << funcName << "(" << argPosition << ") at line " << lineNum; + break; + } +} diff --git a/src/signer/noscrypt_signer.cpp b/src/signer/noscrypt_signer.cpp index 2b87703..d12bd44 100644 --- a/src/signer/noscrypt_signer.cpp +++ b/src/signer/noscrypt_signer.cpp @@ -2,23 +2,87 @@ #include <chrono> #include <cstring> #include <memory> -#include <random> #include <sstream> #include <tuple> #include <nlohmann/json.hpp> -#include <openssl/err.h> -#include <openssl/rand.h> #include <uuid_v4.h> #include "signer/noscrypt_signer.hpp" -#include "noscrypt_cipher.hpp" +#include "../cryptography/nostr_secure_rng.hpp" +#include "../cryptography/noscrypt_cipher.hpp" +#include "../internal/noscrypt_logger.hpp" +using namespace std; using namespace nostr::data; using namespace nostr::service; using namespace nostr::signer; using namespace nostr::cryptography; -using namespace std; + +#pragma region Local Statics + +static shared_ptr<NCContext> ncAllocContext() +{ + /* + * Use the utilties library to allocate a new Noscrypt context. + * Shared pointer will call free when smart pointer is destroyed + */ + + return shared_ptr<NCContext>( + NCUtilContextAlloc(), + &NCUtilContextFree + ); +} + +static shared_ptr<NCContext> initNoscryptContext() +{ + //Use helper to allocate a dynamic sized shared pointer + auto ctx = ncAllocContext(); + + auto randomEntropy = make_unique<uint8_t>(NC_CONTEXT_ENTROPY_SIZE); + NostrSecureRng::fill(randomEntropy.get(), NC_CONTEXT_ENTROPY_SIZE); + + NCResult initResult = NCInitContext(ctx.get(), randomEntropy.get()); + + NC_LOG_ERROR(initResult); + + return ctx; +}; + +/** + * @brief Generates a private/public key pair for local use. + * @returns The generated keypair of the form `[privateKey, publicKey]`, or a pair of empty + * strings if the function failed. + * @remarks This keypair is intended for temporary use, and should not be saved or used outside + * of this class. + */ +static void createLocalKeypair( + const shared_ptr<const NCContext> ctx, + shared_ptr<NCSecretKey> secret, + shared_ptr<NCPublicKey> pubkey +) +{ + // Loop attempts to generate a secret key until a valid key is produced. + // Limit the number of attempts to prevent resource exhaustion in the event of a failure. + NCResult secretValidationResult; + int loopCount = 0; + do + { + NostrSecureRng::fill(secret.get(), sizeof(NCSecretKey)); + + secretValidationResult = NCValidateSecretKey(ctx.get(), secret.get()); + + } while (secretValidationResult != NC_SUCCESS && ++loopCount < 64); + + NC_LOG_ERROR(secretValidationResult); + + // Use noscrypt to derive the public key from its private counterpart. + NCResult pubkeyGenerationResult = NCGetPublicKey(ctx.get(), secret.get(), pubkey.get()); + + NC_LOG_ERROR(pubkeyGenerationResult); +}; + +#pragma endregion #pragma region Constructors and Destructors @@ -28,9 +92,13 @@ NoscryptSigner::NoscryptSigner( { plog::init(plog::debug, appender.get()); - this->_reseedRandomNumberGenerator(); - this->_initNoscryptContext(); - this->_createLocalKeypair(); + this->_noscryptContext = initNoscryptContext(); + + createLocalKeypair( + this->_noscryptContext, + this->_localPrivateKey, + this->_localPublicKey + ); this->_nostrService = nostrService; }; @@ -258,67 +326,6 @@ inline void NoscryptSigner::_setRemotePublicKey(const string value) #pragma region Setup -void NoscryptSigner::_initNoscryptContext() -{ - shared_ptr<NCContext> context; - auto contextStructSize = NCGetContextStructSize(); - auto randomEntropy = make_unique<uint8_t>(contextStructSize); - - random_device rd; - mt19937 gen(rd()); - uniform_int_distribution<> dist(0, contextStructSize); - generate_n(randomEntropy.get(), contextStructSize, [&]() { return dist(gen); }); - - NCResult initResult = NCInitContext(context.get(), randomEntropy.get()); - this->_logNoscryptInitResult(initResult); - - this->_noscryptContext = move(context); -}; - -/** - * @brief Generates a private/public key pair for local use. - * @returns The generated keypair of the form `[privateKey, publicKey]`, or a pair of empty - * strings if the function failed. - * @remarks This keypair is intended for temporary use, and should not be saved or used outside - * of this class. - */ -void NoscryptSigner::_createLocalKeypair() -{ - string privateKey; - string publicKey; - - // To generate a private key, all we need is a random 32-bit buffer. - auto secret = make_unique<NCSecretKey>(); - - // Loop attempts to generate a secret key until a valid key is produced. - // Limit the number of attempts to prevent resource exhaustion in the event of a failure. - NCResult secretValidationResult; - int loopCount = 0; - do - { - int rc = RAND_bytes(secret->key, sizeof(NCSecretKey)); - if (rc != 1) - { - unsigned long err = ERR_get_error(); - PLOG_ERROR << "OpenSSL error " << err << " occurred while generating a secret key."; - } - - secretValidationResult = NCValidateSecretKey(this->_noscryptContext.get(), secret.get()); - } while (secretValidationResult != NC_SUCCESS && ++loopCount < 64); - - this->_logNoscryptSecretValidationResult(secretValidationResult); - this->_localPrivateKey = move(secret); - - // Use noscrypt to derive the public key from its private counterpart. - auto pubkey = make_unique<NCPublicKey>(); - NCResult pubkeyGenerationResult = NCGetPublicKey( - this->_noscryptContext.get(), - secret.get(), - pubkey.get()); - this->_logNoscryptPubkeyGenerationResult(pubkeyGenerationResult); - this->_localPublicKey = move(pubkey); -}; - int NoscryptSigner::_parseRemotePublicKey(string connectionToken) { int queryStart = connectionToken.find('?'); @@ -403,35 +410,39 @@ shared_ptr<Event> NoscryptSigner::_wrapSignerMessage(nlohmann::json jrpc) wrapperEvent->tags.push_back({ "p", this->_getRemotePublicKey() }); wrapperEvent->content = encryptedContent; - // Generate a random seed for the signer. - auto random32 = make_shared<uint8_t>(32); - int code = RAND_bytes(random32.get(), 32); - if (code <= 0) - { - PLOG_ERROR << "Failed to generate a random 32-byte seed buffer for the signer."; - return nullptr; - } + uint8_t schnorrSig[64]; + uint8_t random32[32]; + + //Secure random signing entropy is required + NostrSecureRng::fill(random32, sizeof(random32)); // Sign the wrapper message with the local secret key. string serializedEvent = wrapperEvent->serialize(); - uint32_t dataSize = serializedEvent.length(); - auto signature = make_unique<uint8_t>(64); + NCResult signatureResult = NCSignData( this->_noscryptContext.get(), this->_localPrivateKey.get(), - random32.get(), - reinterpret_cast<uint8_t*>(serializedEvent.data()), - dataSize, - signature.get()); + random32, + reinterpret_cast<const uint8_t*>(serializedEvent.c_str()), + serializedEvent.length(), + schnorrSig + ); + + //Random buffer could leak sensitive signing information + NostrSecureRng::zero(random32, sizeof(random32)); // TODO: Handle result codes. if (signatureResult != NC_SUCCESS) { + NC_LOG_ERROR(signatureResult); return nullptr; } // Add the signature to the event. - wrapperEvent->sig = string((char*)signature.get(), 64); + wrapperEvent->sig = string( + reinterpret_cast<char*>(schnorrSig), + sizeof(schnorrSig) + ); return wrapperEvent; }; @@ -512,16 +523,6 @@ promise<bool> NoscryptSigner::_pingSigner() #pragma region Cryptography -void NoscryptSigner::_reseedRandomNumberGenerator(uint32_t bufferSize) -{ - int rc = RAND_load_file("/dev/random", bufferSize); - if (rc != bufferSize) - { - PLOG_WARNING << "Failed to reseed the RNG with /dev/random, falling back to /dev/urandom."; - RAND_poll(); - } -}; - string NoscryptSigner::_encryptNip04(std::string input) { throw runtime_error("NIP-04 encryption is not yet implemented."); @@ -534,7 +535,10 @@ string NoscryptSigner::_decryptNip04(string input) string NoscryptSigner::_encryptNip44(string input) { - NoscryptCipher cipher = NoscryptCipher(NC_ENC_VERSION_NIP44, NC_UTIL_CIPHER_MODE_ENCRYPT); + NoscryptCipher cipher = NoscryptCipher( + NoscryptCipherVersion::NIP44, + NoscryptCipherMode::CIPHER_MODE_ENCRYPT + ); auto output = cipher.update( this->_noscryptContext, @@ -552,7 +556,10 @@ string NoscryptSigner::_decryptNip44(string input) { //TODO handle input validation as per nip44 spec - NoscryptCipher cipher = NoscryptCipher(NC_ENC_VERSION_NIP44, NC_UTIL_CIPHER_MODE_DECRYPT); + NoscryptCipher cipher = NoscryptCipher( + NoscryptCipherVersion::NIP44, + NoscryptCipherMode::CIPHER_MODE_DECRYPT + ); return cipher.update( this->_noscryptContext, @@ -564,77 +571,3 @@ string NoscryptSigner::_decryptNip44(string input) #pragma endregion -#pragma region Logging - -inline void NoscryptSigner::_logNoscryptInitResult(NCResult initResult) const -{ - switch (NCParseErrorCode(initResult, NULL)) { - case NC_SUCCESS: - PLOG_INFO << "noscrypt - success"; - break; - - case E_NULL_PTR: - PLOG_ERROR << "noscrypt - error: A null pointer was passed to the initializer."; - break; - - case E_INVALID_ARG: - PLOG_ERROR << "noscrypt - error: An invalid argument was passed to the initializer."; - break; - - case E_INVALID_CONTEXT: - PLOG_ERROR << "noscrypt - error: The NCContext struct is in an invalid state."; - break; - - case E_ARGUMENT_OUT_OF_RANGE: - PLOG_ERROR << "noscrypt - error: An initializer argument was outside the range of acceptable values."; - break; - - case E_OPERATION_FAILED: - PLOG_ERROR << "noscrypt - error"; - break; - } -}; - -inline void NoscryptSigner::_logNoscryptSecretValidationResult(NCResult secretValidationResult) const -{ - if (NCParseErrorCode(secretValidationResult, NULL) == NC_SUCCESS) - { - PLOG_INFO << "noscrypt_signer - success: Generated a valid secret key."; - } - else - { - PLOG_ERROR << "noscrypt_signer - error: Failed to generate a valid secret key."; - } -}; - -inline void NoscryptSigner::_logNoscryptPubkeyGenerationResult(NCResult pubkeyGenerationResult) const -{ - - switch (NCParseErrorCode(pubkeyGenerationResult, NULL)) { - case NC_SUCCESS: - PLOG_INFO << "noscrypt - success: Generated a valid public key."; - break; - - case E_NULL_PTR: - PLOG_ERROR << "noscrypt - error: A null pointer was passed to the public key generation function."; - break; - - case E_INVALID_ARG: - PLOG_ERROR << "noscrypt - error: An invalid argument was passed to the public key generation function."; - break; - - case E_INVALID_CONTEXT: - PLOG_ERROR << "noscrypt - error: The NCContext struct is in an invalid state."; - break; - - case E_ARGUMENT_OUT_OF_RANGE: - PLOG_ERROR << "noscrypt - error: An argument was outside the range of acceptable values."; - break; - - case E_OPERATION_FAILED: - PLOG_ERROR << "noscrypt - error: Failed to generate the public key from the secret key."; - break; - } -}; - -#pragma endregion |