-
Notifications
You must be signed in to change notification settings - Fork 2
[ALPHANET] Quantum #27
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
base: develop
Are you sure you want to change the base?
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 |
|---|---|---|
|
|
@@ -67,6 +67,7 @@ target_link_libraries( | |
| Xrpl::opts | ||
| Xrpl::syslibs | ||
| secp256k1::secp256k1 | ||
| NIH::dilithium2_ref | ||
|
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. The Dilithium library is compiled with Suggested fixIn |
||
| xrpl.libpb | ||
| xxHash::xxhash | ||
| $<$<BOOL:${voidstar}>:antithesis-sdk-cpp> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| include(FetchContent) | ||
|
|
||
| ExternalProject_Add( | ||
| dilithium_src | ||
| PREFIX ${nih_cache_path} | ||
|
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. The file opens with Suggested fixDefine nih_cache_path before this file is included — e.g., set(nih_cache_path "${CMAKE_BINARY_DIR}/nih_c") in CMakeLists.txt following the pattern used by upstream rippled for other external dependencies, or replace the reference with a concrete path variable that actually exists in the build graph. |
||
| # Pin to an explicit commit, not a moving branch ref. Bumping this SHA | ||
| # is a supply-chain decision that must be reviewed; never revert to a | ||
| # branch tag here. Upstream: | ||
| # https://github.com/Transia-RnD/dilithium/commit/3032292cfd4d94e0df9bd49a0098669ca9166aa1 | ||
| GIT_REPOSITORY https://github.com/Transia-RnD/dilithium.git | ||
| GIT_TAG 3032292cfd4d94e0df9bd49a0098669ca9166aa1 | ||
| GIT_SHALLOW FALSE | ||
| CONFIGURE_COMMAND "" | ||
| LOG_BUILD ON | ||
| BUILD_IN_SOURCE 0 | ||
| BUILD_COMMAND | ||
| COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/ref <BINARY_DIR>/ref | ||
| COMMAND make -C <BINARY_DIR>/ref clean | ||
| COMMAND /bin/sh -c "CFLAGS='-DDILITHIUM_MODE=2 -DDILITHIUM_RANDOMIZED_SIGNING' make -C <BINARY_DIR>/ref libdilithium2_ref.a libfips202_ref.a" | ||
|
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. The BUILD_COMMAND assigns CFLAGS via Suggested fixChange the CFLAGS assignment to |
||
| INSTALL_COMMAND "" | ||
| BUILD_BYPRODUCTS | ||
| <BINARY_DIR>/ref/libdilithium2_ref.a | ||
|
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. The build step wraps Suggested fixEliminate the /bin/sh -c wrapper. Use: BUILD_COMMAND COMMAND ${CMAKE_COMMAND} -E env "CFLAGS=-DDILITHIUM_MODE=2 -DDILITHIUM_RANDOMIZED_SIGNING" make -C <BINARY_DIR>/ref clean COMMAND ${CMAKE_COMMAND} -E env "CFLAGS=-DDILITHIUM_MODE=2 -DDILITHIUM_RANDOMIZED_SIGNING" make -C <BINARY_DIR>/ref libdilithium2_ref.a libfips202_ref.a. This passes arguments directly to the build tool without shell interpolation. |
||
| <BINARY_DIR>/ref/libfips202_ref.a | ||
| ) | ||
|
|
||
| ExternalProject_Get_Property(dilithium_src SOURCE_DIR BINARY_DIR) | ||
| set(dilithium_src_SOURCE_DIR "${SOURCE_DIR}") | ||
| set(dilithium_src_BINARY_DIR "${BINARY_DIR}") | ||
|
|
||
| # Include the reference implementation headers from source | ||
| include_directories("${dilithium_src_SOURCE_DIR}/ref") | ||
|
|
||
| # Create imported targets for each static library using BINARY_DIR | ||
| add_library(dilithium::dilithium2_ref STATIC IMPORTED GLOBAL) | ||
| set_target_properties(dilithium::dilithium2_ref PROPERTIES | ||
| IMPORTED_LOCATION "${dilithium_src_BINARY_DIR}/ref/libdilithium2_ref.a" | ||
| INTERFACE_INCLUDE_DIRECTORIES "${dilithium_src_SOURCE_DIR}/ref/" | ||
| ) | ||
|
|
||
| add_library(dilithium::libfips202_ref STATIC IMPORTED GLOBAL) | ||
| set_target_properties(dilithium::libfips202_ref PROPERTIES | ||
| IMPORTED_LOCATION "${dilithium_src_BINARY_DIR}/ref/libfips202_ref.a" | ||
| INTERFACE_INCLUDE_DIRECTORIES "${dilithium_src_SOURCE_DIR}/ref/" | ||
| ) | ||
|
|
||
| # Add dependencies to ensure the external project is built first | ||
| add_dependencies(dilithium::dilithium2_ref dilithium_src) | ||
| add_dependencies(dilithium::libfips202_ref dilithium_src) | ||
|
|
||
| # Note: We do NOT link the Dilithium library's randombytes.c because we provide | ||
|
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. The comment asserting that Suggested fixAdd a post-build ar command to strip the symbol from the archive: COMMAND ${CMAKE_AR} d <BINARY_DIR>/ref/libdilithium2_ref.a randombytes.o. Alternatively, apply a PATCH_COMMAND that edits the upstream Makefile to exclude randombytes.c from SOURCES before compilation. In either case, add a CI step that runs |
||
| # our own thread-safe implementation in src/libxrpl/protocol/SecretKey.cpp | ||
| # that uses xrpld's crypto_prng() instead of direct /dev/urandom access. | ||
|
|
||
| # Create an interface library that links to the Dilithium libraries | ||
| # Note: Link order matters - libraries that provide symbols must come AFTER libraries that use them | ||
| target_link_libraries(xrpl_libs INTERFACE | ||
| dilithium::dilithium2_ref | ||
| dilithium::libfips202_ref | ||
| ) | ||
|
|
||
| # Create alias for convenience | ||
| add_library(NIH::dilithium2_ref ALIAS dilithium::dilithium2_ref) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ namespace xrpl { | |
| enum class KeyType { | ||
| Secp256k1 = 0, | ||
| Ed25519 = 1, | ||
| Dilithium = 2, | ||
|
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. The Suggested fixWire every Dilithium acceptance point to |
||
| }; | ||
|
|
||
| inline std::optional<KeyType> | ||
|
|
@@ -19,6 +20,9 @@ keyTypeFromString(std::string const& s) | |
| if (s == "ed25519") | ||
| return KeyType::Ed25519; | ||
|
|
||
| if (s == "dilithium") | ||
|
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. Adding 'dilithium' as a parseable key_type string creates a remote process-termination vulnerability. Suggested fixDo not add 'dilithium' to |
||
| return KeyType::Dilithium; | ||
|
|
||
| return {}; | ||
| } | ||
|
|
||
|
|
@@ -31,6 +35,9 @@ to_string(KeyType type) | |
| if (type == KeyType::Ed25519) | ||
| return "ed25519"; | ||
|
|
||
| if (type == KeyType::Dilithium) | ||
| return "dilithium"; | ||
|
|
||
| return "INVALID"; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,10 +35,11 @@ namespace xrpl { | |
| information needed to determine the cryptosystem | ||
| parameters used is stored inside the key. | ||
|
|
||
| As of this writing two systems are supported: | ||
| As of this writing three systems are supported: | ||
|
|
||
| secp256k1 | ||
| ed25519 | ||
| dilithium | ||
|
|
||
| secp256k1 public keys consist of a 33 byte | ||
| compressed public key, with the lead byte equal | ||
|
|
@@ -47,14 +48,18 @@ namespace xrpl { | |
| The ed25519 public keys consist of a 1 byte | ||
| prefix constant 0xED, followed by 32 bytes of | ||
| public key data. | ||
|
|
||
| The dilithium public keys will have their own specific format. | ||
| */ | ||
| class PublicKey | ||
| { | ||
| protected: | ||
| // All the constructed public keys are valid, non-empty and contain 33 | ||
| // bytes of data. | ||
| // Minimum / standard public key size (secp256k1, ed25519). | ||
| static constexpr std::size_t kSize = 33; | ||
| std::uint8_t buf_[kSize]{}; // should be large enough | ||
| // Buffer sized for the largest supported key (dilithium = 1312 bytes). | ||
| // Actual length is tracked in size_. | ||
| std::uint8_t buf_[1312]{}; | ||
|
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. The constructor lower-bounds Suggested fixIn PublicKey.cpp, add |
||
| std::size_t size_ = 0; | ||
|
|
||
| public: | ||
| using const_iterator = std::uint8_t const*; | ||
|
|
@@ -79,10 +84,10 @@ class PublicKey | |
| return buf_; | ||
| } | ||
|
|
||
| static std::size_t | ||
| size() noexcept | ||
| [[nodiscard]] std::size_t | ||
| size() const noexcept | ||
| { | ||
| return kSize; | ||
| return size_; | ||
| } | ||
|
|
||
| [[nodiscard]] const_iterator | ||
|
|
@@ -100,19 +105,19 @@ class PublicKey | |
| [[nodiscard]] const_iterator | ||
| end() const noexcept | ||
| { | ||
| return buf_ + kSize; | ||
| return buf_ + size_; | ||
| } | ||
|
|
||
| [[nodiscard]] const_iterator | ||
| cend() const noexcept | ||
| { | ||
| return buf_ + kSize; | ||
| return buf_ + size_; | ||
| } | ||
|
|
||
| [[nodiscard]] Slice | ||
| slice() const noexcept | ||
| { | ||
| return {buf_, kSize}; | ||
| return {buf_, size_}; | ||
| } | ||
|
|
||
| operator Slice() const noexcept | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -166,7 +166,13 @@ STValidation::STValidation(SerialIter& sit, LookupNodeID&& lookupNodeID, bool ch | |
| , signingPubKey_([this]() { | ||
|
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. The diff comment explicitly describes this as a 'pre-amendment / post-amendment' change, yet the Suggested fixEither (a) generate the |
||
| auto const spk = getFieldVL(sfSigningPubKey); | ||
|
|
||
| if (publicKeyType(makeSlice(spk)) != KeyType::Secp256k1) | ||
| // Validations are signed with either the legacy secp256k1 key | ||
| // (pre-amendment) or the new dilithium key (post-amendment). Mixed | ||
| // sets are expected during the rolling upgrade. Ed25519 has never | ||
| // been valid for validations and is still rejected. verifyDigest() | ||
| // dispatches per keytype. | ||
| auto const kt = publicKeyType(makeSlice(spk)); | ||
|
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. The comment added here explicitly frames Dilithium acceptance as a post-amendment behavior during a rolling upgrade, but Suggested fixGate Dilithium validation acceptance on |
||
| if (kt != KeyType::Secp256k1 && kt != KeyType::Dilithium) | ||
| Throw<std::runtime_error>("Invalid public key in validation"); | ||
|
|
||
| return PublicKey{makeSlice(spk)}; | ||
|
|
@@ -208,9 +214,12 @@ STValidation::STValidation( | |
| "xrpl::STValidation::STValidation(PublicKey, SecretKey) : nonzero " | ||
| "node"); | ||
|
|
||
| // First, set our own public key: | ||
| if (publicKeyType(pk) != KeyType::Secp256k1) | ||
| logicError("We can only use secp256k1 keys for signing validations"); | ||
| // First, set our own public key. Only secp256k1 (legacy) and dilithium | ||
| // (post-quantum) are valid for signing validations; Ed25519 has never | ||
| // been supported here. | ||
| if (auto const kt = publicKeyType(pk); | ||
| kt != KeyType::Secp256k1 && kt != KeyType::Dilithium) | ||
| logicError("Validation signing requires secp256k1 or dilithium key"); | ||
|
|
||
| setFieldVL(sfSigningPubKey, pk.slice()); | ||
| setFieldU32(sfSigningTime, signTime.time_since_epoch().count()); | ||
|
|
||
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.
The dilithium library is fetched from
https://github.com/Transia-RnD/dilithium.git, a private Transia-RnD fork of the NIST reference implementation, with no content integrity verification — noURL_HASH SHA256or equivalent. Only a git commit SHA pins the dependency, which provides no protection if the fork repository is force-pushed, if the GitHub account is compromised, or if the CI environment DNS-spoofs the host. This library is linked unconditionally intoxrpl_libs, making it a hard dependency of every rippled node's post-quantum key generation and signing path — a supply-chain compromise silently backdoors all Dilithium validator key material across every build. Replace theGIT_REPOSITORYfetch with aURLpointing to a pinned release tarball from the upstreampq-crystals/dilithiumreference repository, combined withURL_HASH SHA256=<hash>verification, or vendor the code as a reviewed git submodule.Suggested fix
Use FetchContent or ExternalProject_Add with a pinned tarball URL from the upstream pq-crystals/dilithium official repository and a
URL_HASH SHA256=...computed out-of-band against that specific release. Alternatively, vendor the code as a git submodule with the commit pinned in .gitmodules so every clone has an auditable history. Add a post-build KAT step to verify the compiled artifact produces correct known-answer test outputs before linking it into xrpl_libs.