Skip to content

Falcon: seeded keygen and cross-platform stability? #2305

Description

@Federico2014

Hi BC team — a couple of questions on the Falcon implementation in org.bouncycastle.pqc.crypto.falcon (relevant to wallet / HD-key derivation and blockchain consensus use cases). Apologies if any of this is already documented somewhere I missed.

Context

We're evaluating Falcon-512 for a blockchain protocol's post-quantum signature path. Two invariants we need to hold:

  1. Wallet side — keys derived from a user-controlled seed (e.g. BIP-39 mnemonic) must produce the same public key / address on every platform the user might restore their wallet on. Same seed, same account, everywhere.
  2. Consensus side — every full node must reach the same verify result (accept/reject) for the same (publicKey, message, signature) regardless of the host platform. A single divergence would split consensus.

The matrix we care about

Keygen needs to be deterministic and bit-identical across this matrix when driven from the same seed. Signing is randomized in Falcon, so repeated signatures are not expected to be byte-identical; the signing and verification paths still need to be cross-platform stable and interoperable across this matrix:

Dimension Examples
OS Linux, macOS, Windows, Android, iOS
CPU architecture x86_64, ARM64, 32-bit ARM
JDK / runtime OpenJDK 8 / 11 / 17 / 21, GraalVM native-image, Android Runtime (ART), restricted JVMs on hardware wallets
JIT / execution mode C1, C2, interpreter-only, AOT

Background: Falcon's reference implementation has two code paths — a native floating-point path (fast, but double arithmetic can drift across FPUs, JIT optimization levels, strictfp settings, and JDK versions) and an emulated floating-point path (software-emulated IEEE 754 over integers, slower but bit-identical across platforms; provided in the upstream Falcon reference at falcon-sign.info and inherited by PQClean). The choice of path is the main determinism risk.

Questions

1. Seed-based deterministic keygen

Does FalconKeyPairGenerator support deterministic keygen from a caller-supplied seed (e.g. by passing a SecureRandom backed by a fixed seed via FalconKeyGenerationParameters)? Concretely: given the same input seed bytes, will two invocations of generateKeyPair() produce the same (publicKey, privateKey) byte-for-byte?

If yes, are there any caveats (JDK version, JVM flags, internal use of ThreadLocalRandom / System.nanoTime / non-seeded sources) that could break determinism?

2. Keygen determinism across the matrix

Assuming question 1 is yes — does FalconKeyPairGenerator produce bit-identical keypairs from the same seed across every cell of the matrix above?

  • Which keygen code path does BC use today — native FP or emulated FP?
  • If native FP: has anyone tested the matrix for keygen determinism, or is drift known to occur?
  • If determinism is not currently guaranteed, would the BC project be open to offering an emulated-FP keygen mode (e.g. opt-in via FalconParameters) so wallets and the protocol can rely on same-seed → same-key?

3. Signing correctness and cross-platform stability

Falcon signing is randomized, so we do not require repeated signing of the same message with the same private key to produce identical signature bytes.

  • Does FalconSigner use floating-point at sign time?
  • Are signatures generated on every supported platform guaranteed to verify correctly on every other supported platform?
  • Are there any known platform-dependent floating-point behaviors in signing that can cause invalid signatures or interoperability failures?

4. Verification determinism across the matrix

  • Does FalconSigner.verifySignature use floating-point at verify time? Even if verify is "just" accept/reject, any FP-dependent intermediate computation could in principle drift across platforms and cause a single full-node to disagree.
  • Are there tests in BC that exercise verify with fixed (publicKey, message, signature) vectors and confirm identical accept/reject across the matrix above?

Why this matters

Concrete failure modes we're trying to rule out:

  • Wallet portability break — a user's seed derives one Falcon pubkey on a desktop wallet (server-class JDK on x86_64 Linux) and a different pubkey on a mobile wallet (ART on ARM64 Android) or hardware wallet (restricted JVM on 32-bit ARM). Seed backup is no longer portable. Wallet recovery is broken.
  • Consensus split — two full nodes verifying the same signature reach different accept/reject results, forking the chain.
  • Signer interoperability break — a signature produced by a signer on one supported platform fails to verify on another platform because signing-side platform behavior produces an invalid or non-portable signature.

If BC already guarantees matrix-stable keygen and cross-platform sign / verify interoperability, great — happy to be pointed at the API surface and test coverage. If not, we'd like to discuss whether an emulated-FP path is something the BC project would be open to upstreaming, ideally toggleable so existing perf-sensitive users aren't affected.

Thanks for the work on PQ algorithms in BC — this is one of the few mature Java implementations available.

Metadata

Metadata

Assignees

Labels

support requestCommunity assistance requested

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions