UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
ecdsa.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_ECDSA_HPP
2#define SECP256K1_ECDSA_HPP
3#pragma once
4
5// ============================================================================
6// ECDSA Sign / Verify for secp256k1
7// ============================================================================
8// Standard ECDSA (RFC 6979 deterministic nonce recommended for production).
9// This implementation provides:
10// - sign(message_hash, private_key) -> (r, s)
11// - verify(message_hash, public_key, r, s) -> bool
12// - Signature normalization (low-S, BIP-62)
13//
14// WARNING: The nonce k MUST be cryptographically random or deterministic
15// (RFC 6979). Reusing k leaks the private key. This library provides a
16// deterministic nonce function (RFC 6979) for safety.
17// ============================================================================
18
19#include <array>
20#include <cstdint>
21#include "secp256k1/scalar.hpp"
22#include "secp256k1/point.hpp"
23
24namespace secp256k1 {
25
26// -- Signature ----------------------------------------------------------------
27
31
32 // DER encoding (variable length, max 72 bytes)
33 // Returns {encoded_bytes, length}
34 std::pair<std::array<std::uint8_t, 72>, std::size_t> to_der() const;
35
36 // Compact 64-byte encoding: r (32 bytes) || s (32 bytes)
37 std::array<std::uint8_t, 64> to_compact() const;
38
39 // Decode from compact 64-byte encoding
40 static ECDSASignature from_compact(const std::uint8_t* data64);
41 static ECDSASignature from_compact(const std::array<std::uint8_t, 64>& data);
42
43 // Strict compact parse: rejects r >= n, s >= n, r == 0, s == 0 (no reduce)
44 static bool parse_compact_strict(const std::uint8_t* data64, ECDSASignature& out) noexcept;
45 static bool parse_compact_strict(const std::array<std::uint8_t, 64>& data, ECDSASignature& out) noexcept;
46
47 // Normalize to low-S form (BIP-62): if s > n/2, replace with n - s
49
50 // Check if signature has low-S
51 bool is_low_s() const;
52};
53
54// -- ECDSA Operations ---------------------------------------------------------
55
56// Sign a 32-byte message hash with a private key.
57// Uses RFC 6979 deterministic nonce generation.
58// Returns normalized (low-S) signature.
59// Returns {zero, zero} signature on failure (zero key, etc.)
60ECDSASignature ecdsa_sign(const std::array<std::uint8_t, 32>& msg_hash,
61 const fast::Scalar& private_key);
62
63// Sign + verify (FIPS 186-4 fault attack countermeasure).
64// Verifies the produced signature before returning it.
65// Use this when fault injection resistance is required.
66ECDSASignature ecdsa_sign_verified(const std::array<std::uint8_t, 32>& msg_hash,
67 const fast::Scalar& private_key);
68
69// Sign with hedged nonce: RFC 6979 + extra entropy (RFC 6979 Section 3.6).
70// aux_rand: 32 bytes of fresh CSPRNG randomness mixed into the HMAC-DRBG.
71// This provides defense-in-depth against HMAC-SHA256 weakness or fault
72// injection while maintaining deterministic fallback behavior.
73// The nonce is deterministic for a given (key, msg, aux_rand) triple.
74// Equivalent to libsecp256k1's secp256k1_ecdsa_sign() with ndata parameter.
75ECDSASignature ecdsa_sign_hedged(const std::array<std::uint8_t, 32>& msg_hash,
76 const fast::Scalar& private_key,
77 const std::array<std::uint8_t, 32>& aux_rand);
78
79// Hedged sign + verify (FIPS 186-4 fault attack countermeasure).
80ECDSASignature ecdsa_sign_hedged_verified(const std::array<std::uint8_t, 32>& msg_hash,
81 const fast::Scalar& private_key,
82 const std::array<std::uint8_t, 32>& aux_rand);
83
84// Verify an ECDSA signature against a public key and message hash.
85// Accepts both low-S and high-S signatures.
86// Raw-pointer overload: avoids 32B array copy when caller has a raw pointer.
87bool ecdsa_verify(const std::uint8_t* msg_hash32,
88 const fast::Point& public_key,
89 const ECDSASignature& sig);
90
91// Array overload: thin wrapper.
92bool ecdsa_verify(const std::array<std::uint8_t, 32>& msg_hash,
93 const fast::Point& public_key,
94 const ECDSASignature& sig);
95
96// -- RFC 6979 Deterministic Nonce ---------------------------------------------
97
98// Generate deterministic nonce k per RFC 6979.
99// Inputs: private key (32 bytes), message hash (32 bytes).
100// Output: scalar k suitable for ECDSA signing.
102 const std::array<std::uint8_t, 32>& msg_hash);
103
104// Hedged variant: RFC 6979 Section 3.6 with extra entropy.
105// aux_rand (32 bytes of CSPRNG randomness) is mixed into the HMAC-DRBG.
107 const std::array<std::uint8_t, 32>& msg_hash,
108 const std::array<std::uint8_t, 32>& aux_rand);
109
110} // namespace secp256k1
111
112#endif // SECP256K1_ECDSA_HPP
ECDSASignature ecdsa_sign_verified(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
fast::Scalar rfc6979_nonce(const fast::Scalar &private_key, const std::array< std::uint8_t, 32 > &msg_hash)
fast::Scalar rfc6979_nonce_hedged(const fast::Scalar &private_key, const std::array< std::uint8_t, 32 > &msg_hash, const std::array< std::uint8_t, 32 > &aux_rand)
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)
ECDSASignature ecdsa_sign(const std::array< std::uint8_t, 32 > &msg_hash, const fast::Scalar &private_key)
bool ecdsa_verify(const std::uint8_t *msg_hash32, const fast::Point &public_key, const ECDSASignature &sig)
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)
static ECDSASignature from_compact(const std::array< std::uint8_t, 64 > &data)
std::pair< std::array< std::uint8_t, 72 >, std::size_t > to_der() const
ECDSASignature normalize() const
static bool parse_compact_strict(const std::uint8_t *data64, ECDSASignature &out) noexcept
static bool parse_compact_strict(const std::array< std::uint8_t, 64 > &data, ECDSASignature &out) noexcept
std::array< std::uint8_t, 64 > to_compact() const
static ECDSASignature from_compact(const std::uint8_t *data64)