Botan 3.0.0-alpha0
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#include <botan/internal/pk_ops_impl.h>
13#include <botan/internal/ed25519_internal.h>
14#include <botan/hash.h>
15#include <botan/ber_dec.h>
16#include <botan/der_enc.h>
17#include <botan/rng.h>
18
19namespace Botan {
20
22 {
24 }
25
26bool Ed25519_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const
27 {
28 if(m_public.size() != 32)
29 return false;
30
31 /*
32 This function was derived from public domain code in Tor's blinding.c
33 */
34
35 const uint8_t identity_element[32] = { 1 };
36 if(same_mem(m_public.data(), identity_element, 32))
37 return false;
38
39 // The order of the Ed25519 group encoded
40 const uint8_t modm_m[32] = {
41 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
42 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 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 uint8_t result[32];
57 ge_double_scalarmult_vartime(result, modm_m, &point, zero);
58
59 if(!same_mem(result, identity_element, 32))
60 return false;
61
62 return true;
63 }
64
65Ed25519_PublicKey::Ed25519_PublicKey(const uint8_t pub_key[], size_t pub_len)
66 {
67 if(pub_len != 32)
68 throw Decoding_Error("Invalid length for Ed25519 key");
69 m_public.assign(pub_key, pub_key + pub_len);
70 }
71
73 const std::vector<uint8_t>& key_bits)
74 {
75 m_public = key_bits;
76
77 if(m_public.size() != 32)
78 throw Decoding_Error("Invalid size for Ed25519 public key");
79 }
80
81std::vector<uint8_t> Ed25519_PublicKey::public_key_bits() const
82 {
83 return m_public;
84 }
85
87 {
88 if(secret_key.size() == 64)
89 {
90 m_private = secret_key;
91 m_public.assign(m_private.begin() + 32, m_private.end());
92 }
93 else if(secret_key.size() == 32)
94 {
95 m_public.resize(32);
96 m_private.resize(64);
97 ed25519_gen_keypair(m_public.data(), m_private.data(), secret_key.data());
98 }
99 else
100 throw Decoding_Error("Invalid size for Ed25519 private key");
101 }
102
104 {
105 const secure_vector<uint8_t> seed = rng.random_vec(32);
106 m_public.resize(32);
107 m_private.resize(64);
108 ed25519_gen_keypair(m_public.data(), m_private.data(), seed.data());
109 }
110
112 const secure_vector<uint8_t>& key_bits)
113 {
116
117 if(bits.size() != 32)
118 throw Decoding_Error("Invalid size for Ed25519 private key");
119 m_public.resize(32);
120 m_private.resize(64);
121 ed25519_gen_keypair(m_public.data(), m_private.data(), bits.data());
122 }
123
124std::unique_ptr<Public_Key> Ed25519_PrivateKey::public_key() const
125 {
126 return std::make_unique<Ed25519_PublicKey>(get_public_key());
127 }
128
130 {
131 secure_vector<uint8_t> bits(&m_private[0], &m_private[32]);
133 }
134
135bool Ed25519_PrivateKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const
136 {
137 return true; // ???
138 }
139
140namespace {
141
142/**
143* Ed25519 verifying operation
144*/
145class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification
146 {
147 public:
148 explicit Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey& key) : m_key(key)
149 {
150 }
151
152 void update(const uint8_t msg[], size_t msg_len) override
153 {
154 m_msg.insert(m_msg.end(), msg, msg + msg_len);
155 }
156
157 bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
158 {
159 if(sig_len != 64)
160 return false;
161
162 const std::vector<uint8_t>& pub_key = m_key.get_public_key();
163 BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
164 const bool ok = ed25519_verify(m_msg.data(), m_msg.size(), sig, pub_key.data(), nullptr, 0);
165 m_msg.clear();
166 return ok;
167 }
168
169 private:
170 std::vector<uint8_t> m_msg;
171 const Ed25519_PublicKey& m_key;
172 };
173
174/**
175* Ed25519 verifying operation with pre-hash
176*/
177class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification
178 {
179 public:
180 Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, const std::string& hash, bool rfc8032) :
181 m_key(key)
182 {
184
185 if(rfc8032)
186 {
187 m_domain_sep = {
188 0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
189 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
190 0x01, 0x00 };
191 }
192 }
193
194 void update(const uint8_t msg[], size_t msg_len) override
195 {
196 m_hash->update(msg, msg_len);
197 }
198
199 bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
200 {
201 if(sig_len != 64)
202 return false;
203 std::vector<uint8_t> msg_hash(m_hash->output_length());
204 m_hash->final(msg_hash.data());
205
206 const std::vector<uint8_t>& pub_key = m_key.get_public_key();
207 BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
208 return ed25519_verify(msg_hash.data(), msg_hash.size(), sig, pub_key.data(), m_domain_sep.data(), m_domain_sep.size());
209 }
210
211 private:
212 std::unique_ptr<HashFunction> m_hash;
213 const Ed25519_PublicKey& m_key;
214 std::vector<uint8_t> m_domain_sep;
215 };
216
217/**
218* Ed25519 signing operation ('pure' - signs message directly)
219*/
220class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature
221 {
222 public:
223 explicit Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey& key) : m_key(key)
224 {
225 }
226
227 void update(const uint8_t msg[], size_t msg_len) override
228 {
229 m_msg.insert(m_msg.end(), msg, msg + msg_len);
230 }
231
232 secure_vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override
233 {
234 secure_vector<uint8_t> sig(64);
235 ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.get_private_key().data(), nullptr, 0);
236 m_msg.clear();
237 return sig;
238 }
239
240 size_t signature_length() const override { return 64; }
241
242 private:
243 std::vector<uint8_t> m_msg;
244 const Ed25519_PrivateKey& m_key;
245 };
246
247/**
248* Ed25519 signing operation with pre-hash
249*/
250class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature
251 {
252 public:
253 Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, const std::string& hash, bool rfc8032) :
254 m_key(key)
255 {
257
258 if(rfc8032)
259 {
260 m_domain_sep = std::vector<uint8_t>{
261 0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
262 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
263 0x01, 0x00 };
264 }
265 }
266
267 size_t signature_length() const override { return 64; }
268
269 void update(const uint8_t msg[], size_t msg_len) override
270 {
271 m_hash->update(msg, msg_len);
272 }
273
274 secure_vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override
275 {
276 secure_vector<uint8_t> sig(64);
277 std::vector<uint8_t> msg_hash(m_hash->output_length());
278 m_hash->final(msg_hash.data());
279 ed25519_sign(sig.data(),
280 msg_hash.data(), msg_hash.size(),
281 m_key.get_private_key().data(),
282 m_domain_sep.data(), m_domain_sep.size());
283 return sig;
284 }
285
286 private:
287 std::unique_ptr<HashFunction> m_hash;
288 const Ed25519_PrivateKey& m_key;
289 std::vector<uint8_t> m_domain_sep;
290 };
291
292}
293
294std::unique_ptr<PK_Ops::Verification>
296 const std::string& provider) const
297 {
298 if(provider == "base" || provider.empty())
299 {
300 if(params.empty() || params == "Identity" || params == "Pure")
301 return std::make_unique<Ed25519_Pure_Verify_Operation>(*this);
302 else if(params == "Ed25519ph")
303 return std::make_unique<Ed25519_Hashed_Verify_Operation>(*this, "SHA-512", true);
304 else
305 return std::make_unique<Ed25519_Hashed_Verify_Operation>(*this, params, false);
306 }
307 throw Provider_Not_Found(algo_name(), provider);
308 }
309
310std::unique_ptr<PK_Ops::Signature>
312 const std::string& params,
313 const std::string& provider) const
314 {
315 if(provider == "base" || provider.empty())
316 {
317 if(params.empty() || params == "Identity" || params == "Pure")
318 return std::make_unique<Ed25519_Pure_Sign_Operation>(*this);
319 else if(params == "Ed25519ph")
320 return std::make_unique<Ed25519_Hashed_Sign_Operation>(*this, "SHA-512", true);
321 else
322 return std::make_unique<Ed25519_Hashed_Sign_Operation>(*this, params, false);
323 }
324 throw Provider_Not_Found(algo_name(), provider);
325 }
326
327}
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:80
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:187
BER_Decoder & discard_remaining()
Definition: ber_dec.cpp:228
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:155
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:288
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
std::unique_ptr< Public_Key > public_key() const override
Ed25519_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
bool check_key(RandomNumberGenerator &rng, bool strong) const override
secure_vector< uint8_t > private_key_bits() const override
std::vector< uint8_t > m_public
Definition: ed25519.h:55
const std::vector< uint8_t > & get_public_key() const
Definition: ed25519.h:51
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition: ed25519_key.cpp:26
std::string algo_name() const override
Definition: ed25519.h:21
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
std::vector< uint8_t > public_key_bits() const override
Definition: ed25519_key.cpp:81
AlgorithmIdentifier algorithm_identifier() const override
Definition: ed25519_key.cpp:21
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:312
virtual OID get_oid() const
Definition: pk_keys.cpp:53
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:167
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
Definition: alg_id.cpp:13
int ge_frombytes_negate_vartime(ge_p3 *v, const uint8_t *)
Definition: ge.cpp:457
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:36
void ed25519_gen_keypair(uint8_t *pk, uint8_t *sk, const uint8_t seed[32])
Definition: ed25519.cpp:18
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:126
bool same_mem(const T *p1, const T *p2, size_t n)
Definition: mem_ops.h:210
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:71
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
void ge_double_scalarmult_vartime(uint8_t out[32], const uint8_t a[], const ge_p3 *A, const uint8_t b[])
MechanismType hash