aboutsummaryrefslogtreecommitdiff
path: root/include/signer/noscrypt_signer.hpp
blob: 79359f35c0f7eeb1e3f38c4ab9e4b341eeba5bc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#pragma once

#include <plog/Init.h>
#include <plog/Log.h>
#include <noscrypt.h>

#include "service/nostr_service_base.hpp"
#include "signer/signer.hpp"

namespace nostr
{
namespace signer
{
class NoscryptSigner : public INostrConnectSigner
{
public:
    NoscryptSigner(
        std::shared_ptr<plog::IAppender> appender,
        std::shared_ptr<nostr::service::INostrServiceBase> nostrService);

    ~NoscryptSigner();

    void receiveConnection(std::string connectionToken) override;

    std::string initiateConnection(
        std::vector<std::string> relays,
        std::string name,
        std::string url,
        std::string description) override;

    std::shared_ptr<std::promise<bool>> sign(std::shared_ptr<data::Event> event) override;

private:
    const int _nostrConnectKind = 24133; // Kind 24133 is reserved for NIP-46 events.

    Encryption _nostrConnectEncryption;

    std::shared_ptr<NCContext> _noscryptContext;
    std::shared_ptr<nostr::service::INostrServiceBase> _nostrService;

    std::shared_ptr<NCPublicKey> _remotePubkey; // TODO: Set this when available.
    std::shared_ptr<NCSecretKey> _localSecret;

    std::string _localPrivateKey;
    std::string _localPublicKey;

    std::string _remotePublicKey;
    std::string _bunkerSecret;

    ///< A list of relays that will be used to connect to the remote signer.
    std::vector<std::string> _relays;
    
    /**
     * @brief Initializes the noscrypt library context into the class's `context` property.
     * @returns `true` if successful, `false` otherwise.
     */
    std::shared_ptr<NCContext> _initNoscryptContext();

    /**
     * @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.
     */
    std::tuple<std::string, std::string> _createLocalKeypair();

    /**
     * @brief Parses the remote signer npub from a connection token provided by the signer.
     * @param connectionToken A connection token beginning with `bunker://`.
     * @returns The index of the first character of the connection token's query string, or -1 if
     * no valid public key could be parsed.
     * @remark This function updates the `_remotePublicKey` string in its class instance by side
     * effect.
     */
    int _parseRemotePublicKey(std::string connectionToken);

    /**
     * @brief Parses a single query param from a connection token provided by a remote signer.
     * @param param A single query param from the connection token of the form `key=value`.
     * @remark This function updates the `_relays` vector and the `_bunkerSecret` string in its
     * class instance by side effect.
     */
    void _handleConnectionTokenParam(std::string param);

    /**
     * @brief Generates a unique ID for a signer request.
     * @returns A GUID string.
     */
    std::string _generateSignerRequestId();

    /**
     * @brief Builds and signs a wrapper event for JRPC-like signer messages.
     * @param jrpc The JRPC-like payload that will comprise the event content, as specified by
     * NIP-46.
     * @returns A shared pointer to the signed wrapper event.
     */
    std::shared_ptr<nostr::data::Event> _wrapSignerMessage(nlohmann::json jrpc);

    /**
     * @brief Unwraps the JRPC-like payload from a signer message, typically one received from the
     * remote signer in response to a request.
     * @param event An event containing a NIP-46 message payload.
     * @returns The unwrapped payload.  The returned object will be empty if no valid payload could
     * be extracted from the given event.
     */
    std::string _unwrapSignerMessage(std::shared_ptr<nostr::data::Event> event);

    /**
     * @brief Pings the remote signer to confirm that it is online and available.
     * @returns A promise that will be set to `true` if the signer is available, `false` otherwise.
     */
    std::promise<bool> _pingSigner();

    #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
     * encrypted.
     */
    std::string _encryptNip04(const std::string input);

    /**
     * @brief Decrypts a NIP-04 encrypted string.
     * @param input The string to be decrypted.
     * @return The decrypted string, or an empty string if the input could not be decrypted.
     */
    std::string _decryptNip04(const std::string input);

    /**
     * @brief Encrypts a string according to the standard specified in NIP-44.
     * @param input The string to be encrypted.
     * @return The resulting encrypted string, or an empty string if the input could not be
     * encrypted.
     */
    std::string _encryptNip44(const std::string input); // TODO: Return or set HMAC?

    /**
     * @brief Decrypts a NIP-44 encrypted string.
     * @param input The string to be decrypted.
     * @return The decrypted string, or an empty string if the input could not be decrypted.
     */
    std::string _decryptNip44(const std::string input);

    #pragma endregion

    #pragma region Logging

    void _logNoscryptInitResult(NCResult initResult);

    void _logNoscryptSecretValidationResult(NCResult secretValidationResult);

    void _logNoscryptPubkeyGenerationResult(NCResult pubkeyGenerationResult);

    #pragma endregion
};
} // namespace signer
} // namespace nostr