UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
sign.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_CT_SIGN_HPP
2#define SECP256K1_CT_SIGN_HPP
3
4// ============================================================================
5// Constant-Time Signing & Key Generation
6// ============================================================================
7// Drop-in CT replacements for secp256k1::ecdsa_sign() and schnorr_sign().
8// These use ct::generator_mul() (data-independent execution trace) instead of
9// the fast variable-time scalar_mul on the generator.
10//
11// For production signing where the private key/nonce must remain secret,
12// ALWAYS use these functions instead of the fast:: variants.
13//
14// Usage:
15// #include <secp256k1/ct/sign.hpp>
16// auto sig = secp256k1::ct::ecdsa_sign(msg_hash, privkey);
17// auto schnorr_sig = secp256k1::ct::schnorr_sign(keypair, msg, aux);
18//
19// Compile with -DSECP256K1_REQUIRE_CT=1 to deprecate non-CT sign functions.
20// ============================================================================
21
22#include <array>
23#include <cstdint>
24#include "secp256k1/ecdsa.hpp"
26#include "secp256k1/schnorr.hpp"
29
30namespace secp256k1::ct {
31
32// -- CT ECDSA Sign ------------------------------------------------------------
33// Equivalent to secp256k1::ecdsa_sign() but uses ct::generator_mul() for R=k*G.
34// RFC 6979 deterministic nonce. Returns normalized (low-S) signature.
35ECDSASignature ecdsa_sign(const std::array<std::uint8_t, 32>& msg_hash,
36 const fast::Scalar& private_key);
37
38// -- CT ECDSA Sign + Verify (fault attack countermeasure) ---------------------
39// Signs and then verifies (FIPS 186-4 fault countermeasure).
40ECDSASignature ecdsa_sign_verified(const std::array<std::uint8_t, 32>& msg_hash,
41 const fast::Scalar& private_key);
42
43// -- CT ECDSA Sign (hedged, with extra entropy) --------------------------------
44// RFC 6979 Section 3.6: aux_rand mixed into HMAC-DRBG. CT generator_mul for R.
45ECDSASignature ecdsa_sign_hedged(const std::array<std::uint8_t, 32>& msg_hash,
46 const fast::Scalar& private_key,
47 const std::array<std::uint8_t, 32>& aux_rand);
48
49// -- CT ECDSA Sign Hedged + Verify (fault attack countermeasure) ---------------
50ECDSASignature ecdsa_sign_hedged_verified(const std::array<std::uint8_t, 32>& msg_hash,
51 const fast::Scalar& private_key,
52 const std::array<std::uint8_t, 32>& aux_rand);
53
54// -- CT ECDSA Sign with Recovery ID -------------------------------------------
55// Like ecdsa_sign() but also returns the recovery ID (0-3) needed for public key
56// recovery. Uses ct::generator_mul() for R=k*G and ct::scalar_inverse() for
57// k^{-1}: the private key and nonce remain constant-time throughout.
58//
59// Replaces the variable-time ::ecdsa_sign_recoverable() in all signing contexts
60// where a private key is involved (bitcoin_sign_message, Ethereum personal_sign,
61// and any Sparrow Wallet / ECIES integration using this library).
62//
63// Recovery ID extraction reads R.y parity from FieldElement::limbs()[0]&1 and
64// checks R.x overflow with a byte comparison -- neither branches on secret data.
66 const std::array<std::uint8_t, 32>& msg_hash,
67 const fast::Scalar& private_key);
68
69// PrivateKey overload.
71 const std::array<std::uint8_t, 32>& msg_hash,
72 const PrivateKey& private_key) {
73 return ecdsa_sign_recoverable(msg_hash, private_key.scalar());
74}
75
76// -- CT ECDSA Sign (PrivateKey overload) --------------------------------------
77// Preferred overload: accepts strong-typed PrivateKey for compile-time safety.
78inline ECDSASignature ecdsa_sign(const std::array<std::uint8_t, 32>& msg_hash,
79 const PrivateKey& private_key) {
80 return ecdsa_sign(msg_hash, private_key.scalar());
81}
82
83inline ECDSASignature ecdsa_sign_verified(const std::array<std::uint8_t, 32>& msg_hash,
84 const PrivateKey& private_key) {
85 return ecdsa_sign_verified(msg_hash, private_key.scalar());
86}
87
88// -- CT ECDSA Sign Hedged (PrivateKey overload) --------------------------------
89inline ECDSASignature ecdsa_sign_hedged(const std::array<std::uint8_t, 32>& msg_hash,
90 const PrivateKey& private_key,
91 const std::array<std::uint8_t, 32>& aux_rand) {
92 return ecdsa_sign_hedged(msg_hash, private_key.scalar(), aux_rand);
93}
94
95inline ECDSASignature ecdsa_sign_hedged_verified(const std::array<std::uint8_t, 32>& msg_hash,
96 const PrivateKey& private_key,
97 const std::array<std::uint8_t, 32>& aux_rand) {
98 return ecdsa_sign_hedged_verified(msg_hash, private_key.scalar(), aux_rand);
99}
100
101// -- CT Schnorr Pubkey --------------------------------------------------------
102// X-only public key derivation using ct::generator_mul().
103std::array<std::uint8_t, 32> schnorr_pubkey(const fast::Scalar& private_key);
104
105// PrivateKey overload.
106inline std::array<std::uint8_t, 32> schnorr_pubkey(const PrivateKey& pk) {
107 return schnorr_pubkey(pk.scalar());
108}
109
110// -- CT Schnorr Keypair Create ------------------------------------------------
111// Creates a BIP-340 keypair using ct::generator_mul().
113
114// PrivateKey overload.
118
119// -- CT Schnorr Sign (keypair variant) ----------------------------------------
120// BIP-340 signing using ct::generator_mul() for the nonce point R = k'*G.
121//
122// aux_rand: MUST be 32 bytes of fresh cryptographic randomness (e.g. from
123// OS CSPRNG). Provides synthetic nonce hedging per BIP-340. All-zeros is
124// safe against nonce reuse but not against fault injection.
125// See secp256k1/schnorr.hpp for full entropy contract.
127 const std::array<std::uint8_t, 32>& msg,
128 const std::array<std::uint8_t, 32>& aux_rand);
129
130// -- CT Schnorr Sign + Verify (fault attack countermeasure) --------------------
131// Signs and then verifies (FIPS 186-4 fault countermeasure).
133 const std::array<std::uint8_t, 32>& msg,
134 const std::array<std::uint8_t, 32>& aux_rand);
135
136} // namespace secp256k1::ct
137
138// ============================================================================
139// FAST guardrail: when SECP256K1_REQUIRE_CT is defined, mark the non-CT
140// sign functions as deprecated so callers get a compile-time warning.
141// ============================================================================
142#if defined(SECP256K1_REQUIRE_CT) && SECP256K1_REQUIRE_CT
143
144// GCC/Clang [[deprecated]] on existing declarations (re-declaration is valid)
145namespace secp256k1 {
146
147[[deprecated("Non-CT signing: use secp256k1::ct::ecdsa_sign() for production. "
148 "Define SECP256K1_ALLOW_FAST_SIGN to suppress.")]]
149ECDSASignature ecdsa_sign(const std::array<std::uint8_t, 32>& msg_hash,
150 const fast::Scalar& private_key);
151
152[[deprecated("Non-CT signing: use secp256k1::ct::schnorr_sign() for production. "
153 "Define SECP256K1_ALLOW_FAST_SIGN to suppress.")]]
155 const std::array<std::uint8_t, 32>& msg,
156 const std::array<std::uint8_t, 32>& aux_rand);
157
158[[deprecated("Non-CT key gen: use secp256k1::ct::schnorr_keypair_create().")]]
160
161[[deprecated("Non-CT key gen: use secp256k1::ct::schnorr_pubkey().")]]
162std::array<std::uint8_t, 32> schnorr_pubkey(const fast::Scalar& private_key);
163
164} // namespace secp256k1
165
166#endif // SECP256K1_REQUIRE_CT
167
168#endif // SECP256K1_CT_SIGN_HPP
const fast::Scalar & scalar() const noexcept
ECDSASignature ecdsa_sign_hedged_verified(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key, const std::array< std::uint8_t, 32 > &aux_rand)
ECDSASignature ecdsa_sign_verified(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
ECDSASignature ecdsa_sign_hedged(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key, const std::array< std::uint8_t, 32 > &aux_rand)
RecoverableSignature ecdsa_sign_recoverable(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
std::array< std::uint8_t, 32 > schnorr_pubkey(const fast::Scalar &private_key)
ECDSASignature ecdsa_sign(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
SchnorrSignature schnorr_sign(const SchnorrKeypair &kp, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
SchnorrSignature schnorr_sign_verified(const SchnorrKeypair &kp, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
SchnorrKeypair schnorr_keypair_create(const fast::Scalar &private_key)
SchnorrSignature schnorr_sign(const SchnorrKeypair &kp, const std::array< std::uint8_t, 32 > &msg, const std::array< std::uint8_t, 32 > &aux_rand)
SchnorrKeypair schnorr_keypair_create(const fast::Scalar &private_key)
std::array< std::uint8_t, 32 > schnorr_pubkey(const fast::Scalar &private_key)
ECDSASignature ecdsa_sign(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)