From 92c6dc1c1d8e656d316c63af995464a7bfe8bd26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Meusel?= Date: Thu, 18 Jul 2024 09:47:22 +0200 Subject: [PATCH] Doc: examples how to load raw ECC keys This does come up as usage questions occasionally (#3137, #4224) --- src/examples/ecc_raw_private_key.cpp | 27 +++++++++++++++++++++++ src/examples/ecc_raw_public_key.cpp | 32 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/examples/ecc_raw_private_key.cpp create mode 100644 src/examples/ecc_raw_public_key.cpp diff --git a/src/examples/ecc_raw_private_key.cpp b/src/examples/ecc_raw_private_key.cpp new file mode 100644 index 00000000000..a3961ee75cf --- /dev/null +++ b/src/examples/ecc_raw_private_key.cpp @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +int main() { + const std::string curve_name = "secp256r1"; + const auto private_scalar_bytes = + Botan::hex_decode("D2AC61C35CAEE918E47B0BD5E61DA9B3A5C2964AB317647DEF6DFC042A06C829"); + + Botan::Null_RNG null_rng; + const auto domain = Botan::EC_Group::from_name(curve_name); + const auto private_scalar = Botan::BigInt(private_scalar_bytes); + + // This loads the private scalar into an ECDH_PrivateKey. Creating an + // ECDSA_PrivateKey would work the same way. + const auto private_key = Botan::ECDH_PrivateKey(null_rng, domain, private_scalar); + const auto public_key = private_key.public_key(); + + std::cout << "Private Key (PEM):\n\n" << Botan::PKCS8::PEM_encode(private_key) << '\n'; + std::cout << "Public Key (PEM):\n\n" << Botan::X509::PEM_encode(*public_key) << '\n'; +} diff --git a/src/examples/ecc_raw_public_key.cpp b/src/examples/ecc_raw_public_key.cpp new file mode 100644 index 00000000000..a3d8b63bd17 --- /dev/null +++ b/src/examples/ecc_raw_public_key.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +#include +#include +#include +#include + +std::vector to_uncompress_point_encoding(std::span x, std::span y) { + std::vector public_key_bytes; + public_key_bytes.reserve(x.size() + y.size() + 1); + public_key_bytes.push_back(0x04); // means: uncompressed point encoding + public_key_bytes.insert(public_key_bytes.end(), x.begin(), x.end()); + public_key_bytes.insert(public_key_bytes.end(), y.begin(), y.end()); + return public_key_bytes; +} + +int main() { + const std::string curve_name = "secp256r1"; + const auto public_x_bytes = Botan::hex_decode("278309D4A88ADF89CA0E5328D3B655CF8949F2D9F9B2308AA22FE28202A315EC"); + const auto public_y_bytes = Botan::hex_decode("AC457F18D1F3675D46E98ED2E509EE47AC2CB9A012F73263B30CD7248AEA6020"); + + const auto domain = Botan::EC_Group::from_name(curve_name); + const auto encoded_public_point = to_uncompress_point_encoding(public_x_bytes, public_y_bytes); + + // This loads the public point into an ECDSA_PublicKey. Creating an + // ECDH_PublicKey would work the same way. + const auto public_key = Botan::ECDSA_PublicKey(domain, domain.OS2ECP(encoded_public_point)); + + std::cout << "Public Key (PEM):\n\n" << Botan::X509::PEM_encode(public_key) << '\n'; +}