aboutsummaryrefslogtreecommitdiff
path: root/src/signer/noscrypt_signer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/signer/noscrypt_signer.cpp')
-rw-r--r--src/signer/noscrypt_signer.cpp121
1 files changed, 100 insertions, 21 deletions
diff --git a/src/signer/noscrypt_signer.cpp b/src/signer/noscrypt_signer.cpp
index 26f8e54..c56070c 100644
--- a/src/signer/noscrypt_signer.cpp
+++ b/src/signer/noscrypt_signer.cpp
@@ -13,26 +13,22 @@ class NoscryptSigner : public INostrConnectSigner
public:
NoscryptSigner(shared_ptr<plog::IAppender> appender)
{
- // Set up the logger.
plog::init(plog::debug, appender.get());
- // Set up the noscrypt library.
- this->context = make_shared<NCContext>();
- auto contextStructSize = NCGetContextStructSize();
- unique_ptr<uint8_t[]> randomEntropy(new uint8_t[contextStructSize]);
-
- random_device device;
- mt19937 seed(device());
- uniform_int_distribution<int> distribution(1, NC_CONTEXT_ENTROPY_SIZE);
- generate_n(randomEntropy.get(), NC_CONTEXT_ENTROPY_SIZE, [&]() { return distribution(seed); });
+ this->noscryptContext = this->initNoscryptContext();
+ if (this->noscryptContext == nullptr)
+ {
+ return;
+ }
- NCResult result = NCInitContext(context.get(), randomEntropy.get());
- this->handleNoscryptInitResult(result);
+ const auto [privateKey, publicKey] = this->createLocalKeypair();
+ this->localPrivateKey = privateKey;
+ this->localPublicKey = publicKey;
};
~NoscryptSigner()
{
- NCDestroyContext(context.get());
+ NCDestroyContext(this->noscryptContext.get());
};
void receiveConnection(string connectionToken) override
@@ -55,36 +51,119 @@ public:
};
private:
- shared_ptr<NCContext> context;
+ shared_ptr<NCContext> noscryptContext;
+
+ string localPrivateKey;
+ string localPublicKey;
+
+ /**
+ * @brief Initializes the noscrypt library context into the class's `context` property.
+ * @returns `true` if successful, `false` otherwise.
+ */
+ shared_ptr<NCContext> initNoscryptContext()
+ {
+ shared_ptr<NCContext> context(new NCContext);
+ auto contextStructSize = NCGetContextStructSize();
+ unique_ptr<uint8_t> randomEntropy(new uint8_t[contextStructSize]);
+
+ random_device rd;
+ mt19937 gen(rd());
+ uniform_int_distribution<> dist(0, contextStructSize);
+ generate_n(randomEntropy.get(), contextStructSize, [&]() { return dist(gen); });
+
+ NCResult result = NCInitContext(context.get(), randomEntropy.get());
+ this->logNoscryptResult(result);
+
+ if (result != NC_SUCCESS)
+ {
+ return nullptr;
+ }
+
+ return context;
+ };
- void handleNoscryptInitResult(NCResult result)
+ void logNoscryptResult(NCResult result)
{
switch (result) {
case NC_SUCCESS:
- PLOG_INFO << "Successfully initialized noscrypt.";
+ PLOG_INFO << "noscrypt - success";
break;
case E_NULL_PTR:
- PLOG_ERROR << "Failed to initialize noscrypt: A null pointer was passed to the initializer.";
+ PLOG_ERROR << "noscrypt - error: A null pointer was passed to the initializer.";
break;
case E_INVALID_ARG:
- PLOG_ERROR << "Failed to initialize noscrypt: An invalid argument was passed to the initializer.";
+ PLOG_ERROR << "noscrypt - error: An invalid argument was passed to the initializer.";
break;
case E_INVALID_CONTEXT:
- PLOG_ERROR << "Failed to initialize noscrypt: The NCContext struct is in an invalid state.";
+ PLOG_ERROR << "noscrypt - error: The NCContext struct is in an invalid state.";
break;
case E_ARGUMENT_OUT_OF_RANGE:
- PLOG_ERROR << "Failed to initialize noscrypt: An initializer argument was outside the range of acceptable values.";
+ PLOG_ERROR << "noscrypt - error: An initializer argument was outside the range of acceptable values.";
break;
case E_OPERATION_FAILED:
- PLOG_ERROR << "Failed to initialize noscrypt.";
+ PLOG_ERROR << "noscrypt - error";
break;
}
};
+
+ /**
+ * @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.
+ */
+ tuple<string, string> createLocalKeypair()
+ {
+ string privateKey;
+ string publicKey;
+
+ // To generate a private key, all we need is a random 32-bit buffer.
+ unique_ptr<NCSecretKey> secretKey(new NCSecretKey);
+
+ random_device rd;
+ mt19937 gen(rd());
+ uniform_int_distribution<> dist(0, NC_SEC_KEY_SIZE);
+ generate_n(secretKey.get()->key, NC_SEC_KEY_SIZE, [&]() { return dist(gen); });
+
+ // Convert the buffer into a hex string for a more human-friendly representation.
+ stringstream secretKeyStream;
+ for (int i = 0; i < NC_SEC_KEY_SIZE; i++)
+ {
+ secretKeyStream << hex << setw(2) << setfill('0') << static_cast<int>(secretKey->key[i]);
+ }
+ privateKey = secretKeyStream.str();
+
+ // Use noscrypt to derive the public key from its private counterpart.
+ unique_ptr<NCPublicKey> pubkey(new NCPublicKey);
+ NCResult result = NCGetPublicKey(
+ this->noscryptContext.get(),
+ secretKey.get(),
+ pubkey.get());
+ this->logNoscryptResult(result);
+
+ if (result != NC_SUCCESS)
+ {
+ // Return empty strings if the key generation fails.
+ return make_tuple(string(), string());
+ }
+
+ // Convert the now-populated pubkey buffer into a hex string for the pubkey representation
+ // used by Nostr events.
+ stringstream pubkeyStream;
+ for (int i = 0; i < NC_SEC_KEY_SIZE; i++)
+ {
+ pubkeyStream << hex << setw(2) << setfill('0') << static_cast<int>(pubkey->key[i]);
+ }
+ publicKey = pubkeyStream.str();
+
+ return make_tuple(privateKey, publicKey);
+ };
};
} // namespace signer
} // namespace nostr