4#ifdef MAL_PACKET_WEAVER_HAS_OPENSSL
5namespace mal_packet_weaver::crypto::ECDSA
13 [[nodiscard]]
inline int GetCurveByName(
const std::string_view curve)
15 if (curve ==
"secp256k1")
19 else if (curve ==
"secp384r1")
23 else if (curve ==
"secp521r1")
28 throw std::invalid_argument(
"Unknown curve type");
35 class KeyPairGenerator : non_copyable_non_movable
42 explicit KeyPairGenerator(
const int curve_id)
44 ctx_.reset(EVP_PKEY_CTX_new_id(EVP_PKEY_EC,
nullptr));
45 AlwaysAssert(ctx_ !=
nullptr,
"EVP_PKEY_CTX_new_id() failed");
46 AlwaysAssert(EVP_PKEY_keygen_init(ctx_.get()) > 0,
"EVP_PKEY_keygen_init() failed");
47 AlwaysAssert(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx_.get(), curve_id) > 0,
48 "EVP_PKEY_CTX_set_ec_paramgen_curve_nid() failed");
55 explicit KeyPairGenerator(
const std::string_view curve_name) : KeyPairGenerator(GetCurveByName(curve_name)) {}
61 [[nodiscard]] KeyPair generate()
const
63 EVP_PKEY_WRAPPER pkey;
65 EVP_PKEY *pkey_ =
nullptr;
66 AlwaysAssert(EVP_PKEY_keygen(ctx_.get(), &pkey_) > 0,
"EVP_PKEY_keygen() failed");
69 unsigned char *key_data;
70 unsigned long key_size;
72 BIO_WRAPPER bio{ BIO_new(BIO_s_mem()) };
74 AlwaysAssert(PEM_write_bio_PrivateKey(bio.get(), pkey.get(),
nullptr,
nullptr, 0,
nullptr,
nullptr) > 0,
75 "PEM_write_bio_PrivateKey() failed");
76 key_size = BIO_get_mem_data(bio.get(), &key_data);
79 private_key.resize(key_size);
80 std::copy_n(key_data, key_size, private_key.as<
unsigned char>());
82 bio.reset(BIO_new(BIO_s_mem()));
84 AlwaysAssert(PEM_write_bio_PUBKEY(bio.get(), pkey.get()) > 0,
"PEM_write_bio_PUBKEY() failed");
85 key_size = BIO_get_mem_data(bio.get(), &key_data);
87 public_key.resize(key_size);
88 std::copy_n(key_data, key_size, public_key.as<
unsigned char>());
90 return KeyPair{ private_key, public_key };
94 EVP_PKEY_CTX_WRAPPER ctx_ =
nullptr;
100 class Signer : non_copyable_non_movable
108 Signer(
const KeyView private_key,
const Hash::HashType hash_type) : hash_type_(hash_type)
110 BIO_WRAPPER bio{ BIO_new_mem_buf(private_key.data(),
static_cast<int>(private_key.size())) };
112 pkey_.reset(PEM_read_bio_PrivateKey(bio.get(),
nullptr,
nullptr,
nullptr));
113 AlwaysAssert(pkey_ !=
nullptr,
"PEM_read_bio_PrivateKey() failed");
115 ctx_.reset(EVP_PKEY_CTX_new(pkey_.get(),
nullptr));
116 AlwaysAssert(ctx_ !=
nullptr,
"EVP_PKEY_CTX_new() failed");
117 AlwaysAssert(EVP_PKEY_sign_init(ctx_.get()) > 0,
"EVP_PKEY_sign_init() failed");
118 if (hash_type == Hash::HashType::SHA256)
120 AlwaysAssert(EVP_PKEY_CTX_set_signature_md(ctx_.get(), EVP_sha256()) > 0,
121 "EVP_PKEY_CTX_set_signature_md() failed");
123 else if (hash_type == Hash::HashType::SHA384)
125 AlwaysAssert(EVP_PKEY_CTX_set_signature_md(ctx_.get(), EVP_sha384()) > 0,
126 "EVP_PKEY_CTX_set_signature_md() failed");
128 else if (hash_type == Hash::HashType::SHA512)
130 AlwaysAssert(EVP_PKEY_CTX_set_signature_md(ctx_.get(), EVP_sha512()) > 0,
131 "EVP_PKEY_CTX_set_signature_md() failed");
144 [[nodiscard]] ByteArray sign_hash(
const Hash hash)
const
146 Assert(hash.hash_type == hash_type_,
"Unsupported hash type");
148 size_t signature_size = 0;
151 AlwaysAssert(EVP_PKEY_sign(ctx_.get(),
nullptr, &signature_size, hash.as_uint8(), hash.size()) > 0,
152 "EVP_PKEY_sign() failed");
153 signature.resize(signature_size);
155 AlwaysAssert(EVP_PKEY_sign(ctx_.get(), signature.as<
unsigned char>(), &signature_size, hash.as_uint8(),
157 "EVP_PKEY_sign() failed");
158 signature.resize(signature_size);
167 [[nodiscard]] ByteArray sign_data(
const ByteView data)
const
169 const Hash hash = SHA::ComputeHash(data, hash_type_);
170 return sign_hash(hash);
174 EVP_PKEY_CTX_WRAPPER ctx_ =
nullptr;
175 EVP_PKEY_WRAPPER pkey_ =
nullptr;
176 const Hash::HashType hash_type_;
182 class Verifier : non_copyable_non_movable
190 Verifier(
const KeyView public_key,
const Hash::HashType hash_type) : hash_type_(hash_type)
192 BIO_WRAPPER bio{ BIO_new_mem_buf(public_key.data(),
static_cast<int>(public_key.size())) };
194 pkey_.reset(PEM_read_bio_PUBKEY(bio.get(),
nullptr,
nullptr,
nullptr));
195 AlwaysAssert(pkey_ !=
nullptr,
"PEM_read_bio_PUBKEY() failed");
197 ctx_.reset(EVP_PKEY_CTX_new(pkey_.get(),
nullptr));
198 AlwaysAssert(ctx_ !=
nullptr,
"EVP_PKEY_CTX_new() failed");
199 AlwaysAssert(EVP_PKEY_verify_init(ctx_.get()) > 0,
"EVP_PKEY_verify_init() failed");
200 if (hash_type == Hash::HashType::SHA256)
202 AlwaysAssert(EVP_PKEY_CTX_set_signature_md(ctx_.get(), EVP_sha256()) > 0,
203 "EVP_PKEY_CTX_set_signature_md() failed");
205 else if (hash_type == Hash::HashType::SHA384)
207 AlwaysAssert(EVP_PKEY_CTX_set_signature_md(ctx_.get(), EVP_sha384()) > 0,
208 "EVP_PKEY_CTX_set_signature_md() failed");
210 else if (hash_type == Hash::HashType::SHA512)
212 AlwaysAssert(EVP_PKEY_CTX_set_signature_md(ctx_.get(), EVP_sha512()) > 0,
213 "EVP_PKEY_CTX_set_signature_md() failed");
227 [[nodiscard]]
bool verify_hash(
const Hash hash,
const ByteView signature)
const
229 Assert(hash.hash_type == hash_type_,
"Unsupported hash type");
231 return EVP_PKEY_verify(ctx_.get(), signature.as<
unsigned char>(), signature.size(), hash.as_uint8(),
241 [[nodiscard]]
bool verify_data(
const ByteView data,
const ByteView signature)
const
243 const Hash hash = SHA::ComputeHash(data, hash_type_);
244 return verify_hash(hash, signature);
248 EVP_PKEY_CTX_WRAPPER ctx_ =
nullptr;
249 EVP_PKEY_WRAPPER pkey_ =
nullptr;
250 const Hash::HashType hash_type_;
256 [[deprecated]] [[nodiscard]]
inline KeyPair generate_key_pair(std::string curve_name)
258 KeyPairGenerator instance(curve_name);
259 return instance.generate();
266 [[deprecated]] [[nodiscard]]
inline ByteArray sign_data(
const KeyView private_key,
const ByteView data,
267 const Hash::HashType hash_type)
269 Signer instance(private_key, hash_type);
270 return instance.sign_data(data);
277 [[deprecated]] [[nodiscard]]
inline ByteArray sign_hash(
const KeyView private_key,
const Hash hash)
279 Signer instance(private_key, hash.hash_type);
280 return instance.sign_hash(hash);
287 [[deprecated]] [[nodiscard]]
inline bool verify_data(
const KeyView public_key,
const ByteView data,
288 const ByteView signature,
const Hash::HashType hash_type)
290 Verifier instance(public_key, hash_type);
291 return instance.verify_data(data, signature);
298 [[deprecated]] [[nodiscard]]
inline bool verify_hash(
const KeyView public_key,
const Hash hash,
299 const ByteView signature)
301 Verifier instance(public_key, hash.hash_type);
302 return instance.verify_hash(hash, signature);
Represents a cryptographic hash value along with its type.