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
18 namespace Botan {
19
algorithm_identifier() const20 AlgorithmIdentifier Ed25519_PublicKey::algorithm_identifier() const
21 {
22 return AlgorithmIdentifier(get_oid(), AlgorithmIdentifier::USE_EMPTY_PARAM);
23 }
24
check_key(RandomNumberGenerator &,bool) const25 bool Ed25519_PublicKey::check_key(RandomNumberGenerator&, bool) const
26 {
27 return true; // no tests possible?
28 // TODO could check cofactor
29 }
30
Ed25519_PublicKey(const uint8_t pub_key[],size_t pub_len)31 Ed25519_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
Ed25519_PublicKey(const AlgorithmIdentifier &,const std::vector<uint8_t> & key_bits)38 Ed25519_PublicKey::Ed25519_PublicKey(const AlgorithmIdentifier&,
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
public_key_bits() const47 std::vector<uint8_t> Ed25519_PublicKey::public_key_bits() const
48 {
49 return m_public;
50 }
51
Ed25519_PrivateKey(const secure_vector<uint8_t> & secret_key)52 Ed25519_PrivateKey::Ed25519_PrivateKey(const secure_vector<uint8_t>& secret_key)
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
Ed25519_PrivateKey(RandomNumberGenerator & rng)69 Ed25519_PrivateKey::Ed25519_PrivateKey(RandomNumberGenerator& rng)
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
Ed25519_PrivateKey(const AlgorithmIdentifier &,const secure_vector<uint8_t> & key_bits)77 Ed25519_PrivateKey::Ed25519_PrivateKey(const AlgorithmIdentifier&,
78 const secure_vector<uint8_t>& key_bits)
79 {
80 secure_vector<uint8_t> bits;
81 BER_Decoder(key_bits).decode(bits, OCTET_STRING).discard_remaining();
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
private_key_bits() const90 secure_vector<uint8_t> Ed25519_PrivateKey::private_key_bits() const
91 {
92 secure_vector<uint8_t> bits(&m_private[0], &m_private[32]);
93 return DER_Encoder().encode(bits, OCTET_STRING).get_contents();
94 }
95
check_key(RandomNumberGenerator &,bool) const96 bool Ed25519_PrivateKey::check_key(RandomNumberGenerator&, bool) const
97 {
98 return true; // ???
99 }
100
101 namespace {
102
103 /**
104 * Ed25519 verifying operation
105 */
106 class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification
107 {
108 public:
Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey & key)109 Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey& key) : m_key(key)
110 {
111 }
112
update(const uint8_t msg[],size_t msg_len)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
is_valid_signature(const uint8_t sig[],size_t sig_len)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 */
138 class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification
139 {
140 public:
Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey & key,const std::string & hash,bool rfc8032)141 Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, const std::string& hash, bool rfc8032) :
142 m_key(key)
143 {
144 m_hash = HashFunction::create_or_throw(hash);
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
update(const uint8_t msg[],size_t msg_len)155 void update(const uint8_t msg[], size_t msg_len) override
156 {
157 m_hash->update(msg, msg_len);
158 }
159
is_valid_signature(const uint8_t sig[],size_t sig_len)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 */
181 class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature
182 {
183 public:
Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey & key)184 Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey& key) : m_key(key)
185 {
186 }
187
update(const uint8_t msg[],size_t msg_len)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
sign(RandomNumberGenerator &)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
signature_length() const201 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 */
211 class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature
212 {
213 public:
Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey & key,const std::string & hash,bool rfc8032)214 Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, const std::string& hash, bool rfc8032) :
215 m_key(key)
216 {
217 m_hash = HashFunction::create_or_throw(hash);
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
signature_length() const228 size_t signature_length() const override { return 64; }
229
update(const uint8_t msg[],size_t msg_len)230 void update(const uint8_t msg[], size_t msg_len) override
231 {
232 m_hash->update(msg, msg_len);
233 }
234
sign(RandomNumberGenerator &)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
255 std::unique_ptr<PK_Ops::Verification>
create_verification_op(const std::string & params,const std::string & provider) const256 Ed25519_PublicKey::create_verification_op(const std::string& params,
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
271 std::unique_ptr<PK_Ops::Signature>
create_signature_op(RandomNumberGenerator &,const std::string & params,const std::string & provider) const272 Ed25519_PrivateKey::create_signature_op(RandomNumberGenerator&,
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 }
289