Skip to main content
Version: Next (unstable)

EcGFp5/Eidos encryption

EcGFp5/Eidos encrypts a byte or Felt message to a recipient's public key. The application context is authenticated but not encrypted. Each message uses a fresh ephemeral scalar.

The profile combines ephemeral Diffie-Hellman, Eidos extract/expand, and Eidos authenticated encryption. It follows HPKE's key-binding and domain-separation principles, but is not an RFC 9180 ciphersuite.

Key schedule​

Let G be the curve generator, d the recipient's secret scalar, and Q = dG its public key.

For plaintext M and public context C, the sender samples a fresh nonzero scalar r. Write enc8(P) for a point's five-Felt encoding followed by three zero Felts.

R     = rG
S = rQ
c = H_context(C)
prk = H_extract(enc8(S) || enc8(R) || enc8(Q))
key = H_key(prk || c)
nonce = H_nonce(prk || c)

Extraction separates the DH computation from application-specific key expansion. The 24-Felt extraction input consists of three padded point encodings. Each expansion input is one eight-Felt block. All three outputs are four-Felt words.

The recipient computes the same shared point as S = dR and runs the same schedule.

Security assumptions​

The DH assumption is Gap-DH: computing S from Q and R remains hard even with an oracle that recognizes valid DH triples. Extraction and the two expansion roles are modeled as independent random functions with outputs uniform on D = {0, ..., 2^63 - 1}^4. This is Eidos's 252-bit output set, rather than the full space of four field elements.

In this model, a fresh extraction output is a uniform secret prk. Until an attacker obtains or guesses it, the separate expansion roles give independent key and nonce outputs, so disclosing the nonce does not disclose the key. Domain separation identifies these roles; their joint pseudorandomness is an assumption about Eidos.

For one independent hidden prk, q guesses succeed with probability at most q / 2^252. Among m distinct extraction inputs, the probability of any PRK collision is at most m * (m - 1) / 2^253, by counting pairs of uniform outputs. These PRK terms are additional to the DH, Eidos, and AEAD security terms.

Public-key commitments​

The MASM agree and seal procedures take the four-Felt commitment returned by Rust's PublicKey::to_commitment(). This hashes the canonical five-Felt encoding of Q under ECGFP5_PUBLIC_KEY. The procedures read Q from advice and check its commitment.

The preprocessed entry points take the table commitment I returned by PreparedPublicKey::to_commitment(). This hashes the twenty ordered window roots under ECGFP5_PREPROCESSED_PUBLIC_KEY. The agreement procedure authenticates the selected multiplication entries and a fixed entry containing Q against that commitment. It assumes the issuer generated the tables correctly. I identifies the preprocessed key; the authenticated point Q, rather than the table layout, enters key derivation.

Domains and versions​

Each registered domain identifies the profile, role, and version. The length is also bound in Eidos's initial chaining value.

RoleTagLogical input lengthInput
Felt context0x00000e01len(C)C
Byte context0x00001201Context length in bytesContext bytes
Extract0x00000f0124`enc8(S)
Key0x00000c018`prk
Nonce0x00000d018`prk
Public key0x000010015Q
Preprocessed public key0x0000110180Twenty ordered window roots

These roles have fixed output lengths, so no variable output-length parameter is needed.

Encryption and envelope​

The expanded Felt AEAD takes key, nonce, the full context C, and plaintext M. It XORs the plaintext's u32 limbs with raw Eidos stream output.

The MASM envelope is

[R(5), tag(2), plaintext_len, ciphertext(2 * plaintext_len)]

The context is supplied separately. Decryption validates the canonical nonidentity point, envelope length, and u32 ciphertext limbs, then checks the tag before returning plaintext. Decrypted limb pairs must encode canonical Felts.

Byte messages​

The byte API packs seven bytes per Felt, with a padding marker in the last Felt, for both plaintext and associated data. The context digest uses the byte-context domain and the original context bytes. This separates byte messages from Felt messages, including those with empty context.

The common IES wire format carries the scheme identifier, ephemeral key, and ciphertext payload. For EcGFp5/Eidos, the payload contains a byte/Felt flag, the two-Felt tag, and the ciphertext limbs encoded as little-endian u32 values. The key and nonce are derived, so neither is transmitted.

APIs and responsibilities​

Rust callers use miden_crypto::ies::SealingKey::Ecgfp5Eidos(public_key) and UnsealingKey::Ecgfp5Eidos(secret_key) with the common byte or Felt sealing methods. Both use ordinary EcGFp5 keys and require no table preparation.

The miden_crypto::ies::ecgfp5_eidos module provides Envelope and seal_with_scalar for callers that supply their own ephemeral scalar. Decode a MASM envelope with Envelope::from_elements, then decrypt it with ecgfp5_eidos::open and the original context. An Envelope also converts to the common ies::SealedMessage with From.

The core-library crypto::ies::ecgfp5_eidos module provides two sealing procedures:

ProcedurePublic-key inputHost advice builder
sealCommitment to Q (four Felts)PublicKey::advise
seal_preprocessedCommitment I (four Felts)PreparedPublicKey::advise

The core library's ecdh::ecgfp5 Rust module provides advice_inputs and preprocessed_advice_inputs adapters for these builders.

Both procedures produce the same envelope for the same recipient, scalar, plaintext, and context. The recipient does not need the preprocessed tables to decrypt it.

PublicKey::advise uses a shared generator cache, built on its first call and retained for the process lifetime (roughly 4.1 MiB). For seal_preprocessed, the host builds the recipient-specific tables with PreparedPublicKey::new and reuses them to prepare advice.

Use a fresh random scalar for each sealed envelope.

Keep the scalar, plaintext, and execution witness private. Advice generation is variable-time and must run in a trusted environment; public proving also requires zero-knowledge.

The application chooses an unambiguous context encoding and enforces the AEAD's message-size and verification limits. Sender authentication and replay protection remain application responsibilities.