MCPcopy Create free account
hub / github.com/QuipNetwork/cpp-sdk / QuipSigner

Class QuipSigner

src/cli.cpp:120–174  ·  view source on GitHub ↗

QuipSigner: Deterministic Winternitz keypair generator using quantum secret and vaultId

Source from the content-addressed store, hash-verified

118// QuipSigner: Deterministic Winternitz keypair generator using quantum secret
119// and vaultId
120class QuipSigner {
121public:
122 QuipSigner(const std::array<uint8_t, 32> &quantum_secret_raw)
123 : wots_(keccak256) {
124 // Store the raw quantum secret, hashing happens in recoverKeyPair
125 quantum_secret_ = quantum_secret_raw;
126 }
127
128 // Generate a NEW keypair for a given vaultId using a random public seed
129 // This is used for creating the NEXT keypair during transfers
130 std::pair<WinternitzAddress, std::vector<std::array<uint8_t, 32>>>
131 generateKeyPair(const std::array<uint8_t, 32> &vaultId) {
132 // Use a cryptographically secure random 32-byte public seed for the next PQ owner
133 std::array<uint8_t, 32> public_seed = randomSeed32();
134 return recoverKeyPair(vaultId, public_seed);
135 }
136
137 // Deterministically recover keypair for a given vaultId and publicSeed
138 std::pair<WinternitzAddress, std::vector<std::array<uint8_t, 32>>>
139 recoverKeyPair(const std::array<uint8_t, 32> &vaultId,
140 const std::array<uint8_t, 32> &publicSeed) {
141 // Create the private seed by concatenating the quantum secret and
142 // the vaultId, then hash it (matching TypeScript implementation)
143 std::vector<uint8_t> concat(quantum_secret_.begin(),
144 quantum_secret_.end());
145 concat.insert(concat.end(), vaultId.begin(), vaultId.end());
146 std::array<uint8_t, 32> private_seed_array = keccak256(concat);
147 std::vector<uint8_t> private_seed(private_seed_array.begin(), private_seed_array.end());
148
149
150 // Generate keypair using the two-parameter interface (protocol-compatible)
151 auto [public_key, private_key] =
152 wots_.generate_key_pair(private_seed, publicSeed);
153
154 // Create WinternitzAddress from the generated public key
155 WinternitzAddress pqAddress;
156 std::copy(public_key.begin(), public_key.begin() + 32,
157 pqAddress.publicSeed.begin());
158 std::copy(public_key.begin() + 32, public_key.end(),
159 pqAddress.publicKeyHash.begin());
160 return {pqAddress, private_key};
161 }
162
163 // Sign a message using a recovered keypair
164 Signature sign(const std::array<uint8_t, 32> &message,
165 const std::vector<std::array<uint8_t, 32>> &private_key,
166 const std::array<uint8_t, 32> &publicSeed) {
167 // Sign the message with the provided private key and public seed
168 return wots_.sign(private_key, publicSeed, message);
169 }
170
171private:
172 std::array<uint8_t, 32> quantum_secret_;
173 hashsigs::WOTSPlus wots_;
174};
175
176CLI::CLI(const std::string &rpc_url, const std::string &contract_address)
177 : rpc_url_(rpc_url), contract_address_(contract_address) {

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected