Botan 3.5.0
Crypto and TLS for C&
ed25519_key.cpp
Go to the documentation of this file.
1/*
2* Ed25519
3* (C) 2017 Ribose Inc
4*
5* Based on the public domain code from SUPERCOP ref10 by
6* Peter Schwabe, Daniel J. Bernstein, Niels Duif, Tanja Lange, Bo-Yin Yang
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#include <botan/ed25519.h>
12
13#include <botan/ber_dec.h>
14#include <botan/der_enc.h>
15#include <botan/hash.h>
16#include <botan/rng.h>
17#include <botan/internal/ct_utils.h>
18#include <botan/internal/ed25519_internal.h>
19#include <botan/internal/pk_ops_impl.h>
20
21namespace Botan {
22
26
27bool Ed25519_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
28 if(m_public.size() != 32) {
29 return false;
30 }
31
32 /*
33 This function was derived from public domain code in Tor's blinding.c
34 */
35
36 const uint8_t identity_element[32] = {1};
37 if(CT::is_equal(m_public.data(), identity_element, 32).as_bool()) {
38 return false;
39 }
40
41 // The order of the Ed25519 group encoded
42 const uint8_t modm_m[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
43 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
45
46 const unsigned char zero[32] = {0};
47
48 unsigned char pkcopy[32];
49
50 copy_mem(pkcopy, m_public.data(), 32);
51 pkcopy[31] ^= (1 << 7); // flip sign
52 ge_p3 point;
53 if(ge_frombytes_negate_vartime(&point, pkcopy) != 0) {
54 return false;
55 }
56
57 uint8_t result[32];
58 ge_double_scalarmult_vartime(result, modm_m, &point, zero);
59
60 if(!CT::is_equal(result, identity_element, 32).as_bool()) {
61 return false;
62 }
63
64 return true;
65}
66
67Ed25519_PublicKey::Ed25519_PublicKey(const uint8_t pub_key[], size_t pub_len) {
68 if(pub_len != 32) {
69 throw Decoding_Error("Invalid length for Ed25519 key");
70 }
71 m_public.assign(pub_key, pub_key + pub_len);
72}
73
74Ed25519_PublicKey::Ed25519_PublicKey(const AlgorithmIdentifier& /*unused*/, std::span<const uint8_t> key_bits) {
75 m_public.assign(key_bits.begin(), key_bits.end());
76
77 if(m_public.size() != 32) {
78 throw Decoding_Error("Invalid size for Ed25519 public key");
79 }
80}
81
82std::vector<uint8_t> Ed25519_PublicKey::raw_public_key_bits() const {
83 return m_public;
84}
85
86std::vector<uint8_t> Ed25519_PublicKey::public_key_bits() const {
87 return raw_public_key_bits();
88}
89
90std::unique_ptr<Private_Key> Ed25519_PublicKey::generate_another(RandomNumberGenerator& rng) const {
91 return std::make_unique<Ed25519_PrivateKey>(rng);
92}
93
95 if(secret_key.size() == 64) {
96 m_private = secret_key;
97 m_public.assign(m_private.begin() + 32, m_private.end());
98 } else if(secret_key.size() == 32) {
99 m_public.resize(32);
100 m_private.resize(64);
101 ed25519_gen_keypair(m_public.data(), m_private.data(), secret_key.data());
102 } else {
103 throw Decoding_Error("Invalid size for Ed25519 private key");
104 }
105}
106
108 const secure_vector<uint8_t> seed = rng.random_vec(32);
109 m_public.resize(32);
110 m_private.resize(64);
111 ed25519_gen_keypair(m_public.data(), m_private.data(), seed.data());
112}
113
114Ed25519_PrivateKey::Ed25519_PrivateKey(const AlgorithmIdentifier& /*unused*/, std::span<const uint8_t> key_bits) {
117
118 if(bits.size() != 32) {
119 throw Decoding_Error("Invalid size for Ed25519 private key");
120 }
121 m_public.resize(32);
122 m_private.resize(64);
123 ed25519_gen_keypair(m_public.data(), m_private.data(), bits.data());
124}
125
126std::unique_ptr<Public_Key> Ed25519_PrivateKey::public_key() const {
127 return std::make_unique<Ed25519_PublicKey>(get_public_key());
128}
129
134
135bool Ed25519_PrivateKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
136 return true; // ???
137}
138
139namespace {
140
141/**
142* Ed25519 verifying operation
143*/
144class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification {
145 public:
146 explicit Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey& key) : m_key(key.get_public_key()) {}
147
148 void update(const uint8_t msg[], size_t msg_len) override { m_msg.insert(m_msg.end(), msg, msg + msg_len); }
149
150 bool is_valid_signature(const uint8_t sig[], size_t sig_len) override {
151 if(sig_len != 64) {
152 return false;
153 }
154
155 BOTAN_ASSERT_EQUAL(m_key.size(), 32, "Expected size");
156 const bool ok = ed25519_verify(m_msg.data(), m_msg.size(), sig, m_key.data(), nullptr, 0);
157 m_msg.clear();
158 return ok;
159 }
160
161 std::string hash_function() const override { return "SHA-512"; }
162
163 private:
164 std::vector<uint8_t> m_msg;
165 std::vector<uint8_t> m_key;
166};
167
168/**
169* Ed25519 verifying operation with pre-hash
170*/
171class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification {
172 public:
173 Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, std::string_view hash, bool rfc8032) :
174 m_key(key.get_public_key()) {
175 m_hash = HashFunction::create_or_throw(hash);
176
177 if(rfc8032) {
178 m_domain_sep = {0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
179 0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
180 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
181 }
182 }
183
184 void update(const uint8_t msg[], size_t msg_len) override { m_hash->update(msg, msg_len); }
185
186 bool is_valid_signature(const uint8_t sig[], size_t sig_len) override {
187 if(sig_len != 64) {
188 return false;
189 }
190 std::vector<uint8_t> msg_hash(m_hash->output_length());
191 m_hash->final(msg_hash.data());
192
193 BOTAN_ASSERT_EQUAL(m_key.size(), 32, "Expected size");
194 return ed25519_verify(
195 msg_hash.data(), msg_hash.size(), sig, m_key.data(), m_domain_sep.data(), m_domain_sep.size());
196 }
197
198 std::string hash_function() const override { return m_hash->name(); }
199
200 private:
201 std::unique_ptr<HashFunction> m_hash;
202 std::vector<uint8_t> m_key;
203 std::vector<uint8_t> m_domain_sep;
204};
205
206/**
207* Ed25519 signing operation ('pure' - signs message directly)
208*/
209class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature {
210 public:
211 explicit Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey& key) : m_key(key.raw_private_key_bits()) {}
212
213 void update(const uint8_t msg[], size_t msg_len) override { m_msg.insert(m_msg.end(), msg, msg + msg_len); }
214
215 secure_vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
217 ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.data(), nullptr, 0);
218 m_msg.clear();
219 return sig;
220 }
221
222 size_t signature_length() const override { return 64; }
223
224 AlgorithmIdentifier algorithm_identifier() const override;
225
226 std::string hash_function() const override { return "SHA-512"; }
227
228 private:
229 std::vector<uint8_t> m_msg;
231};
232
233AlgorithmIdentifier Ed25519_Pure_Sign_Operation::algorithm_identifier() const {
234 return AlgorithmIdentifier(OID::from_string("Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
235}
236
237/**
238* Ed25519 signing operation with pre-hash
239*/
240class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature {
241 public:
242 Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, std::string_view hash, bool rfc8032) :
243 m_key(key.raw_private_key_bits()) {
244 m_hash = HashFunction::create_or_throw(hash);
245
246 if(rfc8032) {
247 m_domain_sep = std::vector<uint8_t>{0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
248 0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
249 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
250 }
251 }
252
253 size_t signature_length() const override { return 64; }
254
255 void update(const uint8_t msg[], size_t msg_len) override { m_hash->update(msg, msg_len); }
256
257 secure_vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
258 secure_vector<uint8_t> sig(64);
259 std::vector<uint8_t> msg_hash(m_hash->output_length());
260 m_hash->final(msg_hash.data());
262 sig.data(), msg_hash.data(), msg_hash.size(), m_key.data(), m_domain_sep.data(), m_domain_sep.size());
263 return sig;
264 }
265
266 std::string hash_function() const override { return m_hash->name(); }
267
268 private:
269 std::unique_ptr<HashFunction> m_hash;
270 secure_vector<uint8_t> m_key;
271 std::vector<uint8_t> m_domain_sep;
272};
273
274} // namespace
275
276std::unique_ptr<PK_Ops::Verification> Ed25519_PublicKey::create_verification_op(std::string_view params,
277 std::string_view provider) const {
278 if(provider == "base" || provider.empty()) {
279 if(params.empty() || params == "Identity" || params == "Pure") {
280 return std::make_unique<Ed25519_Pure_Verify_Operation>(*this);
281 } else if(params == "Ed25519ph") {
282 return std::make_unique<Ed25519_Hashed_Verify_Operation>(*this, "SHA-512", true);
283 } else {
284 return std::make_unique<Ed25519_Hashed_Verify_Operation>(*this, params, false);
285 }
286 }
287 throw Provider_Not_Found(algo_name(), provider);
288}
289
290std::unique_ptr<PK_Ops::Verification> Ed25519_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
291 std::string_view provider) const {
292 if(provider == "base" || provider.empty()) {
293 if(alg_id != this->algorithm_identifier()) {
294 throw Decoding_Error("Unexpected AlgorithmIdentifier for Ed25519 X509 signature");
295 }
296
297 return std::make_unique<Ed25519_Pure_Verify_Operation>(*this);
298 }
299 throw Provider_Not_Found(algo_name(), provider);
300}
301
302std::unique_ptr<PK_Ops::Signature> Ed25519_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
303 std::string_view params,
304 std::string_view provider) const {
305 if(provider == "base" || provider.empty()) {
306 if(params.empty() || params == "Identity" || params == "Pure") {
307 return std::make_unique<Ed25519_Pure_Sign_Operation>(*this);
308 } else if(params == "Ed25519ph") {
309 return std::make_unique<Ed25519_Hashed_Sign_Operation>(*this, "SHA-512", true);
310 } else {
311 return std::make_unique<Ed25519_Hashed_Sign_Operation>(*this, params, false);
312 }
313 }
314 throw Provider_Not_Found(algo_name(), provider);
315}
316
317} // namespace Botan
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition assert.h:68
virtual OID object_identifier() const
Definition pk_keys.cpp:22
BER_Decoder & decode(bool &out)
Definition ber_dec.h:186
BER_Decoder & discard_remaining()
Definition ber_dec.cpp:228
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:132
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
Ed25519_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
std::unique_ptr< Public_Key > public_key() const override
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
secure_vector< uint8_t > private_key_bits() const override
std::vector< uint8_t > m_public
Definition ed25519.h:59
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
const std::vector< uint8_t > & get_public_key() const
Definition ed25519.h:38
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
std::vector< uint8_t > public_key_bits() const override
AlgorithmIdentifier algorithm_identifier() const override
std::vector< uint8_t > raw_public_key_bits() const override
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
void random_vec(std::span< uint8_t > v)
Definition rng.h:179
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:486
int ge_frombytes_negate_vartime(ge_p3 *v, const uint8_t *)
Definition ge.cpp:425
void ed25519_sign(uint8_t sig[64], const uint8_t m[], size_t mlen, const uint8_t sk[64], const uint8_t domain_sep[], size_t domain_sep_len)
Definition ed25519.cpp:37
void ed25519_gen_keypair(uint8_t *pk, uint8_t *sk, const uint8_t seed[32])
Definition ed25519.cpp:20
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
bool ed25519_verify(const uint8_t *m, size_t mlen, const uint8_t sig[64], const uint8_t *pk, const uint8_t domain_sep[], size_t domain_sep_len)
Definition ed25519.cpp:73
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146
void ge_double_scalarmult_vartime(uint8_t out[32], const uint8_t a[], const ge_p3 *A, const uint8_t b[])