11#include <botan/ed25519.h>
13#include <botan/ber_dec.h>
14#include <botan/der_enc.h>
15#include <botan/hash.h>
17#include <botan/internal/ct_utils.h>
18#include <botan/internal/ed25519_internal.h>
19#include <botan/internal/pk_ops_impl.h>
36 const uint8_t identity_element[32] = {1};
42 const uint8_t modm_m[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
43 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
46 const unsigned char zero[32] = {0};
48 unsigned char pkcopy[32];
51 pkcopy[31] ^= (1 << 7);
60 if(!
CT::is_equal(result, identity_element, 32).as_bool()) {
71 m_public.assign(pub_key, pub_key + pub_len);
75 m_public.assign(key_bits.begin(), key_bits.end());
87 return std::make_unique<Ed25519_PrivateKey>(rng);
91 if(secret_key.size() == 64) {
92 m_private = secret_key;
93 m_public.assign(m_private.begin() + 32, m_private.end());
94 }
else if(secret_key.size() == 32) {
106 m_private.resize(64);
114 if(bits.size() != 32) {
118 m_private.resize(64);
142 explicit Ed25519_Pure_Verify_Operation(
const Ed25519_PublicKey& key) : m_key(key.get_public_key()) {}
144 void update(
const uint8_t msg[],
size_t msg_len)
override { m_msg.insert(m_msg.end(), msg, msg + msg_len); }
146 bool is_valid_signature(
const uint8_t sig[],
size_t sig_len)
override {
152 const bool ok =
ed25519_verify(m_msg.data(), m_msg.size(), sig, m_key.data(),
nullptr, 0);
157 std::string hash_function()
const override {
return "SHA-512"; }
160 std::vector<uint8_t> m_msg;
161 std::vector<uint8_t> m_key;
167class Ed25519_Hashed_Verify_Operation
final :
public PK_Ops::Verification {
169 Ed25519_Hashed_Verify_Operation(
const Ed25519_PublicKey& key, std::string_view hash,
bool rfc8032) :
170 m_key(key.get_public_key()) {
174 m_domain_sep = {0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
175 0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
176 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
180 void update(
const uint8_t msg[],
size_t msg_len)
override { m_hash->update(msg, msg_len); }
182 bool is_valid_signature(
const uint8_t sig[],
size_t sig_len)
override {
186 std::vector<uint8_t> msg_hash(m_hash->output_length());
187 m_hash->final(msg_hash.data());
191 msg_hash.data(), msg_hash.size(), sig, m_key.data(), m_domain_sep.data(), m_domain_sep.size());
194 std::string hash_function()
const override {
return m_hash->name(); }
197 std::unique_ptr<HashFunction> m_hash;
198 std::vector<uint8_t> m_key;
199 std::vector<uint8_t> m_domain_sep;
205class Ed25519_Pure_Sign_Operation
final :
public PK_Ops::Signature {
207 explicit Ed25519_Pure_Sign_Operation(
const Ed25519_PrivateKey& key) : m_key(key.raw_private_key_bits()) {}
209 void update(
const uint8_t msg[],
size_t msg_len)
override { m_msg.insert(m_msg.end(), msg, msg + msg_len); }
211 secure_vector<uint8_t> sign(RandomNumberGenerator& )
override {
212 secure_vector<uint8_t> sig(64);
213 ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.data(),
nullptr, 0);
218 size_t signature_length()
const override {
return 64; }
220 AlgorithmIdentifier algorithm_identifier()
const override;
222 std::string hash_function()
const override {
return "SHA-512"; }
225 std::vector<uint8_t> m_msg;
226 secure_vector<uint8_t> m_key;
229AlgorithmIdentifier Ed25519_Pure_Sign_Operation::algorithm_identifier()
const {
230 return AlgorithmIdentifier(OID::from_string(
"Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
236class Ed25519_Hashed_Sign_Operation
final :
public PK_Ops::Signature {
238 Ed25519_Hashed_Sign_Operation(
const Ed25519_PrivateKey& key, std::string_view hash,
bool rfc8032) :
239 m_key(key.raw_private_key_bits()) {
240 m_hash = HashFunction::create_or_throw(hash);
243 m_domain_sep = std::vector<uint8_t>{0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
244 0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
245 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
249 size_t signature_length()
const override {
return 64; }
251 void update(
const uint8_t msg[],
size_t msg_len)
override { m_hash->update(msg, msg_len); }
253 secure_vector<uint8_t> sign(RandomNumberGenerator& )
override {
254 secure_vector<uint8_t> sig(64);
255 std::vector<uint8_t> msg_hash(m_hash->output_length());
256 m_hash->final(msg_hash.data());
258 sig.data(), msg_hash.data(), msg_hash.size(), m_key.data(), m_domain_sep.data(), m_domain_sep.size());
262 std::string hash_function()
const override {
return m_hash->name(); }
265 std::unique_ptr<HashFunction> m_hash;
266 secure_vector<uint8_t> m_key;
267 std::vector<uint8_t> m_domain_sep;
273 std::string_view provider)
const {
274 if(provider ==
"base" || provider.empty()) {
275 if(params.empty() || params ==
"Identity" || params ==
"Pure") {
276 return std::make_unique<Ed25519_Pure_Verify_Operation>(*
this);
277 }
else if(params ==
"Ed25519ph") {
278 return std::make_unique<Ed25519_Hashed_Verify_Operation>(*
this,
"SHA-512",
true);
280 return std::make_unique<Ed25519_Hashed_Verify_Operation>(*
this, params,
false);
287 std::string_view provider)
const {
288 if(provider ==
"base" || provider.empty()) {
289 if(alg_id != this->algorithm_identifier()) {
290 throw Decoding_Error(
"Unexpected AlgorithmIdentifier for Ed25519 X509 signature");
293 return std::make_unique<Ed25519_Pure_Verify_Operation>(*
this);
299 std::string_view params,
300 std::string_view provider)
const {
301 if(provider ==
"base" || provider.empty()) {
302 if(params.empty() || params ==
"Identity" || params ==
"Pure") {
303 return std::make_unique<Ed25519_Pure_Sign_Operation>(*
this);
304 }
else if(params ==
"Ed25519ph") {
305 return std::make_unique<Ed25519_Hashed_Sign_Operation>(*
this,
"SHA-512",
true);
307 return std::make_unique<Ed25519_Hashed_Sign_Operation>(*
this, params,
false);
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
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)
std::unique_ptr< Public_Key > public_key() const override
bool check_key(RandomNumberGenerator &rng, bool strong) const override
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 > private_key_bits() const override
std::vector< uint8_t > m_public
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
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::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
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
void random_vec(std::span< uint8_t > v)
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
int ge_frombytes_negate_vartime(ge_p3 *v, const uint8_t *)
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)
void ed25519_gen_keypair(uint8_t *pk, uint8_t *sk, 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)
constexpr void copy_mem(T *out, const T *in, size_t n)
void ge_double_scalarmult_vartime(uint8_t out[32], const uint8_t a[], const ge_p3 *A, const uint8_t b[])