From 27b4bae78b79fe1148a450f38f01997c62e469a8 Mon Sep 17 00:00:00 2001 From: devgianlu Date: Sat, 21 Dec 2024 14:43:45 +0100 Subject: [PATCH] LibCrypto: Implement Ed448 Implement the Ed448 curve for signing and verifying using OpenSSL. The methods could be all made static, but all other curves are not. I think this is material for further refactoring. --- Libraries/LibCrypto/CMakeLists.txt | 1 + Libraries/LibCrypto/Curves/Ed448.cpp | 82 ++++++++++++++++++++++++++++ Libraries/LibCrypto/Curves/Ed448.h | 24 ++++++++ 3 files changed, 107 insertions(+) create mode 100644 Libraries/LibCrypto/Curves/Ed448.cpp create mode 100644 Libraries/LibCrypto/Curves/Ed448.h diff --git a/Libraries/LibCrypto/CMakeLists.txt b/Libraries/LibCrypto/CMakeLists.txt index 45e6a9951ee..32cf50e427f 100644 --- a/Libraries/LibCrypto/CMakeLists.txt +++ b/Libraries/LibCrypto/CMakeLists.txt @@ -26,6 +26,7 @@ set(SOURCES Cipher/ChaCha20.cpp Curves/Curve25519.cpp Curves/Ed25519.cpp + Curves/Ed448.cpp Curves/X25519.cpp Curves/X448.cpp NumberTheory/ModularFunctions.cpp diff --git a/Libraries/LibCrypto/Curves/Ed448.cpp b/Libraries/LibCrypto/Curves/Ed448.cpp new file mode 100644 index 00000000000..1129bf5cff6 --- /dev/null +++ b/Libraries/LibCrypto/Curves/Ed448.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024, Altomani Gianluca + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +#include +#include + +namespace Crypto::Curves { + +ErrorOr Ed448::generate_private_key() +{ + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_Q_keygen(nullptr, nullptr, "ED448"))); + + size_t key_size = EVP_PKEY_get_size(key.ptr()); + auto buf = TRY(ByteBuffer::create_uninitialized(key_size)); + + OPENSSL_TRY(EVP_PKEY_get_raw_private_key(key.ptr(), buf.data(), &key_size)); + + return buf.slice(0, key_size); +} + +ErrorOr Ed448::generate_public_key(ReadonlyBytes private_key) +{ + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED448, nullptr, private_key.data(), private_key.size()))); + + size_t key_size = EVP_PKEY_get_size(key.ptr()); + auto buf = TRY(ByteBuffer::create_uninitialized(key_size)); + + OPENSSL_TRY(EVP_PKEY_get_raw_public_key(key.ptr(), buf.data(), &key_size)); + + return buf.slice(0, key_size); +} + +ErrorOr Ed448::sign(ReadonlyBytes private_key, ReadonlyBytes message, ReadonlyBytes context) +{ + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_private_key_ex(nullptr, "ED448", nullptr, private_key.data(), private_key.size()))); + + auto ctx = TRY(OpenSSL_MD_CTX::create()); + + OSSL_PARAM params[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, const_cast(context.data()), context.size()), + OSSL_PARAM_END + }; + + OPENSSL_TRY(EVP_DigestSignInit_ex(ctx.ptr(), nullptr, nullptr, nullptr, nullptr, key.ptr(), params)); + + size_t sig_len = signature_size(); + auto sig = TRY(ByteBuffer::create_uninitialized(sig_len)); + + OPENSSL_TRY(EVP_DigestSign(ctx.ptr(), sig.data(), &sig_len, message.data(), message.size())); + + return sig.slice(0, sig_len); +} + +ErrorOr Ed448::verify(ReadonlyBytes public_key, ReadonlyBytes signature, ReadonlyBytes message, ReadonlyBytes context) +{ + auto key = TRY(OpenSSL_PKEY::wrap(EVP_PKEY_new_raw_public_key_ex(nullptr, "ED448", nullptr, public_key.data(), public_key.size()))); + + auto ctx = TRY(OpenSSL_MD_CTX::create()); + + OSSL_PARAM params[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, const_cast(context.data()), context.size()), + OSSL_PARAM_END + }; + + OPENSSL_TRY(EVP_DigestVerifyInit_ex(ctx.ptr(), nullptr, nullptr, nullptr, nullptr, key.ptr(), params)); + + auto res = EVP_DigestVerify(ctx.ptr(), signature.data(), signature.size(), message.data(), message.size()); + if (res == 1) + return true; + if (res == 0) + return false; + OPENSSL_TRY(res); + VERIFY_NOT_REACHED(); +} +} diff --git a/Libraries/LibCrypto/Curves/Ed448.h b/Libraries/LibCrypto/Curves/Ed448.h new file mode 100644 index 00000000000..bba9a0456d9 --- /dev/null +++ b/Libraries/LibCrypto/Curves/Ed448.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024, Altomani Gianluca + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Crypto::Curves { + +class Ed448 { +public: + constexpr size_t key_size() const { return 57; } + constexpr size_t signature_size() const { return 114; } + ErrorOr generate_private_key(); + ErrorOr generate_public_key(ReadonlyBytes private_key); + + ErrorOr sign(ReadonlyBytes private_key, ReadonlyBytes message, ReadonlyBytes context = {}); + ErrorOr verify(ReadonlyBytes public_key, ReadonlyBytes signature, ReadonlyBytes message, ReadonlyBytes context = {}); +}; + +}