Botan  2.12.1
Crypto and TLS for C++11
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 
18 namespace Botan {
19 
21  {
23  }
24 
26  {
27  return true; // no tests possible?
28  // TODO could check cofactor
29  }
30 
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 
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 
47 std::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]);
93  return DER_Encoder().encode(bits, OCTET_STRING).get_contents();
94  }
95 
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:
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 */
138 class 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 */
181 class 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 */
211 class 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 
255 std::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 
271 std::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 }
void ed25519_gen_keypair(uint8_t *pk, uint8_t *sk, const uint8_t seed[32])
Definition: ed25519.cpp:18
std::vector< uint8_t > m_public
Definition: ed25519.h:55
std::string algo_name() const override
Definition: ed25519.h:21
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:344
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string &params, const std::string &provider) const override
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:141
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition: ed25519_key.cpp:25
int(* final)(unsigned char *, CTX *)
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:152
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
std::unique_ptr< PK_Ops::Verification > create_verification_op(const std::string &params, const std::string &provider) const override
secure_vector< uint8_t > private_key_bits() const override
Definition: ed25519_key.cpp:90
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
virtual OID get_oid() const
Definition: pk_keys.cpp:53
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition: ed25519_key.cpp:96
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:81
std::vector< uint8_t > public_key_bits() const override
Definition: ed25519_key.cpp:47
Ed25519_PrivateKey(const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &key_bits)
Definition: ed25519_key.cpp:77
BER_Decoder & discard_remaining()
Definition: ber_dec.cpp:226
Definition: alg_id.cpp:13
int(* update)(CTX *, const void *, CC_LONG len)
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
AlgorithmIdentifier algorithm_identifier() const override
Definition: ed25519_key.cpp:20
MechanismType hash
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