-
-
Notifications
You must be signed in to change notification settings - Fork 16
Add EC private key generation #2670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,12 +8,15 @@ | |
| #include "crypto_helpers.h" | ||
| #include "crypto_other.h" | ||
| #include "crypto_pkcs8.h" | ||
| #include "crypto_random.h" | ||
|
|
||
| #include <array> // std::array | ||
| #include <cassert> // assert | ||
| #include <cstddef> // std::size_t | ||
| #include <cstdint> // std::uint8_t, std::uint32_t | ||
| #include <exception> // std::exception | ||
| #include <optional> // std::optional, std::nullopt | ||
| #include <span> // std::span | ||
| #include <string> // std::string | ||
| #include <string_view> // std::string_view | ||
| #include <utility> // std::move, std::unreachable | ||
|
|
@@ -603,6 +606,48 @@ auto make_ec_private_key(const EllipticCurve curve, | |
| .coordinate_y = expected.second}}; | ||
| } | ||
|
|
||
| auto generate_ec_private_key(const EllipticCurve curve) | ||
| -> std::optional<PrivateKey> { | ||
| const auto parameters{to_curve_parameters(curve)}; | ||
| const auto order_bits{bignum_bit_length(parameters.order)}; | ||
| const auto width{curve_field_bytes(curve)}; | ||
| const auto excess_bits{(width * 8u) - order_bits}; | ||
|
|
||
| // Rejection sampling into [1, order). Masking the surplus high bits keeps the | ||
| // retry rate low even for P-521, whose order fills only 521 of its 528 bits | ||
| std::string scalar(width, '\x00'); | ||
| const SecureStringScope scalar_scope{scalar}; | ||
| Bignum scalar_number; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Severity: medium 🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
cubic-dev-ai[bot] marked this conversation as resolved.
|
||
| const SecureBignumScope scalar_number_scope{scalar_number}; | ||
| do { | ||
| try { | ||
| fill_random_bytes(std::span<std::uint8_t>{ | ||
| reinterpret_cast<std::uint8_t *>(scalar.data()), width}); | ||
| } catch (const std::exception &) { | ||
| return std::nullopt; | ||
| } | ||
|
|
||
| scalar[0] = | ||
| static_cast<char>(static_cast<std::uint8_t>(scalar[0]) & | ||
| static_cast<std::uint8_t>(0xffu >> excess_bits)); | ||
| scalar_number = bignum_from_bytes(scalar); | ||
| } while (bignum_is_zero(scalar_number) || | ||
| bignum_compare(scalar_number, parameters.order) >= 0); | ||
|
|
||
| const auto point{ec_public_from_scalar(curve, scalar)}; | ||
| return PrivateKey{ | ||
| new PrivateKey::Internal{.kind = PrivateKey::Type::EllipticCurve, | ||
| .modulus = {}, | ||
| .public_exponent = {}, | ||
| .private_exponent = {}, | ||
| .scalar = scalar, | ||
| .elliptic_curve = curve, | ||
| .edwards_seed = {}, | ||
| .edwards_curve = {}, | ||
| .coordinate_x = point.first, | ||
| .coordinate_y = point.second}}; | ||
| } | ||
|
|
||
| auto make_edwards_private_key(const EdwardsCurve curve, | ||
| const std::string_view seed) | ||
| -> std::optional<PrivateKey> { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -432,6 +432,35 @@ auto make_ec_private_key(const EllipticCurve curve, | |
| .edwards_curve = {}}}; | ||
| } | ||
|
|
||
| auto generate_ec_private_key(const EllipticCurve curve) | ||
| -> std::optional<PrivateKey> { | ||
| BCRYPT_ALG_HANDLE algorithm{nullptr}; | ||
| if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider( | ||
| &algorithm, to_ecdsa_algorithm(curve), nullptr, 0))) { | ||
| return std::nullopt; | ||
| } | ||
|
|
||
| BCRYPT_KEY_HANDLE key{nullptr}; | ||
| if (!BCRYPT_SUCCESS(BCryptGenerateKeyPair( | ||
| algorithm, &key, static_cast<ULONG>(curve_bit_length(curve)), 0)) || | ||
| !BCRYPT_SUCCESS(BCryptFinalizeKeyPair(key, 0))) { | ||
| if (key != nullptr) { | ||
| BCryptDestroyKey(key); | ||
| } | ||
|
|
||
| BCryptCloseAlgorithmProvider(algorithm, 0); | ||
| return std::nullopt; | ||
| } | ||
|
|
||
| return PrivateKey{ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If Severity: low Other Locations
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage. |
||
| new PrivateKey::Internal{.kind = PrivateKey::Type::EllipticCurve, | ||
| .algorithm = algorithm, | ||
| .key = key, | ||
| .field_bytes = curve_field_bytes(curve), | ||
| .edwards_seed = {}, | ||
| .edwards_curve = {}}}; | ||
| } | ||
|
|
||
| auto make_edwards_private_key(const EdwardsCurve curve, | ||
| const std::string_view seed) | ||
| -> std::optional<PrivateKey> { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: If
new PrivateKey::Internal{...}throws (e.g.,std::bad_alloc), thealgorithmandkeyhandles have not yet been transferred into thePrivateKeydestructor's ownership, so both platform handles will leak. Consider using aunique_ptrwith a custom deleter or a local RAII guard to ensure cleanup on all exit paths. The same pattern also applies in the Apple and OpenSSL backends.Prompt for AI agents