UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
scalar.hpp
Go to the documentation of this file.
1#ifndef B4F0584E_3733_4C2F_BB01_D4BDC40E1760
2#define B4F0584E_3733_4C2F_BB01_D4BDC40E1760
3#pragma once
4
5#include <array>
6#include <cstdint>
7#include <cstring>
8#include <string>
9#include <vector>
10#include "secp256k1/types.hpp"
11
12namespace secp256k1::fast {
13
14class Scalar {
15public:
16 using limbs_type = std::array<std::uint64_t, 4>;
17
19 static Scalar zero();
20 static Scalar one();
21 static Scalar from_uint64(std::uint64_t value);
23 static Scalar from_bytes(const std::array<std::uint8_t, 32>& bytes);
24 static Scalar from_bytes(const std::uint8_t* bytes32);
25
26 // BIP-340 strict parsing: rejects values >= curve order n (no reduction).
27 // Returns false if bytes represent a value >= n.
28 // Use for signature/key parsing where canonical encoding is required.
29 static bool parse_bytes_strict(const std::uint8_t* bytes32, Scalar& out) noexcept;
30 static bool parse_bytes_strict(const std::array<std::uint8_t, 32>& bytes, Scalar& out) noexcept;
31
32 // BIP-340 strict parsing + nonzero: rejects values >= n OR == 0.
33 // Use for secret key validation (BIP-340: 0 < d' < n).
34 static bool parse_bytes_strict_nonzero(const std::uint8_t* bytes32, Scalar& out) noexcept;
35 static bool parse_bytes_strict_nonzero(const std::array<std::uint8_t, 32>& bytes, Scalar& out) noexcept;
36
37 // Developer-friendly: Create from hex string (64 hex chars)
38 // Example: Scalar::from_hex("fffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140")
39 static Scalar from_hex(const std::string& hex);
40
41 std::array<std::uint8_t, 32> to_bytes() const;
42 void write_bytes(std::uint8_t* out32) const noexcept;
43 std::string to_hex() const;
44 const limbs_type& limbs() const noexcept { return limbs_; }
45
46 Scalar operator+(const Scalar& rhs) const;
47 Scalar operator-(const Scalar& rhs) const;
48 Scalar operator*(const Scalar& rhs) const;
49
50 Scalar& operator+=(const Scalar& rhs);
51 Scalar& operator-=(const Scalar& rhs);
52 Scalar& operator*=(const Scalar& rhs);
53
54 bool is_zero() const noexcept;
55 bool operator==(const Scalar& rhs) const noexcept;
56
57 // Modular inverse: a^{-1} mod n (Fermat's little theorem: a^{n-2} mod n)
58 // Returns zero if this is zero.
59 Scalar inverse() const;
60
61 // Modular negation: -a mod n (= n - a, or 0 if a == 0)
62 Scalar negate() const;
63
64 // Parity check: returns true if lowest bit is 0
65 bool is_even() const noexcept;
66
67 // Safe conversion to shared data type (memcpy, compiler-optimized to noop).
68 // Returns by value -- no strict-aliasing UB.
69 ::secp256k1::ScalarData data() const noexcept {
71 std::memcpy(&d, &limbs_, sizeof(d));
72 return d;
73 }
74 static Scalar from_data(const ::secp256k1::ScalarData& d) {
75 return from_limbs({d.limbs[0], d.limbs[1], d.limbs[2], d.limbs[3]});
76 }
77
78 std::uint8_t bit(std::size_t index) const;
79
80 // Phase 5.6: NAF (Non-Adjacent Form) encoding
81 // Converts scalar to signed digit representation {-1, 0, 1}
82 // Returns vector where naf[i] represents digit at bit position i
83 // NAF has ~33% fewer non-zero digits than binary
84 std::vector<int8_t> to_naf() const;
85
86 // Phase 5.7: wNAF (width-w Non-Adjacent Form) encoding
87 // Converts scalar to signed odd-digit representation {+/-1, +/-3, +/-5, ..., +/-(2^w-1)}
88 // width: window width (typically 4-6 bits)
89 // Returns vector where wnaf[i] represents digit at position i
90 // Only odd values are used, reducing precompute table size by 50%
91 std::vector<int8_t> to_wnaf(unsigned width) const;
92
93private:
94 explicit Scalar(const limbs_type& limbs, bool normalized);
95
96 limbs_type limbs_{};
97};
98
99// Cross-backend layout compatibility (shared types contract)
100static_assert(sizeof(Scalar) == sizeof(::secp256k1::ScalarData),
101 "CPU Scalar must match shared data layout size");
102static_assert(sizeof(Scalar) == 32, "Scalar must be 256 bits");
103
104} // namespace secp256k1::fast
105
106
107#endif /* B4F0584E_3733_4C2F_BB01_D4BDC40E1760 */
Scalar & operator-=(const Scalar &rhs)
static bool parse_bytes_strict_nonzero(const std::uint8_t *bytes32, Scalar &out) noexcept
Scalar & operator+=(const Scalar &rhs)
std::vector< int8_t > to_naf() const
static Scalar from_data(const ::secp256k1::ScalarData &d)
Definition scalar.hpp:74
std::array< std::uint8_t, 32 > to_bytes() const
std::uint8_t bit(std::size_t index) const
bool is_even() const noexcept
bool is_zero() const noexcept
std::vector< int8_t > to_wnaf(unsigned width) const
Scalar operator-(const Scalar &rhs) const
static Scalar from_hex(const std::string &hex)
static Scalar zero()
static Scalar one()
const limbs_type & limbs() const noexcept
Definition scalar.hpp:44
static Scalar from_uint64(std::uint64_t value)
std::array< std::uint64_t, 4 > limbs_type
Definition scalar.hpp:16
static bool parse_bytes_strict(const std::uint8_t *bytes32, Scalar &out) noexcept
std::string to_hex() const
Scalar operator+(const Scalar &rhs) const
static Scalar from_limbs(const limbs_type &limbs)
Scalar inverse() const
Scalar & operator*=(const Scalar &rhs)
static bool parse_bytes_strict(const std::array< std::uint8_t, 32 > &bytes, Scalar &out) noexcept
static Scalar from_bytes(const std::array< std::uint8_t, 32 > &bytes)
Scalar negate() const
Scalar operator*(const Scalar &rhs) const
static Scalar from_bytes(const std::uint8_t *bytes32)
::secp256k1::ScalarData data() const noexcept
Definition scalar.hpp:69
static bool parse_bytes_strict_nonzero(const std::array< std::uint8_t, 32 > &bytes, Scalar &out) noexcept
void write_bytes(std::uint8_t *out32) const noexcept