Homework 1: Building Quantum-Resistant Signatures for XRPL

← Back to Protocol Extensions and Quantum Signatures


Objective

Implement post-quantum (Dilithium-2) signature support in Rippled as an amendment and extend the protocol to allow accounts to opt into quantum-resistant signing and register quantum keys.

Format: Repository + written report (PDF or Markdown) with commands, screenshots, code snippets.

Reference Commit: bc8f0c2e13002887d57e69e27eafd0f11260bac2


Task

Complete all implementation steps (build integration, amendment creation, key type extension, account flag, ledger entry, new transaction type, tests) and document the process.


Requirements

1. Build System Integration (Dilithium Library)

  • Create cmake/deps/dilithium.cmake to fetch/build Dilithium-2 (randomized signing + AES support).

  • Provide imported targets: NIH::dilithium2_ref, NIH::dilithium2aes_ref, NIH::fips202_ref.

  • Add include(deps/dilithium) to CMakeLists.txt.

  • Link NIH::dilithium2_ref in cmake/RippledCore.cmake.

  • Clean and rebuild:

cd .. && rm -r build
eval "$(pyenv init -)" && \
mkdir -p build && cd build && \
conan install .. --output-folder . --build --settings build_type=Debug && \
cmake -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake \
  -DCMAKE_CXX_FLAGS=-DBOOST_ASIO_HAS_STD_INVOKE_RESULT \
  -DCMAKE_BUILD_TYPE=Debug \
  -DUNIT_TEST_REFERENCE_FEE=200 \
  -Dtests=TRUE \
  -Dxrpld=TRUE \
  -Dstatic=OFF \
  -Dassert=TRUE \
  -Dwerr=TRUE ..
cmake --build . --target rippled --parallel 10

2. Amendment Feature

  • Add to features.macro:

XRPL_FEATURE(Quantum, Supported::yes, VoteBehavior::DefaultNo)

3. Key Type & Cryptographic Classes

  • Add dilithium = 2 to KeyType.h; update keyTypeFromString() and to_string().

  • PublicKey:

    • Expand buffer to 1312 bytes (Dilithium public key size).

    • Implement size tracking and detection in publicKeyType().

    • Add Dilithium verify logic in PublicKey.cpp.

  • SecretKey:

    • Expand to 2528 bytes (Dilithium secret key size).

    • Implement generator, signing support.

  • Implement Dilithium generation in randomSecretKey(KeyType type).

  • Update Base58 handling in tokens.cpp (remove size limits blocking large keys).

4. Force Quantum Account Flag

  • Add lsfForceQuantum = 0x02000000 to LedgerFormats.h.

  • Add asfForceQuantum = 11 to TxFlags.h.

  • Update SetAccount.cpp for setting/clearing the flag.

  • In Transactor.cpp::checkSign():

    • If lsfForceQuantum set, reject non-Dilithium signatures.

5. Initial Tests

  • Create src/test/app/MyTests_test.cpp covering:

    • Key generation

    • Dilithium signature verification

    • Payment signed with Dilithium

    • ForceQuantum flag behavior

6. Test Execution

cmake --build . --target rippled --parallel 10 && ./rippled -u ripple.app.MyTests

7. Quantum Key Ledger Entry

  • Add QUANTUM_KEY = 'Q' to LedgerNameSpace.

  • In ledger_entries.macro:

LEDGER_ENTRY(ltQUANTUM_KEY, 0x0071, QuantumKey, quantumKey, ({
  {sfAccount,              soeREQUIRED},
  {sfQuantumPublicKey,     soeREQUIRED},
  {sfPreviousTxnID,        soeREQUIRED},
  {sfPreviousTxnLgrSeq,    soeREQUIRED},
  {sfOwnerNode,            soeREQUIRED},
}))
  • Add field in sfields.macro:

TYPED_SFIELD(sfQuantumPublicKey, VL, 19)
  • Keylet helper (Indexes.cpp + header):

Keylet
quantum(AccountID const& account, Slice const& quantumPublicKey) noexcept
{
    return {
      ltQUANTUM_KEY,
      indexHash(
        LedgerNameSpace::QUANTUM_KEY,
        account,
        quantumPublicKey)
    };
}

8. SetQuantumKey Transaction

  • Add to transactions.macro:

TRANSACTION(ttSET_QUANTUM_KEY, 25, SetQuantumKey, Delegation::notDelegatable, ({
  {sfQuantumPublicKey, soeREQUIRED},
}))
  • Implement SetQuantumKey.h/.cpp:

// SetQuantumKey.cpp (skeleton)
NotTEC
SetQuantumKey::preflight(PreflightContext const& ctx)
{
    if (!ctx.rules.enabled(featureQuantum))
        return temDISABLED;
    if (auto ret = preflight1(ctx); !isTesSuccess(ret))
        return ret;
    // Validate Dilithium public key format/size
    return preflight2(ctx);
}

TER
SetQuantumKey::preclaim(PreclaimContext const& ctx)
{
    // Check existence (keylet::quantum)
    return tesSUCCESS;
}

TER
SetQuantumKey::doApply()
{
    // Create ledger entry (ltQUANTUM_KEY) with sfQuantumPublicKey
    return tesSUCCESS;
}

9. Signature Path Validation

  • In Transactor.cpp::checkSign():

    • If Dilithium signature present:

      • Lookup quantum key ledger entry via keylet::quantum.

      • Ensure stored key matches signing key.

10. Extended Testing

  • Unit tests:

    • Quantum key index generation

    • Keylet lookup

    • Error cases (duplicate registration, invalid size)

  • Integration tests:

    • Register quantum key (SetQuantumKey)

    • Set ForceQuantum and submit non-Dilithium (expect failure)

    • Submit Dilithium-signed Payment (expect success)

    • Rotate quantum key (optional)

    • Disable amendment (temDISABLED behavior)


Deliverables

Include in the report:

  1. Build System

    • Added CMake module snippet

    • Commands used (copy/paste)

    • Screenshot of successful build linking Dilithium

  2. Amendment & Protocol

    • Feature declaration

    • KeyType + class changes summary

  3. Ledger & Transactions

    • Quantum key ledger entry definition

    • SetQuantumKey transaction workflow

  4. Code Snippets

    • PublicKey/SecretKey modifications

    • checkSign() Dilithium branch

  5. Tests

    • Test file paths

    • Output from ./rippled -u ripple.app.MyTests

  6. Validation

    • Sample Dilithium key pair sizes

    • Example SetQuantumKey transaction JSON

    • Example Payment signed with Dilithium

  7. Issues & Resolutions

    • Any build or runtime errors and fixes


Helpful Checks

  • Public key size: 1312 bytes (Dilithium-2)

  • Secret key size: 2528 bytes

  • Signature size (verify expected range for Dilithium-2)

  • Amendment must be enabled (featureQuantum) for SetQuantumKey to succeed.


Resources

Last updated