Botan 2.19.2
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/hash.h>
14#include <botan/ber_dec.h>
15#include <botan/der_enc.h>
16#include <botan/rng.h>
17
18namespace Botan {
19
21 {
23 }
24
26 {
27 return true; // no tests possible?
28 // TODO could check cofactor
29 }
30
31Ed25519_PublicKey::Ed25519_PublicKey(const uint8_t pub_key[], size_t pub_len)
32 {
33 if(pub_len != 32)
34 throw Decoding_Error("Invalid length for Ed25519 key");
35 m_public.assign(pub_key, pub_key + pub_len);
36 }
37
39 const std::vector<uint8_t>& key_bits)
40 {
41 m_public = key_bits;
42
43 if(m_public.size() != 32)
44 throw Decoding_Error("Invalid size for Ed25519 public key");
45 }
46
47std::vector<uint8_t> Ed25519_PublicKey::public_key_bits() const
48 {
49 return m_public;
50 }
51
53 {
54 if(secret_key.size() == 64)
55 {
56 m_private = secret_key;
57 m_public.assign(m_private.begin() + 32, m_private.end());
58 }
59 else if(secret_key.size() == 32)
60 {
61 m_public.resize(32);
62 m_private.resize(64);
63 ed25519_gen_keypair(m_public.data(), m_private.data(), secret_key.data());
64 }
65 else
66 throw Decoding_Error("Invalid size for Ed25519 private key");
67 }
68
70 {
71 const secure_vector<uint8_t> seed = rng.random_vec(32);
72 m_public.resize(32);
73 m_private.resize(64);
74 ed25519_gen_keypair(m_public.data(), m_private.data(), seed.data());
75 }
76
78 const secure_vector<uint8_t>& key_bits)
79 {
82
83 if(bits.size() != 32)
84 throw Decoding_Error("Invalid size for Ed25519 private key");
85 m_public.resize(32);
86 m_private.resize(64);
87 ed25519_gen_keypair(m_public.data(), m_private.data(), bits.data());
88 }
89
91 {
92 secure_vector<uint8_t> bits(&m_private[0], &m_private[32]);
94 }
95
97 {
98 return true; // ???
99 }
100
101namespace {
102
103/**
104* Ed25519 verifying operation
105*/
106class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification
107 {
108 public:
109 Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey& key) : m_key(key)
110 {
111 }
112
113 void update(const uint8_t msg[], size_t msg_len) override
114 {
115 m_msg.insert(m_msg.end(), msg, msg + msg_len);
116 }
117
118 bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
119 {
120 if(sig_len != 64)
121 return false;
122
123 const std::vector<uint8_t>& pub_key = m_key.get_public_key();
124 BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
125 const bool ok = ed25519_verify(m_msg.data(), m_msg.size(), sig, pub_key.data(), nullptr, 0);
126 m_msg.clear();
127 return ok;
128 }
129
130 private:
131 std::vector<uint8_t> m_msg;
132 const Ed25519_PublicKey& m_key;
133 };
134
135/**
136* Ed25519 verifying operation with pre-hash
137*/
138class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification
139 {
140 public:
141 Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, const std::string& hash, bool rfc8032) :
142 m_key(key)
143 {
145
146 if(rfc8032)
147 {
148 m_domain_sep = {
149 0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
150 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
151 0x01, 0x00 };
152 }
153 }
154
155 void update(const uint8_t msg[], size_t msg_len) override
156 {
157 m_hash->update(msg, msg_len);
158 }
159
160 bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
161 {
162 if(sig_len != 64)
163 return false;
164 std::vector<uint8_t> msg_hash(m_hash->output_length());
165 m_hash->final(msg_hash.data());
166
167 const std::vector<uint8_t>& pub_key = m_key.get_public_key();
168 BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
169 return ed25519_verify(msg_hash.data(), msg_hash.size(), sig, pub_key.data(), m_domain_sep.data(), m_domain_sep.size());
170 }
171
172 private:
173 std::unique_ptr<HashFunction> m_hash;
174 const Ed25519_PublicKey& m_key;
175 std::vector<uint8_t> m_domain_sep;
176 };
177
178/**
179* Ed25519 signing operation ('pure' - signs message directly)
180*/
181class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature
182 {
183 public:
184 Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey& key) : m_key(key)
185 {
186 }
187
188 void update(const uint8_t msg[], size_t msg_len) override
189 {
190 m_msg.insert(m_msg.end(), msg, msg + msg_len);
191 }
192
193 secure_vector<uint8_t> sign(RandomNumberGenerator&) override
194 {
195 secure_vector<uint8_t> sig(64);
196 ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.get_private_key().data(), nullptr, 0);
197 m_msg.clear();
198 return sig;
199 }
200
201 size_t signature_length() const override { return 64; }
202
203 private:
204 std::vector<uint8_t> m_msg;
205 const Ed25519_PrivateKey& m_key;
206 };
207
208/**
209* Ed25519 signing operation with pre-hash
210*/
211class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature
212 {
213 public:
214 Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, const std::string& hash, bool rfc8032) :
215 m_key(key)
216 {
218
219 if(rfc8032)
220 {
221 m_domain_sep = std::vector<uint8_t>{
222 0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
223 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
224 0x01, 0x00 };
225 }
226 }
227
228 size_t signature_length() const override { return 64; }
229
230 void update(const uint8_t msg[], size_t msg_len) override
231 {
232 m_hash->update(msg, msg_len);
233 }
234
235 secure_vector<uint8_t> sign(RandomNumberGenerator&) override
236 {
237 secure_vector<uint8_t> sig(64);
238 std::vector<uint8_t> msg_hash(m_hash->output_length());
239 m_hash->final(msg_hash.data());
240 ed25519_sign(sig.data(),
241 msg_hash.data(), msg_hash.size(),
242 m_key.get_private_key().data(),
243 m_domain_sep.data(), m_domain_sep.size());
244 return sig;
245 }
246
247 private:
248 std::unique_ptr<HashFunction> m_hash;
249 const Ed25519_PrivateKey& m_key;
250 std::vector<uint8_t> m_domain_sep;
251 };
252
253}
254
255std::unique_ptr<PK_Ops::Verification>
257 const std::string& provider) const
258 {
259 if(provider == "base" || provider.empty())
260 {
261 if(params == "" || params == "Identity" || params == "Pure")
262 return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Pure_Verify_Operation(*this));
263 else if(params == "Ed25519ph")
264 return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Hashed_Verify_Operation(*this, "SHA-512", true));
265 else
266 return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Hashed_Verify_Operation(*this, params, false));
267 }
268 throw Provider_Not_Found(algo_name(), provider);
269 }
270
271std::unique_ptr<PK_Ops::Signature>
273 const std::string& params,
274 const std::string& provider) const
275 {
276 if(provider == "base" || provider.empty())
277 {
278 if(params == "" || params == "Identity" || params == "Pure")
279 return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Pure_Sign_Operation(*this));
280 else if(params == "Ed25519ph")
281 return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Hashed_Sign_Operation(*this, "SHA-512", true));
282 else
283 return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Hashed_Sign_Operation(*this, params, false));
284 }
285 throw Provider_Not_Found(algo_name(), provider);
286 }
287
288}
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:81
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
BER_Decoder & discard_remaining()
Definition: ber_dec.cpp:226
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:152
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
Ed25519_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: ed25519_key.cpp:77
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition: ed25519_key.cpp:96
secure_vector< uint8_t > private_key_bits() const override
Definition: ed25519_key.cpp:90
std::vector< uint8_t > m_public
Definition: ed25519.h:55
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition: ed25519_key.cpp:25
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:47
AlgorithmIdentifier algorithm_identifier() const override
Definition: ed25519_key.cpp:20
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:329
virtual OID get_oid() const
Definition: pk_keys.cpp:53
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:143
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
Definition: alg_id.cpp:13
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
@ OCTET_STRING
Definition: asn1_obj.h:38
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
MechanismType hash