9#include <botan/ed25519.h>
11#include <botan/ber_dec.h>
12#include <botan/der_enc.h>
13#include <botan/hash.h>
15#include <botan/internal/ct_utils.h>
16#include <botan/internal/ed25519_internal.h>
17#include <botan/internal/pk_ops_impl.h>
21class Ed25519_PublicKey_Data final {
23 explicit Ed25519_PublicKey_Data(std::vector<uint8_t> key) : m_key(std::move(key)) {}
25 const std::vector<uint8_t>& key()
const {
return m_key; }
28 std::vector<uint8_t> m_key;
31class Ed25519_PrivateKey_Data final {
46 return m_private->key();
50 return m_private->key();
58 const std::vector<uint8_t>& pub =
m_public->key();
60 if(pub.size() != 32) {
68 const uint8_t identity_element[32] = {1};
69 if(
CT::is_equal(pub.data(), identity_element, 32).as_bool()) {
77 uint8_t noncanonical_identity[32] = {1};
78 noncanonical_identity[31] = 0x80;
79 if(
CT::is_equal(pub.data(), noncanonical_identity, 32).as_bool()) {
84 const uint8_t modm_m[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
85 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
88 const unsigned char zero[32] = {0};
90 unsigned char pkcopy[32];
93 pkcopy[31] ^= (1 << 7);
102 m_public = std::make_shared<const Ed25519_PublicKey_Data>(std::vector<uint8_t>(pub_key, pub_key + pub_len));
108 throw Decoding_Error(
"Unexpected parameters for Ed25519 public key");
111 if(key_bits.size() != 32) {
115 m_public = std::make_shared<const Ed25519_PublicKey_Data>(std::vector<uint8_t>(key_bits.begin(), key_bits.end()));
127 return std::make_unique<Ed25519_PrivateKey>(rng);
135 std::shared_ptr<const Ed25519_PublicKey_Data>& pk_out,
136 std::shared_ptr<const Ed25519_PrivateKey_Data>& sk_out) {
138 pk_out = std::make_shared<const Ed25519_PublicKey_Data>(
139 std::vector<uint8_t>(expanded_key.begin() + 32, expanded_key.end()));
140 sk_out = std::make_shared<const Ed25519_PrivateKey_Data>(std::move(expanded_key));
146 std::vector<uint8_t> pk(32);
155 if(secret_key.size() == 64) {
157 }
else if(secret_key.size() == 32) {
158 load_ed25519_keypair(ed25519_expand_seed(secret_key),
m_public, m_private);
166 BOTAN_ARG_CHECK(seed.size() == 32,
"Ed25519 seed must be exactly 32 bytes long");
172 BOTAN_ARG_CHECK(bytes.size() == 64,
"Ed25519 private key must be exactly 64 bytes long");
178 load_ed25519_keypair(ed25519_expand_seed(seed),
m_public, m_private);
184 throw Decoding_Error(
"Unexpected parameters for Ed25519 private key");
190 if(bits.size() != 32) {
193 load_ed25519_keypair(ed25519_expand_seed(bits),
m_public, m_private);
201 const auto& priv = m_private->key();
207 std::vector<uint8_t> public_point(32);
211 return public_point ==
m_public->key();
221 explicit Ed25519_Pure_Verify_Operation(std::shared_ptr<const Ed25519_PublicKey_Data> key) :
222 m_key(std::move(key)) {}
224 void update(std::span<const uint8_t> msg)
override { m_msg.insert(m_msg.end(), msg.begin(), msg.end()); }
226 bool is_valid_signature(std::span<const uint8_t> sig)
override {
227 if(sig.size() != 64) {
232 const auto& key = m_key->key();
234 const bool ok =
ed25519_verify(m_msg.data(), m_msg.size(), sig.data(), key.data(),
nullptr, 0);
239 std::string hash_function()
const override {
return "SHA-512"; }
242 std::vector<uint8_t> m_msg;
243 std::shared_ptr<const Ed25519_PublicKey_Data> m_key;
251 Ed25519_Hashed_Verify_Operation(std::shared_ptr<const Ed25519_PublicKey_Data> key,
252 std::string_view hash,
254 PK_Ops::Verification_with_Hash(hash), m_key(std::move(key)) {
256 m_domain_sep = {0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
257 0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
258 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
262 bool verify(std::span<const uint8_t> ph, std::span<const uint8_t> sig)
override {
263 if(sig.size() != 64) {
267 const auto& key = m_key->key();
269 return ed25519_verify(ph.data(), ph.size(), sig.data(), key.data(), m_domain_sep.data(), m_domain_sep.size());
273 std::shared_ptr<const Ed25519_PublicKey_Data> m_key;
274 std::vector<uint8_t> m_domain_sep;
282 explicit Ed25519_Pure_Sign_Operation(std::shared_ptr<const Ed25519_PrivateKey_Data> key) :
283 m_key(std::move(key)) {}
285 void update(std::span<const uint8_t> msg)
override { m_msg.insert(m_msg.end(), msg.begin(), msg.end()); }
287 std::vector<uint8_t> sign(RandomNumberGenerator& )
override {
288 std::vector<uint8_t> sig(64);
289 const auto& key = m_key->key();
290 ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), key.data(),
nullptr, 0);
295 size_t signature_length()
const override {
return 64; }
297 AlgorithmIdentifier algorithm_identifier()
const override;
299 std::string hash_function()
const override {
return "SHA-512"; }
302 std::vector<uint8_t> m_msg;
303 std::shared_ptr<const Ed25519_PrivateKey_Data> m_key;
307 return AlgorithmIdentifier(OID::from_string(
"Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
313class Ed25519_Hashed_Sign_Operation final :
public PK_Ops::Signature_with_Hash {
315 Ed25519_Hashed_Sign_Operation(std::shared_ptr<const Ed25519_PrivateKey_Data> key,
316 std::string_view hash,
318 PK_Ops::Signature_with_Hash(hash), m_key(std::move(key)) {
320 m_domain_sep = std::vector<uint8_t>{0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
321 0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
322 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
326 size_t signature_length()
const override {
return 64; }
328 std::vector<uint8_t> raw_sign(std::span<const uint8_t> ph, RandomNumberGenerator& )
override {
329 std::vector<uint8_t> sig(64);
330 const auto& key = m_key->key();
331 ed25519_sign(sig.data(), ph.data(), ph.size(), key.data(), m_domain_sep.data(), m_domain_sep.size());
336 std::shared_ptr<const Ed25519_PrivateKey_Data> m_key;
337 std::vector<uint8_t> m_domain_sep;
343 std::string_view provider)
const {
344 if(provider ==
"base" || provider.empty()) {
345 if(params.empty() || params ==
"Identity" || params ==
"Pure") {
346 return std::make_unique<Ed25519_Pure_Verify_Operation>(
m_public);
347 }
else if(params ==
"Ed25519ph") {
348 return std::make_unique<Ed25519_Hashed_Verify_Operation>(
m_public,
"SHA-512",
true);
350 return std::make_unique<Ed25519_Hashed_Verify_Operation>(
m_public, params,
false);
357 std::string_view provider)
const {
358 if(provider ==
"base" || provider.empty()) {
360 throw Decoding_Error(
"Unexpected AlgorithmIdentifier for Ed25519 X509 signature");
363 return std::make_unique<Ed25519_Pure_Verify_Operation>(
m_public);
369 std::string_view params,
370 std::string_view provider)
const {
371 if(provider ==
"base" || provider.empty()) {
372 if(params.empty() || params ==
"Identity" || params ==
"Pure") {
373 return std::make_unique<Ed25519_Pure_Sign_Operation>(m_private);
374 }
else if(params ==
"Ed25519ph") {
375 return std::make_unique<Ed25519_Hashed_Sign_Operation>(m_private,
"SHA-512",
true);
377 return std::make_unique<Ed25519_Hashed_Sign_Operation>(m_private, params,
false);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
#define BOTAN_ARG_CHECK(expr, msg)
bool parameters_are_empty() const
virtual OID object_identifier() const
BER_Decoder & decode(bool &out)
BER_Decoder & discard_remaining()
secure_vector< uint8_t > get_contents()
DER_Encoder & encode(bool b)
Ed25519_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
const secure_vector< uint8_t > & get_private_key() const
static Ed25519_PrivateKey from_seed(std::span< const uint8_t > seed)
std::unique_ptr< Public_Key > public_key() const override
bool check_key(RandomNumberGenerator &rng, bool strong) const override
static Ed25519_PrivateKey from_bytes(std::span< const uint8_t > bytes)
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 > raw_private_key_bits() const override
secure_vector< uint8_t > private_key_bits() const override
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
std::shared_ptr< const Ed25519_PublicKey_Data > m_public
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
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::string algo_name() const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
Ed25519_PublicKey()=default
std::vector< uint8_t > public_key_bits() const override
AlgorithmIdentifier algorithm_identifier() const override
std::vector< uint8_t > raw_public_key_bits() const override
void random_vec(std::span< uint8_t > v)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
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)
constexpr void copy_mem(T *out, const T *in, size_t n)
bool signature_check(std::span< const uint8_t, 32 > pk, const uint8_t h[32], const uint8_t r[32], const uint8_t s[32])
void ed25519_gen_keypair(uint8_t pk[32], uint8_t sk[64], const uint8_t seed[32])
std::vector< T, secure_allocator< T > > secure_vector
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)