TrinityCore
Ed25519.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Ed25519.h"
19#include "CryptoHash.h"
20#include "Memory.h"
21#include <ed25519/ed25519.h>
22#include <openssl/pem.h>
23#include <memory>
24
25namespace Trinity::Crypto
26{
27Ed25519::Ed25519() = default;
28
30{
31 *this = right;
32}
33
34Ed25519::Ed25519(Ed25519&& right) noexcept
35{
36 *this = std::move(right);
37}
38
40{
41 EVP_PKEY_free(_key);
42}
43
45{
46 if (this == &right)
47 return *this;
48
49 _key = right._key; // EVP_PKEY uses reference counting internally, just copy the pointer
50 EVP_PKEY_up_ref(_key); // Bump reference count for PKEY, as every instance of this class holds two references to PKEY and destructor decrements it twice
51 return *this;
52}
53
55{
56 if (this == &right)
57 return *this;
58
59 _key = std::exchange(right._key, EVP_PKEY_new());
60 return *this;
61}
62
63bool Ed25519::LoadFromFile(std::string const& fileName)
64{
65 if (_key)
66 {
67 EVP_PKEY_free(_key);
68 _key = nullptr;
69 }
70
71 auto keyBIO = make_unique_ptr_with_deleter(BIO_new_file(fileName.c_str(), "r"), BIO_free);
72 if (!keyBIO)
73 return false;
74
75 _key = EVP_PKEY_new();
76 if (!PEM_read_bio_PrivateKey(keyBIO.get(), &_key, nullptr, nullptr))
77 return false;
78
79 return true;
80}
81
82bool Ed25519::LoadFromString(std::string const& keyPem)
83{
84 if (_key)
85 {
86 EVP_PKEY_free(_key);
87 _key = nullptr;
88 }
89
90 auto keyBIO = make_unique_ptr_with_deleter(BIO_new_mem_buf(
91 const_cast<char*>(keyPem.c_str()) /*api hack - this function assumes memory is readonly but lacks const modifier*/,
92 keyPem.length() + 1), BIO_free);
93 if (!keyBIO)
94 return false;
95
96 _key = EVP_PKEY_new();
97 if (!PEM_read_bio_PrivateKey(keyBIO.get(), &_key, nullptr, nullptr))
98 return false;
99
100 return true;
101}
102
103bool Ed25519::LoadFromByteArray(std::array<uint8, 32> const& keyBytes)
104{
105 if (_key)
106 {
107 EVP_PKEY_free(_key);
108 _key = nullptr;
109 }
110
111 _key = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, nullptr, keyBytes.data(), keyBytes.size());
112 if (!_key)
113 return false;
114
115 return true;
116}
117
118bool Ed25519::Sign(uint8 const* message, std::size_t messageLength, std::vector<uint8>& output)
119{
120 constexpr size_t KeySize = 32;
121
122 uint8 publicKey[KeySize] = {};
123 std::size_t keyLength = KeySize;
124 EVP_PKEY_get_raw_public_key(_key, publicKey, &keyLength);
125
126 uint8 privateKey[KeySize] = {};
127 keyLength = KeySize;
128 EVP_PKEY_get_raw_private_key(_key, privateKey, &keyLength);
129
130 output.resize(64);
131 int result = ED25519_sign(output.data(), message, messageLength, publicKey, privateKey);
132 return result != 0;
133}
134
135bool Ed25519::SignWithContext(uint8 const* message, std::size_t messageLength, std::vector<uint8> const& context, std::vector<uint8>& output)
136{
137 constexpr size_t KeySize = 32;
138
139 uint8 publicKey[KeySize] = {};
140 std::size_t keyLength = KeySize;
141 EVP_PKEY_get_raw_public_key(_key, publicKey, &keyLength);
142
143 uint8 privateKey[KeySize] = {};
144 keyLength = KeySize;
145 EVP_PKEY_get_raw_private_key(_key, privateKey, &keyLength);
146
147 output.resize(64);
148 int result = ED25519_sign_ctx(output.data(), message, messageLength, publicKey, privateKey, context.data(), context.size());
149 return result != 0;
150}
151}
uint8_t uint8
Definition: Define.h:144
bool LoadFromByteArray(std::array< uint8, 32 > const &keyBytes)
Definition: Ed25519.cpp:103
Ed25519 & operator=(Ed25519 const &right)
Definition: Ed25519.cpp:44
bool LoadFromFile(std::string const &fileName)
Definition: Ed25519.cpp:63
bool SignWithContext(std::array< uint8, N > const &message, std::vector< uint8 > const &context, std::vector< uint8 > &output)
Definition: Ed25519.h:57
bool Sign(std::array< uint8, N > const &message, std::vector< uint8 > &output)
Definition: Ed25519.h:49
bool LoadFromString(std::string const &keyPem)
Definition: Ed25519.cpp:82
auto make_unique_ptr_with_deleter(T ptr, Del &&deleter)
Definition: Memory.h:41