Botan 3.13.0
Crypto and TLS for C&
ec_scalar.h
Go to the documentation of this file.
1/*
2* (C) 2024 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_EC_SCALAR_H_
8#define BOTAN_EC_SCALAR_H_
9
10#include <botan/concepts.h>
11#include <botan/types.h>
12#include <memory>
13#include <optional>
14#include <span>
15#include <string_view>
16#include <vector>
17
18namespace Botan {
19
20class BigInt;
22class EC_Group;
23class EC_Scalar_Data;
24
25/**
26* Represents an integer modulo the prime group order of an elliptic curve
27*/
28class BOTAN_PUBLIC_API(3, 6) EC_Scalar final {
29 public:
30 /**
31 * Deserialize a scalar
32 *
33 * The span must be exactly bytes() long; this function does not accept
34 * either short inputs (eg [1] to encode the integer 1) or inputs with
35 * excess leading zero bytes.
36 *
37 * Returns nullopt if the length is incorrect or if the integer is not
38 * within the range [0,n) where n is the group order.
39 */
40 static std::optional<EC_Scalar> deserialize(const EC_Group& group, std::span<const uint8_t> bytes);
41
42 /**
43 * Convert a bytestring to an EC_Scalar
44 *
45 * This uses the truncation rules from ECDSA
46 */
47 static EC_Scalar from_bytes_with_trunc(const EC_Group& group, std::span<const uint8_t> bytes);
48
49 /**
50 * Convert a bytestring to an EC_Scalar
51 *
52 * This reduces the bytes modulo the group order. The input can be at most
53 * 2*bytes() long
54 */
55 static EC_Scalar from_bytes_mod_order(const EC_Group& group, std::span<const uint8_t> bytes);
56
57 /**
58 * Hash to scalar following RFC 9380
59 *
60 * This requires XMD. Unlike hash2curve, any group is supported
61 */
62 static EC_Scalar hash(const EC_Group& group,
63 std::string_view hash_fn,
64 std::span<const uint8_t> input,
65 std::span<const uint8_t> domain_sep);
66
67 /**
68 * Convert a bytestring to an EC_Scalar
69 *
70 * This is similar to deserialize but instead of returning nullopt if the input
71 * is invalid, it will throw an exception.
72 */
73 BOTAN_DEPRECATED("Use EC_Scalar::deserialize") EC_Scalar(const EC_Group& group, std::span<const uint8_t> bytes);
74
75 /**
76 * Deserialize a pair of scalars
77 *
78 * Returns nullopt if the length is not 2*bytes(), or if either scalar is
79 * out of range or zero
80 */
81 static std::optional<std::pair<EC_Scalar, EC_Scalar>> deserialize_pair(const EC_Group& group,
82 std::span<const uint8_t> bytes);
83
84 /**
85 * Return a new random scalar value
86 */
87 static EC_Scalar random(const EC_Group& group, RandomNumberGenerator& rng);
88
89 /**
90 * Return the scalar value 1
91 */
92 static EC_Scalar one(const EC_Group& group);
93
94 /**
95 * Convert from the argument BigInt to a EC_Scalar
96 *
97 * Throws an exception if the provided bn is negative or too large
98 */
99 static EC_Scalar from_bigint(const EC_Group& group, const BigInt& bn);
100
101 /**
102 * Compute the elliptic curve scalar multiplication (g*k) where g is the
103 * standard base point on the curve. Then extract the x coordinate of
104 * the resulting point, and reduce it modulo the group order.
105 */
106 static EC_Scalar gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng);
107
108 /**
109 * Compute the elliptic curve scalar multiplication (g*k) where g is the
110 * standard base point on the curve. Then extract the x coordinate of
111 * the resulting point, and reduce it modulo the group order.
112 *
113 * @param scalar the scalar k to multiply the base point by
114 * @param rng a random number generator, used for blinding
115 * @return the x coordinate of g*k reduced modulo the group order
116 */
117 BOTAN_DEPRECATED("Use version without workspace arg")
118 static EC_Scalar
119 gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& /*ws*/) {
120 return EC_Scalar::gk_x_mod_order(scalar, rng);
121 }
122
123 /**
124 * Return the byte size of this scalar
125 */
126 size_t bytes() const;
127
128 /**
129 * Write the fixed length serialization to bytes
130 *
131 * The provided span must be exactly bytes() long
132 */
133 void serialize_to(std::span<uint8_t> bytes) const;
134
135 /**
136 * Return the bytes of the encoded scalar in a container
137 */
138 template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
139 T serialize() const {
140 T s(this->bytes());
141 this->serialize_to(s);
142 return s;
143 }
144
145 /**
146 * Write the fixed length serialization to bytes
147 *
148 * The provided span must be exactly 2*bytes() long
149 */
150 static void serialize_pair_to(std::span<uint8_t> bytes, const EC_Scalar& r, const EC_Scalar& s);
151
152 /**
153 * Return the bytes of the encoded scalar in a container
154 */
155 template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
156 static T serialize_pair(const EC_Scalar& r, const EC_Scalar& s) {
157 T bytes(r.bytes() + s.bytes());
159 return bytes;
160 }
161
162 /**
163 * Return true if this EC_Scalar is zero
164 */
165 bool is_zero() const;
166
167 /**
168 * Return true if this EC_Scalar is not zero
169 */
170 bool is_nonzero() const { return !is_zero(); }
171
172 /**
173 * Constant time modular inversion
174 *
175 * Return the modular inverse of this EC_Scalar
176 *
177 * If *this is zero, then invert() returns zero
178 */
179 EC_Scalar invert() const;
180
181 /**
182 * Variable time modular inversion
183 *
184 * Return the modular inverse of this EC_Scalar
185 *
186 * If *this is zero, then invert_vartime() returns zero
187 */
188 EC_Scalar invert_vartime() const;
189
190 /**
191 * Return the additive inverse of *this
192 */
193 EC_Scalar negate() const;
194
195 /**
196 * Scalar addition (modulo group order)
197 */
198 EC_Scalar add(const EC_Scalar& x) const;
199
200 /**
201 * Scalar subtraction (modulo group order)
202 */
203 EC_Scalar sub(const EC_Scalar& x) const;
204
205 /**
206 * Scalar multiplication (modulo group order)
207 */
208 EC_Scalar mul(const EC_Scalar& x) const;
209
210 /**
211 * Assign a scalar
212 */
213 void assign(const EC_Scalar& x);
214
215 /**
216 * Equivalent to assigning a zero value, but also does so in a way that
217 * attempts to ensure the write always occurs even if a compiler can deduce
218 * the assignment is otherwise unnecessary.
219 */
220 void zeroize();
221
222 /**
223 * Set *this to its own square modulo the group order
224 */
225 void square_self();
226
227 /**
228 * Test for equality
229 */
230 bool is_eq(const EC_Scalar& x) const;
231
232 /**
233 * Convert *this to a BigInt
234 */
235 BigInt to_bigint() const;
236
237 friend EC_Scalar operator+(const EC_Scalar& x, const EC_Scalar& y) { return x.add(y); }
238
239 friend EC_Scalar operator-(const EC_Scalar& x, const EC_Scalar& y) { return x.sub(y); }
240
241 friend EC_Scalar operator*(const EC_Scalar& x, const EC_Scalar& y) { return x.mul(y); }
242
243 friend bool operator==(const EC_Scalar& x, const EC_Scalar& y) { return x.is_eq(y); }
244
245 /**
246 * Copy constructor
247 * @param other the scalar to copy
248 */
249 EC_Scalar(const EC_Scalar& other);
250
251 /**
252 * Move constructor
253 * @param other the scalar to move from
254 */
255 EC_Scalar(EC_Scalar&& other) noexcept;
256
257 /**
258 * Copy assignment
259 * @param other the scalar to copy
260 * @return reference to this
261 */
262 EC_Scalar& operator=(const EC_Scalar& other);
263
264 /**
265 * Move assignment
266 * @param other the scalar to move from
267 * @return reference to this
268 */
269 EC_Scalar& operator=(EC_Scalar&& other) noexcept;
270
272
273 /**
274 * For internal use only
275 * @return the inner representation of this scalar
276 */
277 const EC_Scalar_Data& _inner() const { return inner(); }
278
279 /**
280 * For internal use only
281 * @param inner the inner representation to wrap
282 * @return a scalar wrapping the provided inner representation
283 */
284 static EC_Scalar _from_inner(std::unique_ptr<EC_Scalar_Data> inner);
285
286 private:
287 friend class EC_AffinePoint;
288
289 explicit EC_Scalar(std::unique_ptr<EC_Scalar_Data> scalar);
290
291 const EC_Scalar_Data& inner() const { return *m_scalar; }
292
293 std::unique_ptr<EC_Scalar_Data> m_scalar;
294};
295
296} // namespace Botan
297
298#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_DEPRECATED(msg)
Definition api.h:73
static EC_Scalar one(const EC_Group &group)
Definition ec_scalar.cpp:68
const EC_Scalar_Data & _inner() const
Definition ec_scalar.h:277
static EC_Scalar hash(const EC_Group &group, std::string_view hash_fn, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep)
bool is_eq(const EC_Scalar &x) const
static std::optional< EC_Scalar > deserialize(const EC_Group &group, std::span< const uint8_t > bytes)
EC_Scalar mul(const EC_Scalar &x) const
EC_Scalar add(const EC_Scalar &x) const
friend EC_Scalar operator*(const EC_Scalar &x, const EC_Scalar &y)
Definition ec_scalar.h:241
static EC_Scalar gk_x_mod_order(const EC_Scalar &scalar, RandomNumberGenerator &rng)
Definition ec_scalar.cpp:87
static EC_Scalar gk_x_mod_order(const EC_Scalar &scalar, RandomNumberGenerator &rng, std::vector< BigInt > &)
Definition ec_scalar.h:119
void serialize_to(std::span< uint8_t > bytes) const
Definition ec_scalar.cpp:92
bool is_zero() const
size_t bytes() const
Definition ec_scalar.cpp:48
static EC_Scalar from_bigint(const EC_Group &group, const BigInt &bn)
Definition ec_scalar.cpp:72
static T serialize_pair(const EC_Scalar &r, const EC_Scalar &s)
Definition ec_scalar.h:156
T serialize() const
Definition ec_scalar.h:139
friend EC_Scalar operator+(const EC_Scalar &x, const EC_Scalar &y)
Definition ec_scalar.h:237
static void serialize_pair_to(std::span< uint8_t > bytes, const EC_Scalar &r, const EC_Scalar &s)
Definition ec_scalar.cpp:96
EC_Scalar(const EC_Group &group, std::span< const uint8_t > bytes)
friend bool operator==(const EC_Scalar &x, const EC_Scalar &y)
Definition ec_scalar.h:243
static EC_Scalar from_bytes_mod_order(const EC_Group &group, std::span< const uint8_t > bytes)
Definition ec_scalar.cpp:56
bool is_nonzero() const
Definition ec_scalar.h:170
static EC_Scalar random(const EC_Group &group, RandomNumberGenerator &rng)
Definition ec_scalar.cpp:64
EC_Scalar sub(const EC_Scalar &x) const
friend EC_Scalar operator-(const EC_Scalar &x, const EC_Scalar &y)
Definition ec_scalar.h:239
static std::optional< std::pair< EC_Scalar, EC_Scalar > > deserialize_pair(const EC_Group &group, std::span< const uint8_t > bytes)
friend class EC_AffinePoint
Definition ec_scalar.h:287
static EC_Scalar from_bytes_with_trunc(const EC_Group &group, std::span< const uint8_t > bytes)
Definition ec_scalar.cpp:52