Core

What every scheme shares: the key-generator and crypto base classes with the parameter cache (base), the config classes and option rules (config), the serialized objects (formats) and their version markers (versions), security profiles (profiles), review status (status), one-time precomputations (one_time), the fork handler (forksafe), exceptions and constants.

The status and security-profile modules (pyfe4ai.core.status, pyfe4ai.core.profiles) are documented on Security & Status.

Scheme Registry

The registry of the schemes: one entry per scheme, the single source of what the library records about it.

Every registered scheme has an id "family/variant" – "sife/ddh", "mcfe/ring_lwe", "mcfe/ring_lwe_threshold" – and a Scheme entry in SCHEMES with

The other tables of the library are derived from it: the status table (pyfe4ai.core.status.SCHEME_STATUS) with the README and documentation tables rendered from it, the kinds of the security profiles (pyfe4ai.core.profiles.SCHEME_KIND), the schemes of the ML adapter (pyfe4ai.ml.FESchemeWrapper: classes, labels, the servers it runs, the group variants) and the benchmark scripts. tests/api/test_registry.py checks the entries against the code.

create() builds a scheme’s key generator by id and returns it with the scheme’s crypto class; get_scheme() and list_schemes() query the registry. All three are exported by pyfe4ai:

import pyfe4ai

kg, MCFE = pyfe4ai.create("mcfe/ring_lwe", n=3, bound_x=10, bound_y=10)
pyfe4ai.list_schemes("mcfe", capabilities="threshold")
pyfe4ai.get_scheme("mcfe/ring_lwe").capabilities

Class names. The classes of a scheme are named after its id, one name per class: Threshold or Decentralized for the variants with that suffix, the family (SIFE, MIFE, MCFE, Quadratic), then the rest of the variant in CamelCase with its acronyms in capitals; the key generator adds KeyGenerator, the config class Config: sife/ddh – SIFEDDH, SIFEDDHKeyGenerator, SIFEDDHConfig; mcfe/ring_lwe_threshold – ThresholdMCFERingLWE; mcfe/ddh_decentralized – DecentralizedMCFEDDH; mife/fh_multi_ipe_pairing – MIFEFHMultiIPEPairing; quadratic/miqfe – QuadraticMIQFE.

pyfe4ai.core.registry.STATUSES = ('reviewed', 'experimental', 'unreviewed', 'known-insecure')

The review status values, best first.

pyfe4ai.core.registry.FIDELITIES = ('faithful', 'adapted', 'ad-hoc', 'unknown')

The fidelity values.

class pyfe4ai.core.registry.SchemeStatus(module, status, fidelity, reference, note='', issue='')[source]

Bases: object

Review status of one registered scheme.

status

"reviewed": the implementation was checked against the cited construction and no security defect is known. "experimental": implemented and checked here, but the construction or its security argument is our own rather than a published one; no defect is known. "unreviewed": not yet checked against its paper; no defect is known, but none was looked for systematically either. "known-insecure": a concrete privacy defect is known (see issue); the scheme computes correct results but must only be used for functionality or performance experiments.

fidelity

"faithful": the published construction as written. "adapted": the published construction with documented deviations or extensions (see note). "ad-hoc": a composition with no published construction behind it. "unknown": not assessed (unreviewed schemes).

module is the scheme’s module, reference the construction it implements. All schemes additionally share the caveats of the README (research prototype, toy default parameters, no side-channel hardening).

Parameters:
  • module (str)

  • status (str)

  • fidelity (str)

  • reference (str)

  • note (str, default: '')

  • issue (str, default: '')

pyfe4ai.core.registry.KINDS = {'dcr': 'decisional composite residuosity (Paillier)', 'dl': 'discrete log in a safe-prime group (DDH, Damgard / MDDH)', 'ec': 'DDH over ristretto255 (a fixed group)', 'lwe': 'dense LWE without a public matrix (the ABMPSW20 MCFE family)', 'lwe_abdp15': 'LWE with a seeded public matrix (the ABDP15 IPFE)', 'lwe_matrix': 'LWE with a public matrix, ALS16', 'pairing': 'asymmetric pairings', 'ring_lwe': 'Ring-LWE'}

The kinds of scheme the security profiles size parameters for (see pyfe4ai.core.profiles).

pyfe4ai.core.registry.CAPABILITIES = {'binary_ct': "binary ciphertexts (crypto option ct_format='binary', or the public parameters' format)", 'decentralized': 'the clients derive shares of each functional key, which the decryptor combines (derive_function_decryption_key_share, combine_function_decryption_key_share)', 'labels': 'ciphertexts and functional keys are bound to a label (the MCFE family)', 'ml_servers': 'the ML adapter runs the decryption servers in-process (pyfe4ai.ml: aggregate_gradients, prepare_aggregation)', 'pairing': 'runs over a pairing group (pairing_group_param; BLS12-381 by default)', 'rns': "an RNS modulus, a product of NTT primes (key generator option ring_modulus='rns')", 'threshold': 'functional keys are shared among s servers; t partial decryptions decrypt (share_decrypt, combine_decrypt)'}

The capabilities a scheme may have, with what they mean. labels, threshold, decentralized and pairing follow from the id and the kind; the others are declared per scheme.

pyfe4ai.core.registry.FAMILIES = {'mcfe': 'MCFE', 'mife': 'MIFE', 'quadratic': 'Quadratic', 'sife': 'SIFE'}

The family part of the class names.

pyfe4ai.core.registry.class_name(scheme, role='')[source]

The name of a class of scheme ("family/variant"): the crypto class for role="", else the name with role appended ("KeyGenerator", "Config"); see the module docstring.

Raises:

KeyError – For a family or a variant word without a spelling.

Parameters:
  • scheme (str)

  • role (str, default: '')

Return type:

str

class pyfe4ai.core.registry.Scheme(family, variant, module, kind, status, capabilities, refused='', group=None, instance_of=None)[source]

Bases: object

A registered scheme (see the module docstring).

The classes are imported when first read: key_generator, crypto, config.

Parameters:
module: str

The scheme’s module.

kind: str

See KINDS.

capabilities: frozenset

See CAPABILITIES.

refused: str = ''

Why the standard profile refuses the scheme; empty if it does not.

group: str | None = None

The group of a scheme that instantiates another variant of its family in a group of its own (the ML adapter’s group option), such as ristretto255 for ddh_ristretto255.

instance_of: str | None = None

The variant that such a scheme instantiates (ddh for ddh_ristretto255).

property id: str

"family/variant".

property key: tuple[str, str]

(family, variant), the key of the derived tables.

property key_generator: type

The key generator class (imports the module).

property crypto: type

The crypto class, whose objects encrypt, decrypt or serve (imports the module).

property config: type

The config class (pyfe4ai.core.config).

has(*capabilities)[source]

Whether the scheme has every one of capabilities.

Raises:

FEValidationError – For a name not in CAPABILITIES.

Parameters:

capabilities (str)

Return type:

bool

pyfe4ai.core.registry.SCHEMES: tuple[Scheme, ...]

Every registered scheme, in the order of the tables derived from them.

pyfe4ai.core.registry.get_scheme(scheme)[source]

The registry entry of scheme: an id "family/variant" or a (family, variant) pair.

Raises:

FEValidationError – If the scheme is not registered.

Parameters:

scheme (str | tuple[str, str])

Return type:

Scheme

pyfe4ai.core.registry.scheme_for_module(module)[source]

The scheme whose module is module, if any.

Parameters:

module (str)

Return type:

Scheme | None

pyfe4ai.core.registry.list_schemes(family=None, *, capabilities=(), status=None, kind=None)[source]

The ids of the registered schemes, in registry order, optionally only those of family, with all of capabilities (CAPABILITIES), of review status (STATUSES) or of kind (KINDS).

Raises:

FEValidationError – For an unknown family, capability, status or kind.

Parameters:
Return type:

list[str]

class pyfe4ai.core.registry.CreatedScheme(key_generator, crypto)[source]

Bases: NamedTuple

What create() returns: key_generator, crypto = create(...).

Parameters:
  • key_generator (Any)

  • crypto (type)

key_generator: Any

The scheme’s key generator, built from the config; not set up yet.

crypto: type

The scheme’s crypto class, whose objects encrypt (clients, with pp and sk), decrypt (with pp and a functional key) or, for the threshold schemes, decrypt partially and combine.

pyfe4ai.core.registry.create(scheme, config=None, **options)[source]

Build the key generator of scheme and return it with the scheme’s crypto class.

create("mcfe/ring_lwe", config) is MCFERingLWEKeyGenerator(config) together with MCFERingLWE: the key generator is built exactly as by its class (the config is converted to the scheme’s config class and completed by its security profile, see pyfe4ai.core.config), and not set up: call its setup(), then hand out the public parameters and keys:

kg, SIFEDDH = pyfe4ai.create("sife/ddh", eta=3)
kg.setup()
pp = kg.get_public_parameters()
client = SIFEDDH({"keys": {"pp": pp, "sk": kg.get_private_keys()}})
Parameters:
  • scheme (str | tuple[str, str]) – The scheme’s id "family/variant" (list_schemes()), or (family, variant).

  • config (Mapping | None, default: None) – The key generator’s config (a mapping); None for an empty one (the scheme’s defaults, toy profile).

  • **options – Config entries, added to config (and replacing its entries of the same name).

Return type:

CreatedScheme

Returns:

CreatedScheme (key_generator, crypto).

Raises:

FEValidationError – For an unknown scheme, a config that is not a mapping, or a config the key generator refuses.

The registered schemes (standard: whether the standard profile gives the scheme parameters; see Security & Status):

Scheme

Classes (crypto, key generator, config)

Kind

Capabilities

standard

sife/ddh

SIFEDDH, SIFEDDHKeyGenerator, SIFEDDHConfig

dl

–

yes

sife/ddh_ristretto255

SIFEDDHRistretto255, SIFEDDHRistretto255KeyGenerator, SIFEDDHRistretto255Config

ec

–

yes

sife/lwe

SIFELWE, SIFELWEKeyGenerator, SIFELWEConfig

lwe_abdp15

–

yes

sife/paillier

SIFEPaillier, SIFEPaillierKeyGenerator, SIFEPaillierConfig

dcr

–

yes

sife/damgard

SIFEDamgard, SIFEDamgardKeyGenerator, SIFEDamgardConfig

dl

–

yes

sife/ring_lwe

SIFERingLWE, SIFERingLWEKeyGenerator, SIFERingLWEConfig

ring_lwe

–

yes

sife/fullysec_ring_lwe

SIFEFullySecRingLWE, SIFEFullySecRingLWEKeyGenerator, SIFEFullySecRingLWEConfig

ring_lwe

–

yes

sife/fullysec_lwe

SIFEFullySecLWE, SIFEFullySecLWEKeyGenerator, SIFEFullySecLWEConfig

lwe_matrix

–

refused

sife/ddh_dynamic

SIFEDDHDynamic, SIFEDDHDynamicKeyGenerator, SIFEDDHDynamicConfig

dl

–

yes

sife/fh_ipe_pairing

SIFEFHIPEPairing, SIFEFHIPEPairingKeyGenerator, SIFEFHIPEPairingConfig

pairing

pairing

yes

sife/part_fh_ipe_pairing

SIFEPartFHIPEPairing, SIFEPartFHIPEPairingKeyGenerator, SIFEPartFHIPEPairingConfig

pairing

pairing

yes

mife/ddh

MIFEDDH, MIFEDDHKeyGenerator, MIFEDDHConfig

dl

–

yes

mife/ddh_ristretto255

MIFEDDHRistretto255, MIFEDDHRistretto255KeyGenerator, MIFEDDHRistretto255Config

ec

–

yes

mife/lwe

MIFELWE, MIFELWEKeyGenerator, MIFELWEConfig

lwe_abdp15

–

yes

mife/paillier

MIFEPaillier, MIFEPaillierKeyGenerator, MIFEPaillierConfig

dcr

–

yes

mife/damgard

MIFEDamgard, MIFEDamgardKeyGenerator, MIFEDamgardConfig

dl

–

yes

mife/ring_lwe

MIFERingLWE, MIFERingLWEKeyGenerator, MIFERingLWEConfig

ring_lwe

binary_ct, rns

yes

mife/fullysec_lwe

MIFEFullySecLWE, MIFEFullySecLWEKeyGenerator, MIFEFullySecLWEConfig

lwe_matrix

–

refused

mife/fh_ipe_pairing

MIFEFHIPEPairing, MIFEFHIPEPairingKeyGenerator, MIFEFHIPEPairingConfig

pairing

pairing

yes

mife/fh_multi_ipe_pairing

MIFEFHMultiIPEPairing, MIFEFHMultiIPEPairingKeyGenerator, MIFEFHMultiIPEPairingConfig

pairing

pairing

yes

mife/ddh_threshold

ThresholdMIFEDDH, ThresholdMIFEDDHKeyGenerator, ThresholdMIFEDDHConfig

dl

threshold

yes

mife/lwe_threshold

ThresholdMIFELWE, ThresholdMIFELWEKeyGenerator, ThresholdMIFELWEConfig

lwe_abdp15

threshold

refused

mcfe/ddh

MCFEDDH, MCFEDDHKeyGenerator, MCFEDDHConfig

dl

labels

yes

mcfe/ddh_ristretto255

MCFEDDHRistretto255, MCFEDDHRistretto255KeyGenerator, MCFEDDHRistretto255Config

ec

labels

yes

mcfe/lwe

MCFELWE, MCFELWEKeyGenerator, MCFELWEConfig

lwe

labels

yes

mcfe/paillier

MCFEPaillier, MCFEPaillierKeyGenerator, MCFEPaillierConfig

dcr

labels

yes

mcfe/damgard

MCFEDamgard, MCFEDamgardKeyGenerator, MCFEDamgardConfig

dl

labels

yes

mcfe/ring_lwe

MCFERingLWE, MCFERingLWEKeyGenerator, MCFERingLWEConfig

ring_lwe

binary_ct, labels, rns

yes

mcfe/fullysec_lwe

MCFEFullySecLWE, MCFEFullySecLWEKeyGenerator, MCFEFullySecLWEConfig

lwe

labels

yes

mcfe/fh_multi_ipe_pairing

MCFEFHMultiIPEPairing, MCFEFHMultiIPEPairingKeyGenerator, MCFEFHMultiIPEPairingConfig

pairing

labels, pairing

yes

mcfe/fh_multi_ipe_pairing_threshold

ThresholdMCFEFHMultiIPEPairing, ThresholdMCFEFHMultiIPEPairingKeyGenerator, ThresholdMCFEFHMultiIPEPairingConfig

pairing

labels, pairing, threshold

yes

mcfe/fh_multi_ipe_pairing_decentralized

DecentralizedMCFEFHMultiIPEPairing, DecentralizedMCFEFHMultiIPEPairingKeyGenerator, DecentralizedMCFEFHMultiIPEPairingConfig

pairing

decentralized, labels, pairing

yes

mcfe/ddh_threshold

ThresholdMCFEDDH, ThresholdMCFEDDHKeyGenerator, ThresholdMCFEDDHConfig

dl

labels, threshold

yes

mcfe/ddh_decentralized

DecentralizedMCFEDDH, DecentralizedMCFEDDHKeyGenerator, DecentralizedMCFEDDHConfig

dl

decentralized, labels

yes

mcfe/lwe_threshold

ThresholdMCFELWE, ThresholdMCFELWEKeyGenerator, ThresholdMCFELWEConfig

lwe

labels, threshold

yes

mcfe/lwe_decentralized

DecentralizedMCFELWE, DecentralizedMCFELWEKeyGenerator, DecentralizedMCFELWEConfig

lwe

decentralized, labels

yes

mcfe/ring_lwe_threshold

ThresholdMCFERingLWE, ThresholdMCFERingLWEKeyGenerator, ThresholdMCFERingLWEConfig

ring_lwe

binary_ct, labels, ml_servers, rns, threshold

yes

mcfe/ring_lwe_decentralized

DecentralizedMCFERingLWE, DecentralizedMCFERingLWEKeyGenerator, DecentralizedMCFERingLWEConfig

ring_lwe

binary_ct, decentralized, labels, rns

yes

mcfe/paillier_decentralized

DecentralizedMCFEPaillier, DecentralizedMCFEPaillierKeyGenerator, DecentralizedMCFEPaillierConfig

dcr

decentralized, labels

refused

quadratic/quad

QuadraticQuad, QuadraticQuadKeyGenerator, QuadraticQuadConfig

pairing

pairing

yes

quadratic/sgp

QuadraticSGP, QuadraticSGPKeyGenerator, QuadraticSGPConfig

pairing

pairing

yes

quadratic/miqfe

QuadraticMIQFE, QuadraticMIQFEKeyGenerator, QuadraticMIQFEConfig

pairing

pairing

yes

Base Classes and the Parameter Cache

Abstract base classes shared by all IPFE schemes.

pyfe4ai.core.base.CACHE_DIR_ENV = 'PYFE4AI_CACHE_DIR'

Environment variable that sets the parameter cache directory (see cache_dir()).

pyfe4ai.core.base.default_cache_dir()[source]

The per-user cache directory of PyFE4AI on this platform.

~/Library/Caches/pyfe4ai on macOS, %LOCALAPPDATA%\pyfe4ai\Cache on Windows, and $XDG_CACHE_HOME/pyfe4ai elsewhere (~/.cache/pyfe4ai if XDG_CACHE_HOME is unset or not an absolute path) – the directories of platformdirs.user_cache_dir("pyfe4ai", appauthor=False).

Return type:

str

pyfe4ai.core.base.cache_dir(explicit=None)[source]

The parameter cache directory: explicit (the cache_dir entry of a key generator’s or crypto object’s config) if given, else the PYFE4AI_CACHE_DIR environment variable if set and not empty, else default_cache_dir(). A relative path is relative to the working directory.

Key generators keep their records in <cache_dir>/authority/<scheme type>/ (see ParameterCacheMixin). The cache is trusted: it must not be writable by others.

Raises:

FEValidationError – If explicit is not a non-empty path.

Return type:

str

class pyfe4ai.core.base.ParameterCacheMixin[source]

Bases: object

Mixin that provides JSON-based parameter caching with validation.

Subclasses must set _scheme_type (a CryptoCONST string) and implement _param_verification, _apply_parameters, and _generate_and_save. The records are kept in config_folder, the authority folder of the cache directory (cache_dir(): the cache_dir entry of the config, PYFE4AI_CACHE_DIR or the per-user cache directory).

config_folder: str
class pyfe4ai.core.base.IPFEAbsKeyGenerator(config, **kwargs)[source]

Bases: object

Abstract base for all inner-product FE key generators.

Subclasses implement setup() (generate keys), get_public_parameters(), get_private_keys(), and get_decryption_keys().

Parameters:

config (dict) – Scheme configuration (a mapping, converted to the scheme’s config class of pyfe4ai.core.config). Expected keys vary by scheme; common keys include sec_param, eta, n, s, lst_nid, security_profile (see pyfe4ai.core.profiles) and cache_dir (the parameter cache directory, see cache_dir()).

abstractmethod setup()[source]

Generate master public and secret keys for the scheme.

Return type:

None

abstractmethod get_public_parameters(**kwargs)[source]

Return serialisable public parameters.

Return type:

None | dict

Returns:

A dict of public parameters, or None on error.

abstractmethod get_private_keys(nid, **kwargs)[source]

Return the private (encryption) keys for client nid.

Parameters:

nid (str) – A client/node identifier.

Return type:

None | dict

Returns:

A dict of private keys, or None if nid is invalid.

abstractmethod get_decryption_keys(sid, **kwargs)[source]

Derive a functional decryption key for session sid.

Parameters:
  • sid (str) – A session identifier.

  • **kwargs – Must include credentials with a fusion_weight entry.

Return type:

None | dict

Returns:

A dict containing the decryption key material.

Raises:
pyfe4ai.core.base.decoded_layer(values, layer, scale=1)[source]

Return the decrypted elements of one ndarray layer, divided by scale.

Parameters:
  • values – Array (or nested sequence) of decrypted integers; None marks an element that did not decrypt.

  • layer (int) – Index of the layer, for the error message.

  • scale (int, default: 1) – Fixed-point scale of the plaintexts (10^precision).

Raises:

FESchemeError – For the first element that did not decrypt – its result is outside the decryption bound, or the key and the ciphertext do not match. None is never turned into NaN.

Return type:

ndarray

pyfe4ai.core.base.PRIVATE_KEY_NOT_A_DICT = "the encryption key (keys['sk']) is not a dict of its fields"

The FEKeyError text for an encryption key (keys["sk"]) that is not a dict (raised by IPFEAbsCrypto._check_private_key).

class pyfe4ai.core.base.IPFEAbsCrypto(config, **kwargs)[source]

Bases: ABC

Abstract base for all inner-product FE crypto operations.

Subclasses implement encrypt_lst_ndarray(), compute_lst_ndarray_ct(), and decrypt_lst_ndarray_ct().

Parameters:

config (dict) – Runtime configuration dict containing at least keys (a dict with pp, sk, and/or dk sub-dicts) and optionally id, type, and precision.

abstractmethod encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]

Encrypt a list of ndarray-like plaintexts.

Parameters:

lst_ndarray (list) – List of plaintext arrays to encrypt.

Return type:

list | None

Returns:

List of ciphertext dicts, or None on error.

abstractmethod compute_lst_ndarray_ct(dict_ndarray_ct, **kwargs)[source]

Aggregate ciphertexts from multiple clients.

Parameters:

dict_ndarray_ct (dict) – Mapping of client IDs to their ciphertext lists.

Return type:

list | None

Returns:

Aggregated ciphertext list, or None on error.

abstractmethod decrypt_lst_ndarray_ct(dict_ndarray_ct, **kwargs)[source]

Decrypt aggregated ndarray ciphertexts.

Parameters:

dict_ndarray_ct (dict) – Mapping of client IDs to their ciphertext lists.

Return type:

list | None

Returns:

One float array of decrypted results per layer.

Raises:

FESchemeError – If an element does not decrypt (see decoded_layer()).

Serialized Objects

The serialized objects of the schemes: their layouts and byte codecs.

Every object that leaves a scheme – public parameters, parameter records, encryption keys, functional keys and key shares, ciphertexts, partial decryptions – is a dict (JSON-friendly, with bytes for the binary formats). Its layout is declared once as a Record: the fields in wire order, what each holds, and what an absent field means (versions and their markers: pyfe4ai.core.versions). The schemes build these dicts with Record.new and read them through record views, so the dicts themselves are what they were: a record is the dict, not a copy.

  • record – Record and Field;

  • binary – the byte codecs of the Ring-LWE ciphertexts and values;

  • lwe – the LWE schemes (ABDP15, FullySec, the ABMPSW20 MCFE);

  • ring_lwe – the Ring-LWE schemes;

  • dl – the discrete-log and DCR schemes;

  • pairing – the pairing schemes (function-hiding IPFE, MIFE and MCFE) and the quadratic schemes;

  • threshold – key shares, replicated pieces and partial decryptions of the threshold schemes.

The base of the serialized-object containers: Record and Field.

A record is a typed view of the dict that is its wire form. It holds that dict itself – no copy, no conversion – so a record and its dict are always the same bytes on the wire, key order and unknown fields included: Record.from_dict(d).to_dict() is d. Reading a field reads the dict as the code of earlier versions did:

  • record.name is d["name"] (KeyError if the field is absent);

  • record.get("name", default) is d.get("name", default) and "name" in record is "name" in d, for a declared field only (an undeclared name raises AttributeError);

  • record.name = value, record.update(...) and del record.name write the dict.

So the checks a scheme makes when it reads a key or a ciphertext stay where they are, with their exceptions; what a record adds is one declaration of every field, its order on the wire and what its absence means (Field(absent=...): the default of earlier versions that a missing marker stands for, documented here and applied by pyfe4ai.core.versions, never silently by attribute access). Record.new() builds the dict of a new object in the declared order.

pyfe4ai.core.formats.record.ABSENT: Any = ABSENT

Marks a field that Record.new() leaves out (an optional field whose absence has a meaning, e.g. the JSON format of versions <= 0.3.0).

class pyfe4ai.core.formats.record.Field(doc='', *, absent=<object object>)[source]

Bases: object

A field of a Record, by its wire name (the attribute name).

Parameters:
  • doc (str, default: '') – What the field holds (its type and encoding).

  • absent (Any, default: <object object at 0x7062278c6a40>) – What a missing field means, for fields that versions or options leave out: documentation of the default that pyfe4ai.core.versions (or the scheme) applies, which tests/config/test_versions.py checks against it; None where it depends on the context (the doc says how). Reading a missing field raises KeyError as d[name] does, whatever it means.

property optional: bool

Whether the field has a meaning when absent.

class pyfe4ai.core.formats.record.Record(raw)[source]

Bases: object

A serialized object: a typed view of its wire dict (see the module docstring).

Subclasses declare their fields as Field attributes, in wire order (a base class’s fields first), or give that order in ORDER when a subclass’s fields go between its base’s.

FIELDS: ClassVar[tuple[str, ...]] = ()

Field names in wire order (set for every subclass).

classmethod from_dict(data)[source]

The record of a wire dict (the dict itself, not a copy; its fields are read when used, with the checks of each use).

classmethod new(**values)[source]

A new record: a dict of values in the declared order; a value ABSENT leaves its field out.

Raises:

TypeError – For a name that is not a field.

classmethod extend(base, **values)[source]

dict(base, **values) as a record: a new dict with base’s fields in their order, then values (a field of base keeps its place, as with a dict).

Raises:

TypeError – For a name of values that is not a field.

to_dict()[source]

The wire dict (the record’s own, not a copy).

get(name, default=None)[source]

d.get(name, default) for the declared field name.

Parameters:

name (str)

update(**values)[source]

d.update(values) for declared fields (a field already present keeps its place on the wire, as with a dict).

Raises:

TypeError – For a name that is not a field.

Return type:

None

pop(name, default=None)[source]

d.pop(name, default) for the declared field name.

Parameters:

name (str)

Byte codecs of the Ring-LWE ciphertexts and values.

Both formats start with b"PFRL" and a version byte (1 or 2); a reader of one refuses the other.

pyfe4ai.core.formats.binary.encode_binary_ciphertext(ct0, ct1, q, ring_n)[source]

Binary format 1 of a ciphertext with eta rows ct0 and ct1.

b"PFRL", version 1, wb = ceil(bits(q) / 8), eta (2 bytes, little-endian), log2 ring_n and a zero byte; then the coefficients of the ct0 rows and of ct1, ring_n each, as wb-byte little-endian integers in [0, q).

Parameters:
Return type:

bytes

pyfe4ai.core.formats.binary.decode_binary_ciphertext(data, q, eta, ring_n)[source]

(ct0, ct1) of a format-1 ciphertext, coefficients reduced mod q.

Raises:

ValueError – If the header or the length does not match.

Parameters:
Return type:

tuple

pyfe4ai.core.formats.binary.encode_threshold_ciphertext(ct0, ct1, k, q, ring_n)[source]

Binary format 2 of a ciphertext with batch length k.

b"PFRL", version 2, wb = ceil(bits(q) / 8), eta (2 bytes, little-endian), log2 ring_n, a zero byte and k (4 bytes, little-endian); then the first k coefficients of each ct0 row and the ring_n coefficients of ct1, as wb-byte little-endian integers in [0, q). Decryption reads only the first k coefficients of ct0 (coefficient-wise), while ct1 enters a ring product.

Parameters:
Return type:

bytes

pyfe4ai.core.formats.binary.threshold_ciphertext_from_format1(data, k, q, eta, ring_n)[source]

Format 2 (encode_threshold_ciphertext()) of a format-1 ciphertext whose values are below q (as this library writes them; a reader of format 2 checks that again).

Raises:

ValueError – If data is not a format-1 ciphertext of these parameters.

Parameters:
Return type:

bytes

pyfe4ai.core.formats.binary.threshold_ciphertext_header(data, q, eta, ring_n)[source]

The batch length k of a format-2 ciphertext of these parameters (header and length checked; the values are not).

Raises:

ValueError – If the header or the length does not match.

Parameters:
Return type:

int

pyfe4ai.core.formats.binary.decode_values(data, q, count)[source]

count ceil(bits(q) / 8)-byte little-endian integers, each strictly below q (a value >= q would be a second encoding of one below it).

Raises:

ValueError – For another length or a value >= q.

Parameters:

count (int)

Return type:

list

pyfe4ai.core.formats.binary.encode_values(values, q)[source]

Integers in [0, q) (reduced mod q) as ceil(bits(q) / 8)-byte little-endian words.

Return type:

bytes

pyfe4ai.core.formats.binary.decode_threshold_ciphertext(data, q, eta, ring_n)[source]

(k, ct0, ct1) of a format-2 ciphertext: eta rows of k coefficients and ring_n coefficients, all strictly below q.

Raises:

ValueError – If the header, the length or a value does not match.

Parameters:
Return type:

tuple

pyfe4ai.core.formats.binary.canonical_ring_ciphertext(ct, q, eta, ring_n)[source]

Return (k, ct0, ct1) of a BMMS21 ciphertext with coefficients in [0, q).

ct holds k and either ct0 and ct1 (JSON format) or ct (binary format, encode_binary_ciphertext()).

Raises:

FESchemeError – Unless ct has eta polynomials ct0 and one polynomial ct1 of ring_n integer coefficients each, and a batch length 1 <= k <= ring_n.

Parameters:
Return type:

tuple

The serialized objects of the LWE schemes: the ABDP15 IPFE with a seeded public matrix (pyfe4ai.schemes.sife.lwe, pyfe4ai.schemes.mife.lwe and the threshold pyfe4ai.schemes.mife.lwe_threshold), ALS16 FullySec (pyfe4ai.schemes.sife.fullysec_lwe, pyfe4ai.schemes.mife.fullysec_lwe) and the ABMPSW20 MCFE (pyfe4ai.schemes.mcfe.lwe, its FullySec, threshold and decentralised variants; the threshold key shares and partial decryptions are in pyfe4ai.core.formats.threshold).

Values are decimal strings unless a field says otherwise.

class pyfe4ai.core.formats.lwe.ABDP15Record(raw)[source]

Bases: Record

Parameter record of the ABDP15 schemes (SIFE, MIFE and threshold MIFE LWE): the configuration it was derived for, the derived parameters and the seed of A.

Fields, in wire order:

  • construction – record id (SIFE_LWE_RECORD, MIFE_LWE_RECORD or a tMIFE-LWE construction id)

  • sec_param – int

  • eta – int

  • lwe_n_config – the config’s lwe_n (int or auto)

  • bound_x – decimal string

  • bound_y – decimal string

  • n – int, the number of slots (MIFE)

  • s – int, the number of servers (tMIFE)

  • stat_param – int (tMIFE)

  • flooding_accounting – kl (tMIFE under that accounting) (absent: ‘per-sample’)

  • max_partial_decryptions – int (tMIFE, kl)

  • lwe_n – int

  • p – decimal string

  • q – decimal string

  • m – int, the rows of A

  • sigma_q – float

  • l_sigma – decimal string

  • sigma_f – decimal string, the flooding width (tMIFE)

  • A_seed – 32-byte hex seed of A

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'sec_param', 'eta', 'lwe_n_config', 'bound_x', 'bound_y', 'n', 's', 'stat_param', 'flooding_accounting', 'max_partial_decryptions', 'lwe_n', 'p', 'q', 'm', 'sigma_q', 'l_sigma', 'sigma_f', 'A_seed')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.SIFELWEParameters(raw)[source]

Bases: Record

Public parameters of SIFE LWE (ABDP15).

Fields, in wire order:

  • A_seed – hex seed of A

  • m – int

  • lwe_n – int

  • gaussian_sampler – the sampler of the public keys’ noise

  • security_profile – toy or standard

  • p – decimal string

  • q – decimal string

  • eta – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sec_param – int

FIELDS: ClassVar[tuple[str, ...]] = ('A_seed', 'm', 'lwe_n', 'gaussian_sampler', 'security_profile', 'p', 'q', 'eta', 'bound_x', 'bound_y', 'sec_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.MIFELWEParameters(raw)[source]

Bases: Record

Public parameters of MIFE LWE (ABDP15 slots).

Fields, in wire order:

  • A_seed – hex seed of A

  • m – int

  • lwe_n – int

  • gaussian_sampler – the sampler of the public keys’ noise

  • security_profile – toy or standard

  • p – decimal string

  • q – decimal string

  • eta – int

  • n – int, the number of slots

  • bound_x – decimal string

  • bound_y – decimal string

  • sec_param – int

FIELDS: ClassVar[tuple[str, ...]] = ('A_seed', 'm', 'lwe_n', 'gaussian_sampler', 'security_profile', 'p', 'q', 'eta', 'n', 'bound_x', 'bound_y', 'sec_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.TMIFELWEParameters(raw)[source]

Bases: MIFELWEParameters

Public parameters of the threshold MIFE over LWE.

Fields, in wire order:

  • A_seed – hex seed of A

  • m – int

  • lwe_n – int

  • gaussian_sampler – the sampler of the public keys’ noise

  • security_profile – toy or standard

  • p – decimal string

  • q – decimal string

  • eta – int

  • n – int, the number of slots

  • bound_x – decimal string

  • bound_y – decimal string

  • sec_param – int

  • s – int, the number of servers

  • t – int, the threshold

  • lst_sid – the server ids

  • sigma_f – decimal string, the flooding width

  • sharing – the key sharing (absent: ‘shamir’)

  • threshold_construction – construction id (optional)

  • flooding_accounting – kl (only under that accounting) (absent: ‘per-sample’)

  • max_partial_decryptions – int (kl only)

  • stat_param – int (kl only)

  • flood_tail_cut – int (kl only)

FIELDS: ClassVar[tuple[str, ...]] = ('A_seed', 'm', 'lwe_n', 'gaussian_sampler', 'security_profile', 'p', 'q', 'eta', 'n', 'bound_x', 'bound_y', 'sec_param', 's', 't', 'lst_sid', 'sigma_f', 'sharing', 'threshold_construction', 'flooding_accounting', 'max_partial_decryptions', 'stat_param', 'flood_tail_cut')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.LWEEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE LWE: the public key A S + E.

Fields, in wire order:

  • pk – m x eta matrix

FIELDS: ClassVar[tuple[str, ...]] = ('pk',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.MIFELWEEncryptionKey(raw)[source]

Bases: LWEEncryptionKey

Encryption key of a MIFE LWE slot (the threshold MIFE adds mac_keys).

Fields, in wire order:

  • pk – m x eta matrix

  • u – the slot’s pad (eta values)

  • mac_keys – tMIFE: {server: hex key} of the ciphertext tags

FIELDS: ClassVar[tuple[str, ...]] = ('pk', 'u', 'mac_keys')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.SIFELWEFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE LWE and SIFE FullySec LWE.

Fields, in wire order:

  • sk_y – vector

  • y – the weights (ints)

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y', 'y')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.MIFELWEFunctionalKey(raw)[source]

Bases: Record

Functional key of MIFE LWE and MIFE FullySec LWE (shared among the servers by the threshold MIFE).

Fields, in wire order:

  • sk_y – {slot: vector}

  • z – decimal string, the pad term

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y', 'z')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.LWECiphertext(raw)[source]

Bases: Record

Ciphertext of the ABDP15 and FullySec LWE schemes (ct0: the A-part, ct1: the eta slot values; the threshold MIFE adds tags).

Fields, in wire order:

  • ct0 – vector

  • ct1 – vector of eta values

  • tags – tMIFE: {server: hex HMAC}

FIELDS: ClassVar[tuple[str, ...]] = ('ct0', 'ct1', 'tags')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.FullySecLWERecord(raw)[source]

Bases: Record

Parameter record of SIFE / MIFE FullySec LWE.

Fields, in wire order:

  • construction – record id (SIFE_FULLYSEC_LWE_RECORD or the MIFE one)

  • sec_param – int

  • eta – int

  • n – int, the number of slots (MIFE)

  • lwe_n – int

  • m – int

  • bound_x – decimal string

  • bound_y – decimal string

  • k – decimal string

  • q – decimal string

  • sigma_q – float

  • l_sigma_q – decimal string

  • sigma1 – float

  • l_sigma1 – decimal string

  • sigma2 – float

  • l_sigma2 – decimal string

  • A_seed – 32-byte hex seed of A

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'sec_param', 'eta', 'n', 'lwe_n', 'm', 'bound_x', 'bound_y', 'k', 'q', 'sigma_q', 'l_sigma_q', 'sigma1', 'l_sigma1', 'sigma2', 'l_sigma2', 'A_seed')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.FullySecLWEParameters(raw)[source]

Bases: Record

Public parameters of SIFE / MIFE FullySec LWE (A expanded).

Fields, in wire order:

  • A – m x lwe_n matrix

  • k – decimal string

  • q – decimal string

  • m – int

  • eta – int

  • n – int, the number of slots (MIFE)

  • lwe_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sigma_q – float

  • sigma1 – float

  • sigma2 – float

  • sec_param – int

FIELDS: ClassVar[tuple[str, ...]] = ('A', 'k', 'q', 'm', 'eta', 'n', 'lwe_n', 'bound_x', 'bound_y', 'sigma_q', 'sigma1', 'sigma2', 'sec_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.MCFELWEParameters(raw)[source]

Bases: Record

Public parameters of the MCFE over LWE (ABMPSW20 Fig. 4; also FullySec).

Fields, in wire order:

  • q – decimal string

  • q0 – int, the rounding modulus

  • K – int

  • delta – decimal string

  • bound_ip – int, the decoding bound

  • n0 – int

  • m0 – int

  • security – selective or adaptive

  • eta – int

  • n – int, the number of clients

  • lwe_n – int

  • bound_x – int

  • bound_y – int

  • stat_param – int

  • sec_param – int

  • gaussian_sampler – the sampler of the keys

  • security_profile – toy or standard

  • label_hash – label hash mode (absent: ‘shake256-wide’)

FIELDS: ClassVar[tuple[str, ...]] = ('q', 'q0', 'K', 'delta', 'bound_ip', 'n0', 'm0', 'security', 'eta', 'n', 'lwe_n', 'bound_x', 'bound_y', 'stat_param', 'sec_param', 'gaussian_sampler', 'security_profile', 'label_hash')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.TMCFELWEParameters(raw)[source]

Bases: MCFELWEParameters

Public parameters of the threshold MCFE over LWE.

Fields, in wire order:

  • q – decimal string

  • q0 – int, the rounding modulus

  • K – int

  • delta – decimal string

  • bound_ip – int, the decoding bound

  • n0 – int

  • m0 – int

  • security – selective or adaptive

  • eta – int

  • n – int, the number of clients

  • lwe_n – int

  • bound_x – int

  • bound_y – int

  • stat_param – int

  • sec_param – int

  • gaussian_sampler – the sampler of the keys

  • security_profile – toy or standard

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • s – int, the number of servers

  • t – int, the threshold

  • lst_sid – the server ids

  • sigma_f – decimal string, the flooding width

  • sharing – the key sharing (absent: ‘shamir’)

  • threshold_construction – construction id (optional)

FIELDS: ClassVar[tuple[str, ...]] = ('q', 'q0', 'K', 'delta', 'bound_ip', 'n0', 'm0', 'security', 'eta', 'n', 'lwe_n', 'bound_x', 'bound_y', 'stat_param', 'sec_param', 'gaussian_sampler', 'security_profile', 'label_hash', 's', 't', 'lst_sid', 'sigma_f', 'sharing', 'threshold_construction')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.DecentralizedLWEParameters(raw)[source]

Bases: MCFELWEParameters

Public parameters of the decentralised MCFE over LWE (Fig. 14).

Fields, in wire order:

  • q – decimal string

  • q0 – int, the rounding modulus

  • K – int

  • delta – decimal string

  • bound_ip – int, the decoding bound

  • n0 – int

  • m0 – int

  • security – selective or adaptive

  • eta – int

  • n – int, the number of clients

  • lwe_n – int

  • bound_x – int

  • bound_y – int

  • stat_param – int

  • sec_param – int

  • gaussian_sampler – the sampler of the keys

  • security_profile – toy or standard

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • n2_mod – decimal string, the DCR modulus of the key derivation

  • lst_nid – the client ids

  • contribution_bound – decimal string

FIELDS: ClassVar[tuple[str, ...]] = ('q', 'q0', 'K', 'delta', 'bound_ip', 'n0', 'm0', 'security', 'eta', 'n', 'lwe_n', 'bound_x', 'bound_y', 'stat_param', 'sec_param', 'gaussian_sampler', 'security_profile', 'label_hash', 'n2_mod', 'lst_nid', 'contribution_bound')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.DecentralizedLWERecord(raw)[source]

Bases: Record

Parameter record of the decentralised MCFE over LWE (the DCR modulus only).

Fields, in wire order:

  • construction – record id (DMCFE_LWE_RECORD)

  • n2_prime_bits – int

  • n2_mod – decimal string

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'n2_prime_bits', 'n2_mod')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.MCFELWEEncryptionKey(raw)[source]

Bases: Record

Encryption key of an MCFE LWE client (the decentralised MCFE adds s2).

Fields, in wire order:

  • z – per slot, n0 + m0 decimal strings

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • s2 – dMCFE: the client’s key of the key derivation (decimal strings)

FIELDS: ClassVar[tuple[str, ...]] = ('z', 'label_hash', 's2')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.MCFELWEFunctionalKey(raw)[source]

Bases: Record

Functional key of the MCFE over LWE (also the combined key of the decentralised variant).

Fields, in wire order:

  • sk_y – n0 + m0 decimal strings

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.lwe.MCFELWECiphertext(raw)[source]

Bases: Record

Ciphertext of the MCFE over LWE: one element of Z_q0 per slot (ints) and the label hash code (none for shake256-wide; in an ndarray layer only its first element carries it).

Fields, in wire order:

  • c – ints

  • label_hash – int code; absent, code 0 (versions <= 0.3.0) for a single ciphertext and the layer’s code for an element of an ndarray layer (optional)

FIELDS: ClassVar[tuple[str, ...]] = ('c', 'label_hash')

Field names in wire order (set for every subclass).

The serialized objects of the Ring-LWE schemes: SIFE (pyfe4ai.schemes.sife.ring_lwe), SIFE FullySec (pyfe4ai.schemes.sife.fullysec_ring_lwe), and the MIFE / MCFE family over BMMS21 (pyfe4ai.schemes.mife.ring_lwe, pyfe4ai.schemes.mcfe.ring_lwe, its decentralised and threshold variants; the threshold key shares and partial decryptions are in pyfe4ai.core.formats.threshold).

Values are decimal strings unless a field says otherwise; a polynomial is a list of ring_n values, or (binary formats) bytes of ceil(bits(q) / 8)-byte words (pyfe4ai.core.formats.binary).

class pyfe4ai.core.formats.ring_lwe.SIFERingLWERecord(raw)[source]

Bases: Record

Parameter record of SIFE Ring-LWE (SIFE_RING_LWE/param.json).

Fields, in wire order:

  • param_version – record id (SIFE_RING_LWE_RECORD)

  • sec_param – int

  • eta – int

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • p – decimal string

  • q – decimal string

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • A_seed – hex seed of a

FIELDS: ClassVar[tuple[str, ...]] = ('param_version', 'sec_param', 'eta', 'ring_n', 'bound_x', 'bound_y', 'p', 'q', 'sigma1', 'sigma2', 'sigma3', 'A_seed')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.SIFERingLWEParameters(raw)[source]

Bases: Record

Public parameters of SIFE Ring-LWE.

Fields, in wire order:

  • A – the polynomial a (expanded)

  • p – decimal string

  • q – decimal string

  • eta – int

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • sec_param – int

  • gaussian_sampler – facct or rounded

  • security_profile – toy or standard

FIELDS: ClassVar[tuple[str, ...]] = ('A', 'p', 'q', 'eta', 'ring_n', 'bound_x', 'bound_y', 'sigma1', 'sigma2', 'sigma3', 'sec_param', 'gaussian_sampler', 'security_profile')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.SIFERingLWEEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE Ring-LWE.

Fields, in wire order:

  • pk – eta polynomials

FIELDS: ClassVar[tuple[str, ...]] = ('pk',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.SIFERingLWEFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE Ring-LWE.

Fields, in wire order:

  • sk_y – polynomial

  • y – the weights (ints)

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y', 'y')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.SIFERingLWECiphertext(raw)[source]

Bases: Record

Ciphertext of SIFE Ring-LWE (ct0: the eta slot polynomials pk_i r + f_i + Delta x_i; ct1: a r + e).

Fields, in wire order:

  • ct0 – eta polynomials

  • ct1 – polynomial

  • k – int, the batch length (columns of the plaintext)

FIELDS: ClassVar[tuple[str, ...]] = ('ct0', 'ct1', 'k')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.FullySecRingLWERecord(raw)[source]

Bases: Record

Parameter record of SIFE FullySec Ring-LWE (SIFE_FULLYSEC_RING_LWE/param.json).

Fields, in wire order:

  • param_version – record id (SIFE_FULLYSEC_RING_LWE_RECORD, or the packed one)

  • sec_param – int

  • eta – int

  • bound_x – decimal string

  • bound_y – decimal string

  • ring_n_config – the config’s ring_n (int, auto or null)

  • m_config – the config’s m

  • profile – security profile

  • ring_n – int

  • m – int

  • p – decimal string

  • q – decimal string

  • a_seed – hex seed of a

  • sigma – float

  • sigma_lhl – float

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • ndarray_layout – packed (only for that layout) (absent: ‘elementwise’)

FIELDS: ClassVar[tuple[str, ...]] = ('param_version', 'sec_param', 'eta', 'bound_x', 'bound_y', 'ring_n_config', 'm_config', 'profile', 'ring_n', 'm', 'p', 'q', 'a_seed', 'sigma', 'sigma_lhl', 'sigma1', 'sigma2', 'sigma3', 'ndarray_layout')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.FullySecRingLWEParameters(raw)[source]

Bases: Record

Public parameters of SIFE FullySec Ring-LWE.

Fields, in wire order:

  • a – m polynomials

  • p – decimal string

  • q – decimal string

  • ring_n – int

  • m – int

  • eta – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sigma2 – float

  • sigma3 – float

  • sec_param – int

  • gaussian_sampler – facct or rounded

  • security_profile – toy or standard

  • ndarray_layout – packed (only for that layout) (absent: ‘elementwise’)

FIELDS: ClassVar[tuple[str, ...]] = ('a', 'p', 'q', 'ring_n', 'm', 'eta', 'bound_x', 'bound_y', 'sigma2', 'sigma3', 'sec_param', 'gaussian_sampler', 'security_profile', 'ndarray_layout')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.FullySecRingLWEEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE FullySec Ring-LWE.

Fields, in wire order:

  • pk – eta polynomials

FIELDS: ClassVar[tuple[str, ...]] = ('pk',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.FullySecRingLWEFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE FullySec Ring-LWE.

Fields, in wire order:

  • sk_y – m polynomials

  • y – the weights (ints)

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y', 'y')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.FullySecRingLWECiphertext(raw)[source]

Bases: Record

Ciphertext of SIFE FullySec Ring-LWE (ct0: a r + f0; ct: the eta slots; k: the batch length of a packed ciphertext).

Fields, in wire order:

  • ct0 – m polynomials

  • ct – eta polynomials

  • k – int (packed layout only)

FIELDS: ClassVar[tuple[str, ...]] = ('ct0', 'ct', 'k')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.FullySecRingLWELayer(raw)[source]

Bases: Record

One packed ndarray layer of SIFE FullySec Ring-LWE (ndarray_layout = "packed"): chunk j holds elements j ring_n onward.

Fields, in wire order:

  • shape – list of ints

  • first_chunk – int, the chunks before this layer

  • chunks – packed ciphertexts (FullySecRingLWECiphertext with k)

FIELDS: ClassVar[tuple[str, ...]] = ('shape', 'first_chunk', 'chunks')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.RingLWERecord(raw)[source]

Bases: Record

Parameter record of the MIFE / MCFE Ring-LWE family (param.json; param-rns.json for an RNS modulus). The threshold MCFE adds the fields of ThresholdRingLWERecord.

Fields, in wire order:

  • construction – record id (RING_LWE_RECORD)

  • sec_param – int

  • eta – int

  • n – int, the number of slots

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • p – decimal string

  • q – decimal string (the threshold MCFE’s flooded modulus)

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • A_seed – hex seed of a

  • ring_modulus – rns (only for that modulus) (absent: ‘prime’)

  • q_factors – the factors of an RNS q (decimal strings) (optional)

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'sec_param', 'eta', 'n', 'ring_n', 'bound_x', 'bound_y', 'p', 'q', 'sigma1', 'sigma2', 'sigma3', 'A_seed', 'ring_modulus', 'q_factors')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.ThresholdRingLWERecord(raw)[source]

Bases: RingLWERecord

Parameter record of the threshold MCFE over Ring-LWE.

Fields, in wire order:

  • construction – record id (RING_LWE_RECORD)

  • sec_param – int

  • eta – int

  • n – int, the number of slots

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • p – decimal string

  • q – decimal string (the threshold MCFE’s flooded modulus)

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • A_seed – hex seed of a

  • ring_modulus – rns (only for that modulus) (absent: ‘prime’)

  • q_factors – the factors of an RNS q (decimal strings) (optional)

  • threshold_construction – construction id (TMCFE_RING_LWE_CONSTRUCTION_IDS)

  • s – int, the number of servers

  • stat_param – int

  • flooding_accounting – kl (only under that accounting) (absent: ‘per-sample’)

  • max_partial_decryptions – int (kl only) (optional)

  • flooding – uniform (uniform flooding only) (absent: ‘gaussian’)

  • flood_bits – int, the uniform flooding’s width

  • sigma_f – decimal string, the Gaussian flooding’s width

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'sec_param', 'eta', 'n', 'ring_n', 'bound_x', 'bound_y', 'p', 'q', 'sigma1', 'sigma2', 'sigma3', 'A_seed', 'ring_modulus', 'q_factors', 'threshold_construction', 's', 'stat_param', 'flooding_accounting', 'max_partial_decryptions', 'flooding', 'flood_bits', 'sigma_f')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.MIFERingLWEParameters(raw)[source]

Bases: Record

Public parameters of MIFE Ring-LWE.

Fields, in wire order:

  • A – the polynomial a (expanded)

  • p – decimal string

  • q – decimal string

  • eta – int

  • n – int, the number of slots

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • sec_param – int

  • gaussian_sampler – facct or rounded

  • security_profile – toy or standard

  • q_factors – the factors of an RNS q (decimal strings; RNS only) (optional)

FIELDS: ClassVar[tuple[str, ...]] = ('A', 'p', 'q', 'eta', 'n', 'ring_n', 'bound_x', 'bound_y', 'sigma1', 'sigma2', 'sigma3', 'sec_param', 'gaussian_sampler', 'security_profile', 'q_factors')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.MCFERingLWEParameters(raw)[source]

Bases: MIFERingLWEParameters

Public parameters of MCFE Ring-LWE.

Fields, in wire order:

  • A – the polynomial a (expanded)

  • p – decimal string

  • q – decimal string

  • eta – int

  • n – int, the number of slots

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • sec_param – int

  • gaussian_sampler – facct or rounded

  • security_profile – toy or standard

  • q_factors – the factors of an RNS q (decimal strings; RNS only) (optional)

  • label_hash – label hash mode (LABEL_HASHES) (absent: ‘shake256-wide’)

FIELDS: ClassVar[tuple[str, ...]] = ('A', 'p', 'q', 'eta', 'n', 'ring_n', 'bound_x', 'bound_y', 'sigma1', 'sigma2', 'sigma3', 'sec_param', 'gaussian_sampler', 'security_profile', 'q_factors', 'label_hash')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.DecentralizedRingLWEParameters(raw)[source]

Bases: MCFERingLWEParameters

Public parameters of the decentralised MCFE over Ring-LWE.

Fields, in wire order:

  • A – the polynomial a (expanded)

  • p – decimal string

  • q – decimal string

  • eta – int

  • n – int, the number of slots

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • sec_param – int

  • gaussian_sampler – facct or rounded

  • security_profile – toy or standard

  • q_factors – the factors of an RNS q (decimal strings; RNS only) (optional)

  • label_hash – label hash mode (LABEL_HASHES) (absent: ‘shake256-wide’)

  • lst_nid – the client ids

FIELDS: ClassVar[tuple[str, ...]] = ('A', 'p', 'q', 'eta', 'n', 'ring_n', 'bound_x', 'bound_y', 'sigma1', 'sigma2', 'sigma3', 'sec_param', 'gaussian_sampler', 'security_profile', 'q_factors', 'label_hash', 'lst_nid')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.ThresholdRingLWEParameters(raw)[source]

Bases: MCFERingLWEParameters

Public parameters of the threshold MCFE over Ring-LWE.

Fields, in wire order:

  • A – the polynomial a (expanded)

  • p – decimal string

  • q – decimal string

  • eta – int

  • n – int, the number of slots

  • ring_n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • sigma1 – float

  • sigma2 – float

  • sigma3 – float

  • sec_param – int

  • gaussian_sampler – facct or rounded

  • security_profile – toy or standard

  • q_factors – the factors of an RNS q (decimal strings; RNS only) (optional)

  • label_hash – label hash mode (LABEL_HASHES) (absent: ‘shake256-wide’)

  • s – int, the number of servers

  • t – int, the threshold

  • lst_sid – the server ids

  • flooding – uniform or gaussian (absent: ‘gaussian’)

  • sharing – shamir, replicated or replicated-seeded (absent: ‘shamir’)

  • threshold_construction – construction id (optional)

  • flood_bits – int, the uniform flooding’s width

  • sigma_f – decimal string, the Gaussian flooding’s width

  • ct_format – binary (only for that format) (absent: ‘json’)

  • flooding_accounting – kl (only under that accounting) (absent: ‘per-sample’)

  • max_partial_decryptions – int (kl only)

  • stat_param – int (kl only)

  • flood_tail_cut – int (kl only)

FIELDS: ClassVar[tuple[str, ...]] = ('A', 'p', 'q', 'eta', 'n', 'ring_n', 'bound_x', 'bound_y', 'sigma1', 'sigma2', 'sigma3', 'sec_param', 'gaussian_sampler', 'security_profile', 'q_factors', 'label_hash', 's', 't', 'lst_sid', 'flooding', 'sharing', 'threshold_construction', 'flood_bits', 'sigma_f', 'ct_format', 'flooding_accounting', 'max_partial_decryptions', 'stat_param', 'flood_tail_cut')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.MIFERingLWEEncryptionKey(raw)[source]

Bases: Record

Encryption key of a MIFE Ring-LWE slot.

Fields, in wire order:

  • pk – eta polynomials

  • u – eta polynomials, the slot’s pad

FIELDS: ClassVar[tuple[str, ...]] = ('pk', 'u')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.MCFERingLWEEncryptionKey(raw)[source]

Bases: MIFERingLWEEncryptionKey

Encryption key of an MCFE Ring-LWE client.

Fields, in wire order:

  • pk – eta polynomials

  • u – eta polynomials, the slot’s pad

  • u_prime – hex secret of the label pads

  • label_hash – label hash mode (absent: ‘shake256-wide’)

FIELDS: ClassVar[tuple[str, ...]] = ('pk', 'u', 'u_prime', 'label_hash')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.DecentralizedRingLWEEncryptionKey(raw)[source]

Bases: MCFERingLWEEncryptionKey

Encryption key of a client of the decentralised MCFE over Ring-LWE.

Fields, in wire order:

  • pk – eta polynomials

  • u – eta polynomials, the slot’s pad

  • u_prime – hex secret of the label pads

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • s – eta polynomials, the client’s IPFE secret

  • pair_keys – {other client: hex key}

FIELDS: ClassVar[tuple[str, ...]] = ('pk', 'u', 'u_prime', 'label_hash', 's', 'pair_keys')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.ThresholdRingLWEEncryptionKey(raw)[source]

Bases: MCFERingLWEEncryptionKey

Encryption key of a client of the threshold MCFE over Ring-LWE.

Fields, in wire order:

  • pk – eta polynomials

  • u – eta polynomials, the slot’s pad

  • u_prime – hex secret of the label pads

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • mac_keys – {server: hex key} of the ciphertext tags

FIELDS: ClassVar[tuple[str, ...]] = ('pk', 'u', 'u_prime', 'label_hash', 'mac_keys')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.MIFERingLWEFunctionalKey(raw)[source]

Bases: Record

Functional key of MIFE Ring-LWE.

Fields, in wire order:

  • sk_y – {client: polynomial}

  • z – polynomial

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y', 'z')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.MCFERingLWEFunctionalKey(raw)[source]

Bases: Record

Functional key of MCFE Ring-LWE, bound to a label (also the combined key of the decentralised variant).

Fields, in wire order:

  • sk_y – {client: polynomial}

  • z – polynomial, the term of the label itself

  • z_chunks – polynomials, the terms of the chunk labels

  • label – str, the label

  • label_hash – label hash mode (absent: ‘shake256-wide’)

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y', 'z', 'z_chunks', 'label', 'label_hash')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.DecentralizedRingLWEKeyShare(raw)[source]

Bases: Record

A client’s share of a functional key of the decentralised MCFE over Ring-LWE (derive_function_decryption_key_share()).

Fields, in wire order:

  • sk_y – polynomial, the client’s slot

  • z – polynomial

  • z_chunks – polynomials

  • label – str

  • nid – the client id (str or int)

  • weights_id – hex digest of the weights

  • label_hash – label hash mode (absent: ‘shake256-wide’)

FIELDS: ClassVar[tuple[str, ...]] = ('sk_y', 'z', 'z_chunks', 'label', 'nid', 'weights_id', 'label_hash')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.RingLWECiphertext(raw)[source]

Bases: Record

Ciphertext of the MIFE / MCFE Ring-LWE family: JSON (ct0, ct1) or binary (ct: format 1, or format 2 under binary threshold public parameters), the batch length, the label hash code (MCFE, none for shake256-wide) and the threshold MCFE’s tags.

Fields, in wire order:

  • ct0 – eta polynomials (JSON)

  • ct1 – polynomial (JSON)

  • ct – bytes (binary formats)

  • k – int, the batch length

  • label_hash – int code (LABEL_HASH_CODES); absent, code 0 (versions <= 0.3.0) for a single ciphertext and the layer’s code for a chunk of a packed layer (optional)

  • tags – {server: hex HMAC} (threshold MCFE)

FIELDS: ClassVar[tuple[str, ...]] = ('ct0', 'ct1', 'ct', 'k', 'label_hash', 'tags')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.ring_lwe.RingLWELayer(raw)[source]

Bases: Record

One layer of packed ndarray ciphertexts (MCFE Ring-LWE; SIFE FullySec Ring-LWE’s packed layer has no label_hash): chunk j holds elements j ring_n onward, under the chunk label first_chunk + j.

Fields, in wire order:

  • shape – list of ints

  • first_chunk – int, the chunks before this layer

  • chunks – ciphertexts (RingLWECiphertext)

  • label_hash – int code, the layer’s (absent: 0)

FIELDS: ClassVar[tuple[str, ...]] = ('shape', 'first_chunk', 'chunks', 'label_hash')

Field names in wire order (set for every subclass).

The serialized objects of the discrete-log and DCR schemes: DDH over Z_p^* (pyfe4ai.schemes.sife.ddh, ddh_dynamic, pyfe4ai.schemes.mife.ddh, pyfe4ai.schemes.mcfe.ddh and their threshold and decentralised variants), DDH over ristretto255, Damgard / MDDH and Paillier (DCR), and the key shares of the decentralised MCFE key derivation (ABMPSW20 Fig. 14) that the decentralised DDH, DCR and LWE schemes share. The threshold key shares and partial decryptions are in pyfe4ai.core.formats.threshold.

Values are decimal strings unless a field says otherwise; points of ristretto255 are 64-character hex strings.

class pyfe4ai.core.formats.dl.DLGroupRecord(raw)[source]

Bases: Record

The group of a DDH or Damgard parameter record (p = r q + 1).

Fields, in wire order:

  • p – decimal string, the modulus

  • q – decimal string, the subgroup order

  • r – decimal string, the cofactor (DDH records: 2)

FIELDS: ClassVar[tuple[str, ...]] = ('p', 'q', 'r')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.DDHRecord(raw)[source]

Bases: Record

Parameter record of the DDH schemes over Z_p^* (SIFE, MIFE, MCFE and their threshold and decentralised variants).

Fields, in wire order:

  • sec_param – int, the bits of p

  • g – decimal string, the generator

  • eta – int (or per client)

  • group – DLGroupRecord

  • n – int, the number of clients (MIFE, MCFE)

  • s – the number of servers (MIFE, MCFE; tMCFE)

  • t – int, the threshold (tMCFE)

  • construction – record id (tMCFE TMCFE_DDH_RECORD, dMCFE DMCFE_DDH_RECORD)

  • n2_prime_bits – int (dMCFE)

  • n2_mod – decimal string, the DCR modulus of the key derivation (dMCFE)

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'g', 'eta', 'group', 'n', 's', 't', 'construction', 'n2_prime_bits', 'n2_mod')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.DamgardRecord(raw)[source]

Bases: Record

Parameter record of SIFE and MIFE Damgard.

Fields, in wire order:

  • sec_param – int

  • eta – int

  • modulus_length – int

  • bound – int

  • group – DLGroupRecord (p and q)

  • g – decimal string

  • h_seed – hex seed of h

  • n – int, the number of slots (MIFE)

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'eta', 'modulus_length', 'bound', 'group', 'g', 'h_seed', 'n')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEDamgardRecord(raw)[source]

Bases: Record

Parameter record of MCFE Damgard (MDDH).

Fields, in wire order:

  • construction – record id (MCFE_DAMGARD_RECORD)

  • modulus_length – int

  • p – decimal string

  • q – decimal string

  • g – decimal string

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'modulus_length', 'p', 'q', 'g')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEPaillierRecord(raw)[source]

Bases: Record

Parameter record of SIFE Paillier (the factors are never stored).

Fields, in wire order:

  • sec_param – int

  • eta – int

  • bit_length – int

  • bound_x – int

  • bound_y – int

  • param_format – record format (PAILLIER_RECORD)

  • n – decimal string, the modulus N

  • n_square – decimal string

  • g_seed – hex seed of g

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'eta', 'bit_length', 'bound_x', 'bound_y', 'param_format', 'n', 'n_square', 'g_seed')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEPaillierRecord(raw)[source]

Bases: Record

Parameter record of MIFE Paillier.

Fields, in wire order:

  • sec_param – int

  • eta – int

  • n – int, the number of slots

  • bit_length – int

  • bound_x – int

  • bound_y – int

  • param_format – record format (PAILLIER_RECORD)

  • n_mod – decimal string, the modulus N

  • n_square – decimal string

  • g_seed – hex seed of g

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'eta', 'n', 'bit_length', 'bound_x', 'bound_y', 'param_format', 'n_mod', 'n_square', 'g_seed')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEPaillierRecord(raw)[source]

Bases: Record

Parameter record of MCFE Paillier and of the decentralised MCFE over DCR.

Fields, in wire order:

  • construction – record id (MCFE_PAILLIER_RECORD or the dMCFE one)

  • bit_length – int

  • n2_prime_bits – int (dMCFE)

  • n_mod – decimal string, the modulus N

  • n2_mod – decimal string, the DCR modulus of the key derivation (dMCFE)

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'bit_length', 'n2_prime_bits', 'n_mod', 'n2_mod')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEDDHParameters(raw)[source]

Bases: Record

Public parameters of SIFE DDH.

Fields, in wire order:

  • g – decimal string

  • p – decimal string

  • eta – int

  • sec_param – int

FIELDS: ClassVar[tuple[str, ...]] = ('g', 'p', 'eta', 'sec_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEDDHEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE DDH: g^{s_i}.

Fields, in wire order:

  • gs – eta decimal strings

FIELDS: ClassVar[tuple[str, ...]] = ('gs',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEDDHFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE DDH (ddh_dynamic adds size).

Fields, in wire order:

  • z – decimal string, <s, y> mod q

  • y – the weights (ints)

  • size – int, the number of weights (ddh_dynamic)

FIELDS: ClassVar[tuple[str, ...]] = ('z', 'y', 'size')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEDDHCiphertext(raw)[source]

Bases: Record

Ciphertext of SIFE DDH (also SIFE DDH over ristretto255, with points).

Fields, in wire order:

  • ct0 – g^r

  • ct1 – g^{x_i} gs_i^r

FIELDS: ClassVar[tuple[str, ...]] = ('ct0', 'ct1')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEDDHParameters(raw)[source]

Bases: Record

Public parameters of MIFE DDH (the threshold MIFE adds t, s and lst_sid).

Fields, in wire order:

  • construction – public id (MIFE_DDH_CONSTRUCTION; not checked)

  • g – decimal string

  • p – decimal string

  • q – decimal string

  • n – int

  • eta – int (or per client)

  • lst_nid – the client ids

  • sec_param – int

  • t – int (tMIFE)

  • s – int (tMIFE)

  • lst_sid – the server ids (tMIFE)

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'g', 'p', 'q', 'n', 'eta', 'lst_nid', 'sec_param', 't', 's', 'lst_sid')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEDDHEncryptionKey(raw)[source]

Bases: Record

Encryption key of a MIFE DDH slot (ristretto255: points and scalars).

Fields, in wire order:

  • h – g^{s_j}

  • u – the slot’s pad

FIELDS: ClassVar[tuple[str, ...]] = ('h', 'u')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEDDHFunctionalKey(raw)[source]

Bases: Record

Functional key of MIFE DDH (also over ristretto255).

Fields, in wire order:

  • d – {slot: <s_i, y_i>}

  • z – the pad term

  • weights_id – hex digest of the weights

FIELDS: ClassVar[tuple[str, ...]] = ('d', 'z', 'weights_id')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEDDHCiphertext(raw)[source]

Bases: Record

Ciphertext of MIFE DDH (also over ristretto255).

Fields, in wire order:

  • t – g^r

  • c – the slot values

FIELDS: ClassVar[tuple[str, ...]] = ('t', 'c')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEDDHParameters(raw)[source]

Bases: Record

Public parameters of MCFE DDH (the decentralised MCFE adds its fields).

Fields, in wire order:

  • g – decimal string

  • p – decimal string

  • n – int

  • eta – int (or per client)

  • sec_param – int

  • n2_mod – decimal string (dMCFE)

  • lst_nid – the client ids (dMCFE)

  • contribution_bound – decimal string (dMCFE)

  • mask_bits – int (dMCFE)

FIELDS: ClassVar[tuple[str, ...]] = ('g', 'p', 'n', 'eta', 'sec_param', 'n2_mod', 'lst_nid', 'contribution_bound', 'mask_bits')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.TMCFEDDHParameters(raw)[source]

Bases: Record

Public parameters of the threshold MCFE over DDH.

Fields, in wire order:

  • p – decimal string

  • g – decimal string

  • eta – int

  • s – int

  • t – int

  • n – int

  • sec_param – int

FIELDS: ClassVar[tuple[str, ...]] = ('p', 'g', 'eta', 's', 't', 'n', 'sec_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEDDHEncryptionKey(raw)[source]

Bases: Record

Encryption key of an MCFE DDH client (also MCFE Damgard, Paillier and ristretto255; the decentralised MCFE adds s2 and mask_key).

Fields, in wire order:

  • s – per slot, the client’s secret

  • s2 – dMCFE: the client’s key of the key derivation

  • mask_key – dMCFE DDH: hex key of the carry masks

FIELDS: ClassVar[tuple[str, ...]] = ('s', 's2', 'mask_key')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.PreparedKey(raw)[source]

Bases: Record

A functional key of the element-wise MCFE schemes as prepare_key() returns it: the key’s fields, then key_terms (an in-process object, never serialised).

Fields, in wire order:

  • key_terms – the prepared key terms (in process only)

FIELDS: ClassVar[tuple[str, ...]] = ('key_terms',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEDDHFunctionalKey(raw)[source]

Bases: PreparedKey

Functional key of MCFE DDH and MCFE Damgard.

Fields, in wire order:

  • d – decimal strings

  • key_terms – the prepared key terms (in process only)

FIELDS: ClassVar[tuple[str, ...]] = ('d', 'key_terms')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEPaillierFunctionalKey(raw)[source]

Bases: PreparedKey

Functional key of MCFE Paillier and of the decentralised MCFE over DCR.

Fields, in wire order:

  • k – decimal string (over Z)

  • key_terms – the prepared key terms (in process only)

FIELDS: ClassVar[tuple[str, ...]] = ('k', 'key_terms')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEDDHCiphertext(raw)[source]

Bases: Record

Ciphertext of the element-wise MCFE schemes (DDH, ristretto255, Damgard, Paillier): one value per slot; the threshold MCFE adds the encoded label.

Fields, in wire order:

  • c – one value per slot

  • label – tMCFE DDH: the encoded label

FIELDS: ClassVar[tuple[str, ...]] = ('c', 'label')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.RistrettoParameters(raw)[source]

Bases: Record

Public parameters of the ristretto255 schemes (MIFE adds its id and clients).

Fields, in wire order:

  • construction – MIFE: public id (not checked)

  • group – ristretto255

  • n – int (MIFE, MCFE)

  • eta – int (or per client)

  • lst_nid – the client ids (MIFE)

FIELDS: ClassVar[tuple[str, ...]] = ('construction', 'group', 'n', 'eta', 'lst_nid')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFERistrettoEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE DDH over ristretto255.

Fields, in wire order:

  • h – eta points

FIELDS: ClassVar[tuple[str, ...]] = ('h',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEDamgardParameters(raw)[source]

Bases: Record

Public parameters of SIFE and MIFE Damgard.

Fields, in wire order:

  • p – decimal string

  • q – decimal string

  • g – decimal string

  • h – decimal string

  • eta – int

  • n – int (MIFE)

  • bound – int

  • sec_param – int

  • modulus_length – int

FIELDS: ClassVar[tuple[str, ...]] = ('p', 'q', 'g', 'h', 'eta', 'n', 'bound', 'sec_param', 'modulus_length')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.DamgardEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE / MIFE Damgard (MIFE adds the pad u).

Fields, in wire order:

  • pk – decimal strings

  • u – MIFE: the slot’s pad

FIELDS: ClassVar[tuple[str, ...]] = ('pk', 'u')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEDamgardFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE Damgard.

Fields, in wire order:

  • k1 – decimal string

  • k2 – decimal string

  • y – the weights (ints)

FIELDS: ClassVar[tuple[str, ...]] = ('k1', 'k2', 'y')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEDamgardFunctionalKey(raw)[source]

Bases: Record

Functional key of MIFE Damgard.

Fields, in wire order:

  • k1 – {slot: decimal string}

  • k2 – {slot: decimal string}

  • z – decimal string, the pad term

FIELDS: ClassVar[tuple[str, ...]] = ('k1', 'k2', 'z')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.DamgardCiphertext(raw)[source]

Bases: Record

Ciphertext of SIFE / MIFE Damgard.

Fields, in wire order:

  • c – g^r

  • d – h^r

  • e – the slot values

FIELDS: ClassVar[tuple[str, ...]] = ('c', 'd', 'e')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEDamgardParameters(raw)[source]

Bases: Record

Public parameters of MCFE Damgard (MDDH).

Fields, in wire order:

  • p – decimal string

  • q – decimal string

  • g – decimal string

  • mddh_k – int

  • eta – int

  • n – int

  • bound – int

  • sec_param – int

  • modulus_length – int

FIELDS: ClassVar[tuple[str, ...]] = ('p', 'q', 'g', 'mddh_k', 'eta', 'n', 'bound', 'sec_param', 'modulus_length')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEPaillierParameters(raw)[source]

Bases: Record

Public parameters of SIFE Paillier.

Fields, in wire order:

  • n – decimal string, the modulus N

  • n_square – decimal string

  • g – decimal string

  • eta – int

  • sec_param – int

  • bit_length – int

  • bound_x – int

  • bound_y – int

FIELDS: ClassVar[tuple[str, ...]] = ('n', 'n_square', 'g', 'eta', 'sec_param', 'bit_length', 'bound_x', 'bound_y')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEPaillierParameters(raw)[source]

Bases: Record

Public parameters of MIFE Paillier.

Fields, in wire order:

  • n_mod – decimal string, the modulus N

  • n_square – decimal string

  • g – decimal string

  • eta – int

  • n – int, the number of slots

  • sec_param – int

  • bit_length – int

  • bound_x – int

  • bound_y – int

FIELDS: ClassVar[tuple[str, ...]] = ('n_mod', 'n_square', 'g', 'eta', 'n', 'sec_param', 'bit_length', 'bound_x', 'bound_y')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFEPaillierParameters(raw)[source]

Bases: Record

Public parameters of MCFE Paillier (the decentralised MCFE adds its fields).

Fields, in wire order:

  • n_mod – decimal string, the modulus N

  • n_square – decimal string

  • eta – int

  • n – int

  • sec_param – int

  • bit_length – int

  • bound_x – int

  • bound_y – int

  • n2_mod – decimal string (dMCFE)

  • lst_nid – the client ids (dMCFE)

  • contribution_bound – decimal string (dMCFE)

FIELDS: ClassVar[tuple[str, ...]] = ('n_mod', 'n_square', 'eta', 'n', 'sec_param', 'bit_length', 'bound_x', 'bound_y', 'n2_mod', 'lst_nid', 'contribution_bound')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.PaillierEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE / MIFE Paillier (MIFE adds the pad u).

Fields, in wire order:

  • pk – decimal strings in Z_{N^2}

  • u – MIFE: the slot’s pad

FIELDS: ClassVar[tuple[str, ...]] = ('pk', 'u')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.SIFEPaillierFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE Paillier.

Fields, in wire order:

  • k – decimal string, <s, y> over Z

FIELDS: ClassVar[tuple[str, ...]] = ('k',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MIFEPaillierFunctionalKey(raw)[source]

Bases: Record

Functional key of MIFE Paillier.

Fields, in wire order:

  • k – {slot: decimal string} over Z

  • z – decimal string, the pad term mod N

FIELDS: ClassVar[tuple[str, ...]] = ('k', 'z')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.PaillierCiphertext(raw)[source]

Bases: Record

Ciphertext of SIFE / MIFE Paillier.

Fields, in wire order:

  • ct0 – g^r

  • ct1 – the slot values

FIELDS: ClassVar[tuple[str, ...]] = ('ct0', 'ct1')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.dl.MCFE2KeyShare(raw)[source]

Bases: Record

A client’s share of a functional key of the decentralised MCFE (pyfe4ai.schemes.mcfe.decentralize): its contribution encrypted under the MCFE2 key.

Fields, in wire order:

  • c – decimal strings, the MCFE2 ciphertexts of the contribution

  • nid – the client id (str or int)

  • weights_id – hex digest of the weights

FIELDS: ClassVar[tuple[str, ...]] = ('c', 'nid', 'weights_id')

Field names in wire order (set for every subclass).

The serialized objects of the pairing schemes: function-hiding IPFE (pyfe4ai.schemes.sife.fh_ipe_pairing), partially function-hiding IPFE (pyfe4ai.schemes.sife.part_fh_ipe_pairing), the function-hiding MIFE (pyfe4ai.schemes.mife.fh_ipe_pairing, pyfe4ai.schemes.mife.fh_multi_ipe_pairing), the function-hiding MCFE (pyfe4ai.schemes.mcfe.fh_multi_ipe_pairing and its threshold and decentralised variants; the threshold key shares and partial decryptions are in pyfe4ai.core.formats.threshold) and the quadratic schemes (pyfe4ai.schemes.quadratic).

Group elements are serialised strings (group.serialize(e).decode("utf-8")); scalars are decimal strings unless a field says otherwise.

class pyfe4ai.core.formats.pairing.SIFEFHIPERecord(raw)[source]

Bases: Record

Parameter record of SIFE FH-IPE (the configuration only; no group elements).

Fields, in wire order:

  • sec_param – int

  • eta – int

  • bound_x – decimal string

  • bound_y – decimal string

  • pairing_group_param – the pairing group

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'eta', 'bound_x', 'bound_y', 'pairing_group_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SIFEFHIPEParameters(raw)[source]

Bases: Record

Public parameters of SIFE FH-IPE.

Fields, in wire order:

  • eta – int

  • bound_x – decimal string

  • bound_y – decimal string

  • pairing_group_param – the pairing group

FIELDS: ClassVar[tuple[str, ...]] = ('eta', 'bound_x', 'bound_y', 'pairing_group_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SIFEFHIPEEncryptionKey(raw)[source]

Bases: Record

Encryption key of SIFE FH-IPE (equivalent to the master secret key).

Fields, in wire order:

  • g2 – G2

  • b_star – (eta + 2) x (eta + 2) matrix of decimal strings

FIELDS: ClassVar[tuple[str, ...]] = ('g2', 'b_star')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SIFEFHIPEFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE FH-IPE (no weights: function hiding).

Fields, in wire order:

  • k1 – G1

  • k2 – eta + 2 G1 elements

FIELDS: ClassVar[tuple[str, ...]] = ('k1', 'k2')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SIFEFHIPECiphertext(raw)[source]

Bases: Record

Ciphertext of SIFE FH-IPE.

Fields, in wire order:

  • c1 – G2

  • c2 – eta + 2 G2 elements

FIELDS: ClassVar[tuple[str, ...]] = ('c1', 'c2')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.PartFHIPERecord(raw)[source]

Bases: Record

Parameter record of SIFE partially FH-IPE (the configuration only).

Fields, in wire order:

  • sec_param – int

  • eta – int

  • bound – decimal string

  • subspace_dim – int, k

  • coeff_bound – decimal string

  • pairing_group_param – the pairing group

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'eta', 'bound', 'subspace_dim', 'coeff_bound', 'pairing_group_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.PartFHIPEParameters(raw)[source]

Bases: Record

Public parameters of SIFE partially FH-IPE (the public key included).

Fields, in wire order:

  • eta – int

  • bound – decimal string

  • subspace_dim – int, k

  • coeff_bound – decimal string

  • pairing_group_param – the pairing group

  • g1 – G1

  • g2 – G2

  • a – two G1 elements

  • ua – eta + 2 G1 elements

  • vt_m – 2 x k matrix of decimal strings

  • m – eta x k matrix of decimal strings

FIELDS: ClassVar[tuple[str, ...]] = ('eta', 'bound', 'subspace_dim', 'coeff_bound', 'pairing_group_param', 'g1', 'g2', 'a', 'ua', 'vt_m', 'm')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.PartFHIPEFunctionalKey(raw)[source]

Bases: Record

Functional key of SIFE partially FH-IPE.

Fields, in wire order:

  • k – eta + 4 G2 elements

FIELDS: ClassVar[tuple[str, ...]] = ('k',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.PartFHIPECiphertext(raw)[source]

Bases: Record

Ciphertext of SIFE partially FH-IPE (Enc and Enc').

Fields, in wire order:

  • ct – eta + 4 G1 elements

FIELDS: ClassVar[tuple[str, ...]] = ('ct',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.FHParameters(raw)[source]

Bases: Record

Public parameters of the function-hiding MIFE (ACFGU18) and MCFE (AGT21b).

Fields, in wire order:

  • pairing_group_param – the pairing group

  • g1 – G1

  • g2 – G2

  • eta – int

  • n – int

  • lst_nid – the client ids

  • bound_x – int

  • bound_y – int

  • sec_param – int

FIELDS: ClassVar[tuple[str, ...]] = ('pairing_group_param', 'g1', 'g2', 'eta', 'n', 'lst_nid', 'bound_x', 'bound_y', 'sec_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.TMCFEFHParameters(raw)[source]

Bases: FHParameters

Public parameters of the threshold FH-MCFE.

Fields, in wire order:

  • pairing_group_param – the pairing group

  • g1 – G1

  • g2 – G2

  • eta – int

  • n – int

  • lst_nid – the client ids

  • bound_x – int

  • bound_y – int

  • sec_param – int

  • s – int

  • t – int

  • lst_sid – the server ids

FIELDS: ClassVar[tuple[str, ...]] = ('pairing_group_param', 'g1', 'g2', 'eta', 'n', 'lst_nid', 'bound_x', 'bound_y', 'sec_param', 's', 't', 'lst_sid')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.FHMasterKey(raw)[source]

Bases: Record

A slot’s FH-IPFE master key as a client holds it (imsk; integers as decimal strings). Clients of the MIFE and MCFE get it without a_out, which only key generation needs.

Fields, in wire order:

  • a_in – two decimal strings

  • u – rows of two decimal strings

  • w – rows of two decimal strings

  • z – decimal string

  • a_out – two decimal strings (decentralised MCFE only)

FIELDS: ClassVar[tuple[str, ...]] = ('a_in', 'u', 'w', 'z', 'a_out')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.FHClientKey(raw)[source]

Bases: Record

Encryption key of a client of the function-hiding MIFE / MCFE.

Fields, in wire order:

  • imsk – FHMasterKey

  • mac_keys – tMCFE: {server: hex key} of the ciphertext tags

  • t_tilde – dMCFE: the client’s share of zero (decimal string)

  • seed – dMCFE: 64-char hex seed of the key derivation

FIELDS: ClassVar[tuple[str, ...]] = ('imsk', 'mac_keys', 't_tilde', 'seed')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIFEFHIPEFunctionalKey(raw)[source]

Bases: Record

Functional key of the function-hiding MIFE (ACFGU18 Fig. 12).

Fields, in wire order:

  • dk – {slot: FH-IPFE key (G2 elements)}

  • z – GT, [r sum z_i]_T

  • key_id – 32-char hex, random

FIELDS: ClassVar[tuple[str, ...]] = ('dk', 'z', 'key_id')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.FHKeyEntry(raw)[source]

Bases: Record

A client’s part of a functional key of the FH-MCFE (also a client’s key share of the decentralised FH-MCFE, which adds nid and tag_f).

Fields, in wire order:

  • k – G2 elements

  • z – GT

  • nid – dMCFE: the client

  • tag_f – dMCFE: the function tag

FIELDS: ClassVar[tuple[str, ...]] = ('k', 'z', 'nid', 'tag_f')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MCFEFHFunctionalKey(raw)[source]

Bases: Record

Functional key of the FH-MCFE (the decentralised MCFE’s combined key has tag_f and no key_id).

Fields, in wire order:

  • dk – {client: FHKeyEntry}

  • key_id – 32-char hex, random

  • tag_f – dMCFE: the function tag

FIELDS: ClassVar[tuple[str, ...]] = ('dk', 'key_id', 'tag_f')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.FHCiphertext(raw)[source]

Bases: Record

Ciphertext of the function-hiding MIFE / MCFE schemes (the threshold FH-MCFE adds the encoded label and the server tags).

Fields, in wire order:

  • ct – G1 elements

  • label – tMCFE: the encoded label

  • tags – tMCFE: {server: hex HMAC}

FIELDS: ClassVar[tuple[str, ...]] = ('ct', 'label', 'tags')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIFEFHMultiIPERecord(raw)[source]

Bases: Record

Parameter record of the full-hiding MIFE (DOT18; the configuration only).

Fields, in wire order:

  • sec_param – int

  • sec_level – int

  • eta – int

  • n – int

  • bound_x – decimal string

  • bound_y – decimal string

  • pairing_group_param – the pairing group

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'sec_level', 'eta', 'n', 'bound_x', 'bound_y', 'pairing_group_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIFEFHMultiIPEParameters(raw)[source]

Bases: Record

Public parameters of the full-hiding MIFE (DOT18).

Fields, in wire order:

  • sec_level – int

  • eta – int

  • n – int

  • lst_nid – the client ids

  • bound_x – decimal string

  • bound_y – decimal string

  • pairing_group_param – the pairing group

  • g1 – G1

  • g2 – G2

  • pub – GT

FIELDS: ClassVar[tuple[str, ...]] = ('sec_level', 'eta', 'n', 'lst_nid', 'bound_x', 'bound_y', 'pairing_group_param', 'g1', 'g2', 'pub')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIFEFHMultiIPEEncryptionKey(raw)[source]

Bases: Record

Encryption key of a slot of the full-hiding MIFE.

Fields, in wire order:

  • bhat – (eta + k + 1) x dim matrix of decimal strings

FIELDS: ClassVar[tuple[str, ...]] = ('bhat',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIFEFHMultiIPEFunctionalKey(raw)[source]

Bases: Record

Functional key of the full-hiding MIFE.

Fields, in wire order:

  • dk – {slot: G2 elements}

FIELDS: ClassVar[tuple[str, ...]] = ('dk',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.QuadIPFEPublicKey(raw)[source]

Bases: Record

The public key of the IPFE inside Quad (Gay20 Fig. 4).

Fields, in wire order:

  • a – two G1 elements

  • ua – G1 elements

  • vt_m – rows of G1 elements

  • m – rows of G1 elements

FIELDS: ClassVar[tuple[str, ...]] = ('a', 'ua', 'vt_m', 'm')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.QuadParameters(raw)[source]

Bases: Record

Public parameters (the public key) of Quad.

Fields, in wire order:

  • pairing_group_param – the pairing group

  • n – int

  • m – int

  • bound – int

  • sec_param – int

  • g1 – G1

  • g2 – G2

  • ua – n G1 elements

  • vb – m x 2 G2 elements

  • ipfe – QuadIPFEPublicKey

FIELDS: ClassVar[tuple[str, ...]] = ('pairing_group_param', 'n', 'm', 'bound', 'sec_param', 'g1', 'g2', 'ua', 'vb', 'ipfe')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.QuadFunctionalKey(raw)[source]

Bases: Record

Functional key of Quad.

Fields, in wire order:

  • f – n x m matrix of decimal strings

  • k – 2 m + 3 n + 4 G2 elements

FIELDS: ClassVar[tuple[str, ...]] = ('f', 'k')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.QuadCiphertext(raw)[source]

Bases: Record

Ciphertext of Quad.

Fields, in wire order:

  • ct_x – n G1 elements

  • ct_y – m G2 elements

  • ct – 2 m + 3 n + 4 G1 elements

FIELDS: ClassVar[tuple[str, ...]] = ('ct_x', 'ct_y', 'ct')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SGPRecord(raw)[source]

Bases: Record

Parameter record of SGP (DSGPP18; the configuration only).

Fields, in wire order:

  • sec_param – int

  • n – int

  • bound – decimal string

  • pairing_group_param – the pairing group

FIELDS: ClassVar[tuple[str, ...]] = ('sec_param', 'n', 'bound', 'pairing_group_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SGPParameters(raw)[source]

Bases: Record

Public parameters (the public key) of SGP.

Fields, in wire order:

  • n – int

  • bound – decimal string

  • pairing_group_param – the pairing group

  • g1 – G1

  • g2 – G2

  • g1_s – n G1 elements

  • g2_t – n G2 elements

FIELDS: ClassVar[tuple[str, ...]] = ('n', 'bound', 'pairing_group_param', 'g1', 'g2', 'g1_s', 'g2_t')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SGPFunctionalKey(raw)[source]

Bases: Record

Functional key of SGP.

Fields, in wire order:

  • key – G2

  • f – n x n matrix of decimal strings

FIELDS: ClassVar[tuple[str, ...]] = ('key', 'f')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.SGPCiphertext(raw)[source]

Bases: Record

Ciphertext of SGP.

Fields, in wire order:

  • c0 – G1

  • a – n x 2 G1 elements

  • b – n x 2 G2 elements

FIELDS: ClassVar[tuple[str, ...]] = ('c0', 'a', 'b')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIQFEParameters(raw)[source]

Bases: Record

Public parameters of the multi-input quadratic FE (AGT22).

Fields, in wire order:

  • pairing_group_param – the pairing group

  • g1 – G1

  • g2 – G2

  • n – int, the number of users

  • m – int, each user’s input length

  • mddh_k – int

  • lst_nid – the user ids

  • bound_x – int

  • bound_c – int

  • sec_param – int

FIELDS: ClassVar[tuple[str, ...]] = ('pairing_group_param', 'g1', 'g2', 'n', 'm', 'mddh_k', 'lst_nid', 'bound_x', 'bound_c', 'sec_param')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIQFECiphertext(raw)[source]

Bases: Record

A master ciphertext MstEnc of the multi-input quadratic FE, and a user’s ciphertext (their combination, the same layout).

Fields, in wire order:

  • ct – m rows of G1 elements

  • sk – m rows of G2 elements

  • ct2 – G1 elements

  • sk2 – G2 elements

  • mg_ct – G1 elements

  • mg_sk – G2 elements

FIELDS: ClassVar[tuple[str, ...]] = ('ct', 'sk', 'ct2', 'sk2', 'mg_ct', 'mg_sk')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIQFEEncryptionKey(raw)[source]

Bases: Record

Encryption key EK_i of a user: master ciphertexts only.

Fields, in wire order:

FIELDS: ClassVar[tuple[str, ...]] = ('mct1', 'mct0')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.pairing.MIQFEFunctionalKey(raw)[source]

Bases: Record

Functional key of the multi-input quadratic FE.

Fields, in wire order:

  • c – nm x nm matrix of decimal strings

  • mg_sk – n rows of G2 elements

  • mg_ct – n rows of G1 elements

  • sigma – n x n matrix of decimal strings

FIELDS: ClassVar[tuple[str, ...]] = ('c', 'mg_sk', 'mg_ct', 'sigma')

Field names in wire order (set for every subclass).

The serialized objects of the threshold schemes: key shares (whole, and the weight and label parts of the threshold MCFE over Ring-LWE), the pieces of the replicated sharings, and partial decryptions.

ThresholdKeyShare and PartialDecryption are the views the shared threshold code (pyfe4ai.schemes.threshold) reads any scheme’s key shares and partials through; the other classes are the layouts of each scheme. A key share of the replicated sharings holds sharing and pieces (and, seeded, seeds and layout) in place of the shared values; one of the Shamir sharing holds the values (sk_y, z, …).

class pyfe4ai.core.formats.threshold.KeyPiece(raw)[source]

Bases: Record

A piece r_T of a replicated sharing, as a server holds it.

Fields, in wire order:

  • set – the index set T (sorted server points)

  • share – the piece: the shared material’s structure (sk_y, z, …)

FIELDS: ClassVar[tuple[str, ...]] = ('set', 'share')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.KeySeed(raw)[source]

Bases: Record

The seed of a piece of the seed-expanded replicated sharing.

Fields, in wire order:

  • set – the index set T

  • seed – 32-byte hex seed

FIELDS: ClassVar[tuple[str, ...]] = ('set', 'seed')

Field names in wire order (set for every subclass).

pyfe4ai.core.formats.threshold.PIECE_FIELDS = ('pieces', 'seeds', 'layout')

The fields of a key share that hold the pieces of a replicated sharing.

class pyfe4ai.core.formats.threshold.ThresholdKeyShare(raw)[source]

Bases: Record

Any threshold key share, as the shared server code reads it (the fields of every scheme’s key share that the checks and the sums of pyfe4ai.schemes.threshold use).

Fields, in wire order:

  • sharing – replicated or replicated-seeded (Shamir key shares have none) (absent: ‘shamir’)

  • pieces – replicated: the server’s pieces (KeyPiece)

  • seeds – seeded: the seeds of the other pieces (KeySeed)

  • layout – seeded: the layout of a piece

  • sk_y – the shared key of the weights (LWE, Ring-LWE)

  • z – the shared term of the key (LWE, Ring-LWE: of the label; DDH, FH)

  • z_chunks – tMCFE-Ring-LWE: the shared terms of the chunk labels

  • d – DDH: the shared key

  • k – FH: the shared key in the exponent

  • part – tMCFE-Ring-LWE: weights or label (whole key shares have none) (optional)

  • share_set_id – tMCFE-Ring-LWE: the weight part’s sharing

  • sharing_id – tMCFE-Ring-LWE: this sharing (32-char hex) (optional)

  • label – the label (tMCFE-Ring-LWE)

  • noise_key – hex key of the server’s flooding noise

  • sid – the server id (str or int)

  • lst_sid – the server ids

  • weights_id – hex digest of the weights

  • key_id – hex id of the sharing (tMCFE FH)

  • mac_keys – {client: hex key} of the ciphertext tags

  • noise_version – int, the flooding derivation (absent: 1)

  • noise_sampler – the flooding sampler

  • flooding – uniform or gaussian (absent: ‘gaussian’)

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • pp_binding – hex digest of the public parameters it was issued for

without_pieces()[source]

The key share’s other fields (a new dict, in their order).

Return type:

dict

FIELDS: ClassVar[tuple[str, ...]] = ('sharing', 'pieces', 'seeds', 'layout', 'sk_y', 'z', 'z_chunks', 'd', 'k', 'part', 'share_set_id', 'sharing_id', 'label', 'noise_key', 'sid', 'lst_sid', 'weights_id', 'key_id', 'mac_keys', 'noise_version', 'noise_sampler', 'flooding', 'label_hash', 'pp_binding')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMIFELWEKeyShare(raw)[source]

Bases: Record

Key share of the threshold MIFE over LWE (pyfe4ai.schemes.mife.lwe_threshold).

Fields, in wire order:

  • sharing – replicated sharings only (absent: ‘shamir’)

  • pieces – replicated: KeyPiece of {sk_y, z}

  • seeds – seeded: KeySeed

  • layout – seeded: the piece layout

  • sk_y – Shamir: {client: decimal strings}

  • noise_key – hex key of the flooding noise

  • z – Shamir: decimal string

  • noise_version – int (absent: 1)

  • noise_sampler – the flooding sampler

  • sid – the server id (str or int)

  • lst_sid – server ids

  • weights_id – hex digest of the weights

  • mac_keys – {client: hex key}

  • pp_binding – hex digest

FIELDS: ClassVar[tuple[str, ...]] = ('sharing', 'pieces', 'seeds', 'layout', 'sk_y', 'noise_key', 'z', 'noise_version', 'noise_sampler', 'sid', 'lst_sid', 'weights_id', 'mac_keys', 'pp_binding')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFELWEKeyShare(raw)[source]

Bases: Record

Key share of the threshold MCFE over LWE (pyfe4ai.schemes.mcfe.lwe_threshold).

Fields, in wire order:

  • sharing – replicated sharings only (absent: ‘shamir’)

  • pieces – replicated: KeyPiece of {sk_y}

  • seeds – seeded: KeySeed

  • layout – seeded: the piece layout

  • sk_y – Shamir: decimal strings

  • sid – the server id (str or int)

  • lst_sid – server ids

  • weights_id – hex digest of the weights

  • noise_key – hex key of the flooding noise

  • noise_version – int (absent: 1)

  • noise_sampler – the flooding sampler

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • pp_binding – hex digest

FIELDS: ClassVar[tuple[str, ...]] = ('sharing', 'pieces', 'seeds', 'layout', 'sk_y', 'sid', 'lst_sid', 'weights_id', 'noise_key', 'noise_version', 'noise_sampler', 'label_hash', 'pp_binding')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFERingLWEKeyShare(raw)[source]

Bases: Record

Whole key share of the threshold MCFE over Ring-LWE (pyfe4ai.schemes.mcfe.ring_lwe_threshold, key_part="full"): shares of sk_y, z and z_chunks (Shamir; binary polynomials under binary public parameters) or the pieces of a replicated sharing.

Fields, in wire order:

  • sharing – replicated sharings only (absent: ‘shamir’)

  • pieces – replicated: KeyPiece of {sk_y, z, z_chunks}

  • seeds – seeded: KeySeed

  • layout – seeded: the piece layout

  • sk_y – Shamir: {client: polynomial}

  • z – Shamir: polynomial

  • z_chunks – Shamir: polynomials

  • label – str

  • noise_key – hex key of the flooding noise (per server, weights and label)

  • sharing_id – 32-char hex, this sharing (optional)

  • sid – the server id (str or int)

  • lst_sid – server ids

  • weights_id – hex digest of the weights

  • mac_keys – {client: hex key}

  • noise_version – int (absent: 1)

  • noise_sampler – the flooding sampler

  • flooding – uniform or gaussian (absent: ‘gaussian’)

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • pp_binding – hex digest

FIELDS: ClassVar[tuple[str, ...]] = ('sharing', 'pieces', 'seeds', 'layout', 'sk_y', 'z', 'z_chunks', 'label', 'noise_key', 'sharing_id', 'sid', 'lst_sid', 'weights_id', 'mac_keys', 'noise_version', 'noise_sampler', 'flooding', 'label_hash', 'pp_binding')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFERingLWEWeightShare(raw)[source]

Bases: Record

Weight part of a split key share of the threshold MCFE over Ring-LWE (part = "weights"; once per weights and share set).

Fields, in wire order:

  • sharing – replicated only (absent: ‘shamir’)

  • pieces – replicated: KeyPiece of {sk_y}

  • sk_y – Shamir: {client: polynomial}

  • part – weights

  • share_set_id – 32-char hex, this sharing of sk_y

  • sid – the server id (str or int)

  • lst_sid – server ids

  • weights_id – hex digest of the weights

  • mac_keys – {client: hex key}

  • noise_version – int (absent: 1)

  • noise_sampler – the flooding sampler

  • flooding – uniform or gaussian (absent: ‘gaussian’)

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • pp_binding – hex digest

FIELDS: ClassVar[tuple[str, ...]] = ('sharing', 'pieces', 'sk_y', 'part', 'share_set_id', 'sid', 'lst_sid', 'weights_id', 'mac_keys', 'noise_version', 'noise_sampler', 'flooding', 'label_hash', 'pp_binding')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFERingLWELabelShare(raw)[source]

Bases: Record

Label part of a split key share of the threshold MCFE over Ring-LWE (part = "label"; per label, completing the weight part of its share_set_id).

Fields, in wire order:

  • sharing – replicated only (absent: ‘shamir’)

  • pieces – replicated: KeyPiece of {z, z_chunks}

  • z – Shamir: polynomial (absent with label_term=False)

  • z_chunks – Shamir: polynomials

  • label – str

  • noise_key – hex key of the flooding noise

  • part – label

  • share_set_id – the weight part’s sharing

  • label_hash – label hash mode (absent: ‘shake256-wide’)

  • sharing_id – 32-char hex, this sharing of the label’s terms (optional)

  • sid – the server id (str or int)

  • lst_sid – server ids

  • weights_id – hex digest of the weights

  • mac_keys – {client: hex key}

  • noise_version – int (absent: 1)

  • noise_sampler – the flooding sampler

  • flooding – uniform or gaussian (absent: ‘gaussian’)

  • pp_binding – hex digest

FIELDS: ClassVar[tuple[str, ...]] = ('sharing', 'pieces', 'z', 'z_chunks', 'label', 'noise_key', 'part', 'share_set_id', 'label_hash', 'sharing_id', 'sid', 'lst_sid', 'weights_id', 'mac_keys', 'noise_version', 'noise_sampler', 'flooding', 'pp_binding')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMIFEDDHKeyShare(raw)[source]

Bases: Record

Key share of the threshold MIFE over DDH (pyfe4ai.schemes.mife.ddh_threshold; Shamir).

Fields, in wire order:

  • d – {client: decimal string}

  • z – decimal string

  • sid – the server id (str or int)

  • lst_sid – server ids

  • weights_id – hex digest of the weights

FIELDS: ClassVar[tuple[str, ...]] = ('d', 'z', 'sid', 'lst_sid', 'weights_id')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFEDDHKeyShare(raw)[source]

Bases: Record

Key share of the threshold MCFE over DDH (pyfe4ai.schemes.mcfe.ddh_threshold; Shamir).

Fields, in wire order:

  • d – two decimal strings

  • sid – the server id (str or int)

  • lst_sid – server ids

  • weights_id – hex digest of the weights

FIELDS: ClassVar[tuple[str, ...]] = ('d', 'sid', 'lst_sid', 'weights_id')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFEFHKeyShare(raw)[source]

Bases: Record

Key share of the threshold FH-MCFE (pyfe4ai.schemes.mcfe.fh_multi_ipe_pairing_threshold; shares in the exponent).

Fields, in wire order:

  • k – {client: serialised G2 elements}

  • z – serialised GT element

  • sid – the server id (str or int)

  • lst_sid – server ids

  • key_id – 32-char hex, this sharing

  • mac_keys – {client: hex key}

FIELDS: ClassVar[tuple[str, ...]] = ('k', 'z', 'sid', 'lst_sid', 'key_id', 'mac_keys')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TaggedCiphertext(raw)[source]

Bases: Record

Any ciphertext of the threshold schemes whose servers check client tags (tMIFE-LWE, tMCFE-Ring-LWE, tMCFE FH; the other fields are the scheme’s).

Fields, in wire order:

  • tags – {server: hex HMAC-SHA256} under the client-server keys

FIELDS: ClassVar[tuple[str, ...]] = ('tags',)

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.PartialDecryption(raw)[source]

Bases: Record

Any partial decryption, as the shared combiner code reads it.

Fields, in wire order:

  • w – the server’s key part

  • c_y – the weighted ciphertexts

  • u_d – tMCFE DDH: the label term

  • k – tMCFE-Ring-LWE: int, the batch length

  • ct_digest – hex digest of the decrypted ciphertexts

  • key_id – tMCFE FH: the key’s sharing

  • label – the encoded label

  • sid – the server id (str or int)

  • lst_sid_enrolled – the servers whose partials are combined

  • sharing_id – tMCFE-Ring-LWE: the key share’s sharing (optional)

FIELDS: ClassVar[tuple[str, ...]] = ('w', 'c_y', 'u_d', 'k', 'ct_digest', 'key_id', 'label', 'sid', 'lst_sid_enrolled', 'sharing_id')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFERingLWEPartial(raw)[source]

Bases: Record

Partial decryption of the threshold MCFE over Ring-LWE: w and c_y as decimal strings (ring_n values, JSON public parameters) or bytes (k words, binary ones).

Fields, in wire order:

  • w – values or bytes

  • c_y – values or bytes

  • k – int, the batch length

  • ct_digest – hex digest

  • sid – the server id (str or int)

  • lst_sid_enrolled – server ids

  • sharing_id – the key share’s sharing_id (or null) (optional)

FIELDS: ClassVar[tuple[str, ...]] = ('w', 'c_y', 'k', 'ct_digest', 'sid', 'lst_sid_enrolled', 'sharing_id')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFERingLWELayerPartials(raw)[source]

Bases: Record

One server’s partial decryptions of a packed ndarray layer (one per chunk).

Fields, in wire order:

FIELDS: ClassVar[tuple[str, ...]] = ('shape', 'parts')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMIFELWEPartial(raw)[source]

Bases: Record

Partial decryption of the threshold MIFE over LWE.

Fields, in wire order:

  • w – decimal string

  • c_y – decimal string

  • ct_digest – hex digest of the canonical ciphertexts

  • sid – the server id (str or int)

  • lst_sid_enrolled – server ids

FIELDS: ClassVar[tuple[str, ...]] = ('w', 'c_y', 'ct_digest', 'sid', 'lst_sid_enrolled')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFELWEPartial(raw)[source]

Bases: Record

Partial decryption of the threshold MCFE over LWE.

Fields, in wire order:

  • w – decimal string

  • c_y – int

  • label – the encoded label

  • sid – the server id (str or int)

  • lst_sid_enrolled – server ids

FIELDS: ClassVar[tuple[str, ...]] = ('w', 'c_y', 'label', 'sid', 'lst_sid_enrolled')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMIFEDDHPartial(raw)[source]

Bases: Record

Partial decryption of the threshold MIFE over DDH.

Fields, in wire order:

  • c_y – decimal string

  • w – decimal string

  • ct_digest – hex digest of the request

  • sid – the server id (str or int)

  • lst_sid_enrolled – server ids

FIELDS: ClassVar[tuple[str, ...]] = ('c_y', 'w', 'ct_digest', 'sid', 'lst_sid_enrolled')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFEDDHPartial(raw)[source]

Bases: Record

Partial decryption of the threshold MCFE over DDH.

Fields, in wire order:

  • c_y – decimal string

  • u_d – decimal string

  • label – the encoded label

  • sid – the server id (str or int)

  • lst_sid_enrolled – server ids

FIELDS: ClassVar[tuple[str, ...]] = ('c_y', 'u_d', 'label', 'sid', 'lst_sid_enrolled')

Field names in wire order (set for every subclass).

class pyfe4ai.core.formats.threshold.TMCFEFHPartial(raw)[source]

Bases: Record

Partial decryption of the threshold FH-MCFE.

Fields, in wire order:

  • w – serialised GT element

  • ct_digest – hex digest

  • key_id – the key share’s key_id

  • label – the encoded label

  • sid – the server id (str or int)

  • lst_sid_enrolled – server ids

FIELDS: ClassVar[tuple[str, ...]] = ('w', 'ct_digest', 'key_id', 'label', 'sid', 'lst_sid_enrolled')

Field names in wire order (set for every subclass).

Server and Client Ids

Server and client ids.

A server id (sid: an entry of lst_sid, the server of a key share or a partial decryption) or a client id (nid: an entry of lst_nid, the client of a ciphertext or an encrypted gradient) is a str or an int (not a bool): is_id(). A key generator refuses a lst_sid or lst_nid of other values, or one that mixes str and int ids (check_id_list()); partial decryptions and the wire records of the ML adapter carry ids of these types only, and messages that list ids order them with id_list().

Where an id enters after setup – the server or client named when keys are issued, a crypto object’s own id, the enrolled servers of a partial decryption, the servers of the ML adapter, the ids of partial decryptions and encrypted gradients read back – a numpy integer scalar is read as the int it equals (as_id(); list(rng.choice(lst_sid, t)) gives such ids), and then the same rule and the same membership checks apply.

pyfe4ai.core.ids.ID_LISTS = {'lst_nid': 'lst_nid must be a list of client ids, each a str or an int (convert numpy integers with int(), other ids with str())', 'lst_sid': 'lst_sid must be a list of server ids, each a str or an int (convert numpy integers with int(), other ids with str())'}

What a list of ids must be, by option name (the text of the FEValidationError for a list that is not one).

pyfe4ai.core.ids.MIXED_IDS = {'lst_nid': 'lst_nid mixes str and int client ids (convert them all with str(), or all with int())', 'lst_sid': 'lst_sid mixes str and int server ids (convert them all with str(), or all with int())'}

The FEValidationError text for a list that mixes str and int ids, by option name: JSON names 1 and "1" alike, and sorting such ids (canonical JSON digests, messages) fails.

pyfe4ai.core.ids.DUPLICATE_IDS = {'lst_nid': 'lst_nid contains duplicate client ids', 'lst_sid': 'lst_sid contains duplicate server ids'}

The FEValidationError text for a repeated id, by option name.

pyfe4ai.core.ids.is_id(value)[source]

Whether value is a server or client id: a str, or an int other than a bool.

Return type:

bool

pyfe4ai.core.ids.as_id(value)[source]

value read as an id after setup: a numpy integer scalar (numpy.integer; numpy.bool_ is none) becomes the int it equals (operator.index), which it also hashes like; every other value is returned unchanged, for is_id() and the membership checks to judge (a float, a bool, None stay what they are).

pyfe4ai.core.ids.issued_id(value)[source]

value read as the id a key is issued for: as_id() of it if that is an id, else None – which no lst_sid or lst_nid holds, so that the key generator answers as for an unknown server or client (None), also for True or 1.0, which equal the id 1.

pyfe4ai.core.ids.id_list(ids)[source]

ids sorted for a message: by value, or by repr where the values do not compare ([1, "a"]), so that listing ids never raises.

Return type:

list

pyfe4ai.core.ids.check_id_list(ids, option)[source]

Raise unless ids (the value of the option option, "lst_sid" or "lst_nid") is a list (or tuple) of distinct ids, all str or all int.

The lists themselves are taken as given (numpy integers are refused here, not read as ints: the key generator keeps the list, and the public parameters and key shares carry it).

Raises:

FEValidationError – ID_LISTS[option] for another value (a string, a set, a dict, an iterator) or an entry that is not an id (bytes, a float, None, a bool, a tuple, a numpy integer), MIXED_IDS[option] for str and int ids in one list, DUPLICATE_IDS[option] for a repeated id.

Parameters:

option (str)

Return type:

None

Versions and Compatibility

Versions and compatibility: what every version marker means, what a missing marker means, and the checks that accept, refuse or regenerate an artifact.

The serialized objects of a scheme (public parameters, parameter records, keys, key shares, ciphertexts, partial decryptions; their layouts are in pyfe4ai.core.formats) carry markers of the derivation that made them. Versions <= 0.3.0 wrote fewer markers, so for most of them an absent field has a meaning – the derivation of those versions:

Marker

Absent means

Decided by

label_hash (pp, keys,

"shake256-wide"

pp_label_hash(), key_label_hash(),

key shares)

(LEGACY_LABEL_HASH)

check_key_label_hash(), check_encryption_key_label_hash()

label_hash code

code 0 ("shake256-wide")

ciphertext_label_hash(),

(ciphertexts, layers)

check_ciphertext_label_hashes(), check_lwe_ciphertext_label_hash(), check_lwe_layer_label_hash()

ct_format (threshold

"json"

pp_ct_format()

pp)

sharing (pp, key

"shamir"

check_served_sharing()

shares)

(LEGACY_SHARING)

threshold_construction

none (Shamir only)

check_served_sharing(), check_tmife_lwe_construction(), check_tmcfe_ring_lwe_construction()

noise_version

1 (refused)

check_flooding_version()

flooding

"gaussian" (LEGACY_FLOODING)

pp_flooding(), check_key_flooding()

sharing_id

none (combines only with partials without one)

key_share_sharing_id(), check_partials_sharing()

part (tMCFE-Ring-LWE

a whole key share

key_share_part()

key shares)

_state_version

refused

check_state()

(pickled state)

record ids (construction,

regenerated

record_matches(), caches_record()

param_version, …)

Shamir key shares with t < s (the sharing of versions <= 0.3.0) are served only under the legacy_shamir policy of check_legacy_shamir().

The identifiers are those of earlier versions; nothing here changes a digest or a record. The byte formats’ own version bytes (format 1 and 2 of the Ring-LWE ciphertexts) are in pyfe4ai.core.formats.binary.

pyfe4ai.core.versions.SIFE_LWE_RECORD = 'abdp15-lwe-seeded-a/v1'

Record id of SIFE LWE (ABDP15 with a seeded A; record field construction).

pyfe4ai.core.versions.MIFE_LWE_RECORD = 'acfgu18-abdp15-lwe-seeded-a/v2'

Record id of MIFE LWE (record field construction).

pyfe4ai.core.versions.SIFE_FULLYSEC_LWE_RECORD = 'als16-lwe/v5'

Record id of SIFE FullySec LWE (K = 2 eta X Y + 1, encoding floor(q / K) x, m = 4 n log2 q, B_tau ~ sqrt(m); record field construction).

pyfe4ai.core.versions.MIFE_FULLYSEC_LWE_RECORD = 'acfgu18-als16-lwe/v4'

Record id of MIFE FullySec LWE (m = 4 n log2 q, B_tau ~ sqrt(m); record field construction).

pyfe4ai.core.versions.SIFE_RING_LWE_RECORD = 'bmms21-sec4.2/v3'

Record id of SIFE Ring-LWE (p = 2 l X Y + 2, Sec. 4.2 widths, seeded a; record field param_version).

pyfe4ai.core.versions.SIFE_FULLYSEC_RING_LWE_RECORD = 'bmms21-sec5/v2'

Record id of SIFE FullySec Ring-LWE, element-wise layout (a expanded from a stored seed; param_version).

pyfe4ai.core.versions.SIFE_FULLYSEC_RING_LWE_PACKED_RECORD = 'bmms21-sec5-packed/v2'

Record id of SIFE FullySec Ring-LWE, packed layout (leveraging over the span of the differences; v2: eta = 1 with the basis [1]; param_version).

pyfe4ai.core.versions.RING_LWE_RECORD = 'acfgu18-bmms21/v5'

Record id of the MIFE / MCFE / dMCFE / tMCFE Ring-LWE family (sized for n eta, p = 2T + 2, Sec. 4.2 widths for 3X, seeded a; record field construction).

pyfe4ai.core.versions.PAILLIER_RECORD = 'modulus-only/v1+g-seed'

Record format of the SIFE and MIFE Paillier records (versions <= 0.2.0 also stored p and q; record field param_format).

pyfe4ai.core.versions.MCFE_PAILLIER_RECORD = 'abmpsw20-dcr/v2'

Record id of MCFE Paillier (v1 records stored p and q; record field construction).

pyfe4ai.core.versions.MCFE_DAMGARD_RECORD = 'abmpsw20-mddh/v1'

Record id of MCFE Damgard (MDDH; record field construction).

pyfe4ai.core.versions.TMCFE_DDH_RECORD = 'cdgpp18-shamir/v1'

Record id of the threshold MCFE over DDH (record field construction).

pyfe4ai.core.versions.DMCFE_DDH_RECORD = 'abmpsw20-fig14-cdgpp18-dcr-carry-mask/v2'

Record id of the decentralised MCFE over DDH (record field construction).

pyfe4ai.core.versions.DMCFE_LWE_RECORD = 'abmpsw20-fig14-lwe-dcr/v2'

Record id of the decentralised MCFE over LWE (record field construction).

pyfe4ai.core.versions.DMCFE_PAILLIER_RECORD = 'abmpsw20-fig14-dcr-dcr/v1'

Record id of the decentralised MCFE over DCR (record field construction).

pyfe4ai.core.versions.MIFE_DDH_CONSTRUCTION = 'acfgu18-abdp15/v2'

Public-parameter construction of MIFE DDH (published, not checked).

pyfe4ai.core.versions.MIFE_DDH_RISTRETTO255_CONSTRUCTION = 'acfgu18-abdp15-ristretto255/v1'

Public-parameter construction of MIFE DDH over ristretto255 (published, not checked).

pyfe4ai.core.versions.RECORD_ABSENT = {'ndarray_layout': 'elementwise', 'ring_modulus': 'prime'}

The meaning of an absent field of a parameter record (a record of an earlier version) – the prime modulus of the Ring-LWE family, the element-wise layout of SIFE FullySec Ring-LWE.

pyfe4ai.core.versions.record_matches(param, expected)[source]

Whether the parameter record param has the expected value of every field (in order, stopping at the first difference; an absent field is RECORD_ABSENT’s value, else None). A record that does not match is regenerated by the parameter cache (ParameterCacheMixin).

Parameters:
Return type:

bool

pyfe4ai.core.versions.caches_record(key_generator)[source]

Whether a key generator keeps its parameter record in the cache: not one whose parameters include a DCR modulus under the standard profile (no check can tell whether someone knows its factors, so such parameters are generated afresh, never loaded or stored).

Return type:

bool

pyfe4ai.core.versions.LEGACY_SHARING = 'shamir'

The meaning of an absent sharing (pp and key shares) – the only sharing of versions <= 0.3.0.

pyfe4ai.core.versions.TMIFE_LWE_CONSTRUCTION = 'acfgu18-abdp15-shamir-smudging-seeded-a/v4'

The construction id of tMIFE-LWE (pyfe4ai.schemes.mife.lwe_threshold) with the Shamir sharing.

pyfe4ai.core.versions.TMIFE_LWE_CONSTRUCTION_KL = 'acfgu18-abdp15-shamir-smudging-kl/v2'

The construction id of tMIFE-LWE with the Shamir sharing and the KL accounting of the flooding.

pyfe4ai.core.versions.TMIFE_LWE_CONSTRUCTION_REPLICATED = 'acfgu18-abdp15-replicated-smudging-seeded-a/v1'

The construction id of tMIFE-LWE with the replicated sharing.

pyfe4ai.core.versions.TMIFE_LWE_CONSTRUCTION_REPLICATED_SEEDED = 'acfgu18-abdp15-replicated-seeded-smudging-seeded-a/v1'

The construction id of tMIFE-LWE with the seed-expanded replicated sharing.

pyfe4ai.core.versions.TMIFE_LWE_CONSTRUCTIONS = {'acfgu18-abdp15-replicated-seeded-smudging-seeded-a/v1': 'replicated-seeded', 'acfgu18-abdp15-replicated-smudging-seeded-a/v1': 'replicated', 'acfgu18-abdp15-shamir-smudging-kl/v2': 'shamir', 'acfgu18-abdp15-shamir-smudging-seeded-a/v4': 'shamir'}

The sharing of each tMIFE-LWE construction id.

pyfe4ai.core.versions.TMCFE_LWE_CONSTRUCTION = 'abmpsw20-shamir-flooding/v1'

The construction id of tMCFE-LWE (pyfe4ai.schemes.mcfe.lwe_threshold) with the Shamir sharing.

pyfe4ai.core.versions.TMCFE_LWE_CONSTRUCTION_REPLICATED = 'abmpsw20-replicated-flooding/v1'

The construction id of tMCFE-LWE with the replicated sharing.

pyfe4ai.core.versions.TMCFE_LWE_CONSTRUCTION_REPLICATED_SEEDED = 'abmpsw20-replicated-seeded-flooding/v1'

The construction id of tMCFE-LWE with the seed-expanded replicated sharing.

pyfe4ai.core.versions.TMCFE_LWE_CONSTRUCTIONS = {'abmpsw20-replicated-flooding/v1': 'replicated', 'abmpsw20-replicated-seeded-flooding/v1': 'replicated-seeded', 'abmpsw20-shamir-flooding/v1': 'shamir'}

The sharing of each tMCFE-LWE construction id.

pyfe4ai.core.versions.TMCFE_RING_LWE_CONSTRUCTION_IDS = {('replicated', 'gaussian'): 'bmms21-ibmcfe-replicated-smudging/v1', ('replicated', 'uniform'): 'bmms21-ibmcfe-replicated-smudging-uniform/v1', ('replicated-seeded', 'gaussian'): 'bmms21-ibmcfe-replicated-seeded-smudging/v1', ('replicated-seeded', 'uniform'): 'bmms21-ibmcfe-replicated-seeded-smudging-uniform/v1', ('shamir', 'gaussian'): 'bmms21-ibmcfe-shamir-smudging/v2', ('shamir', 'uniform'): 'bmms21-ibmcfe-shamir-smudging-uniform/v1'}

The parameter record (and public threshold_construction) of a sharing and a flooding of tMCFE-Ring-LWE (pyfe4ai.schemes.mcfe.ring_lwe_threshold) under the per-sample accounting ("kl": TMCFE_RING_LWE_CONSTRUCTION_KL).

pyfe4ai.core.versions.TMCFE_RING_LWE_CONSTRUCTION_KL = 'bmms21-ibmcfe-shamir-smudging-kl/v2'

The construction id of tMCFE-Ring-LWE with the Shamir sharing, Gaussian flooding and KL accounting.

pyfe4ai.core.versions.TMCFE_RING_LWE_CONSTRUCTIONS = {'bmms21-ibmcfe-replicated-seeded-smudging-uniform/v1': 'replicated-seeded', 'bmms21-ibmcfe-replicated-seeded-smudging/v1': 'replicated-seeded', 'bmms21-ibmcfe-replicated-smudging-uniform/v1': 'replicated', 'bmms21-ibmcfe-replicated-smudging/v1': 'replicated', 'bmms21-ibmcfe-shamir-smudging-kl/v2': 'shamir', 'bmms21-ibmcfe-shamir-smudging-uniform/v1': 'shamir', 'bmms21-ibmcfe-shamir-smudging/v2': 'shamir'}

The sharing of each tMCFE-Ring-LWE construction id.

pyfe4ai.core.versions.tmcfe_ring_lwe_construction_id(sharing, flooding, accounting)[source]

The tMCFE-Ring-LWE construction id of a sharing, a flooding and a flooding accounting (None for a combination the key generator does not make).

Parameters:
  • sharing (str)

  • flooding (str)

  • accounting (str)

Return type:

str | None

pyfe4ai.core.versions.check_served_sharing(pp, dk, constructions)[source]

Raise unless key share dk is of the sharing that pp describes.

pp["sharing"] must match the key share (both default to "shamir", the only sharing of versions <= 0.3.0). Public parameters of this version record threshold_construction; it must be one of constructions ({construction id: sharing}) and name that sharing, so that artifacts of another construction (a later version, say) are refused rather than misread. Only Shamir public parameters may lack it (those of versions <= 0.3.0); every version with the replicated sharing records it, so replicated public parameters without it are refused.

Parameters:
Return type:

None

pyfe4ai.core.versions.check_tmife_lwe_construction(pp, kl)[source]

Raise unless tMIFE-LWE public parameters that record a construction id record that of their flooding accounting (kl: "kl").

Raises:

FESchemeError – For the id of the other accounting.

Parameters:
Return type:

None

pyfe4ai.core.versions.check_tmcfe_ring_lwe_construction(pp, sharing, flooding, accounting)[source]

Raise unless tMCFE-Ring-LWE public parameters that record a construction id record that of the key share’s sharing, their flooding and accounting (tmcfe_ring_lwe_construction_id()).

Raises:

FESchemeError – Otherwise.

Parameters:
Return type:

None

pyfe4ai.core.versions.LEGACY_SHAMIR_POLICIES = ('refuse', 'warn')

What a server does with a Shamir key share whose t < s (crypto config entry legacy_shamir): "refuse" (default) or "warn" (serve it with an FESecurityWarning). Key shares of versions <= 0.3.0 are refused before this applies (their flooding derivation, see check_flooding_version()), so "warn" serves the explicit Shamir t < s shares of this version under toy. There is deliberately no environment variable: the opt-out is per server object.

pyfe4ai.core.versions.legacy_shamir_policy(config)[source]

The legacy_shamir entry of a server’s crypto config (default "refuse").

Parameters:

config (dict)

Return type:

str

pyfe4ai.core.versions.check_legacy_shamir(sid, threshold, s, legacy_shamir, profile)[source]

Serve server sid’s Shamir key share with t < s only under the legacy_shamir = "warn" policy and not under the standard profile of the public parameters (profile; None for those of versions <= 0.3.0), with a warning; t = s is served.

Raises:

FESchemeError – For such a key share that is not to be served.

Warns:

FESecurityWarning – When it is served; attributed to the application’s call (the first frame outside pyfe4ai, warn_at_caller()).

Parameters:
Return type:

None

pyfe4ai.core.versions.MIXED_SHARINGS = "partials come from different sharings of the label's key; fetch the label parts again from the key generator for all servers"

The message of MixedSharingsError.

exception pyfe4ai.core.versions.MixedSharingsError[source]

Bases: FESchemeError

Partial decryptions of different sharings of one key were combined.

Every sharing a key generator issues (whole key shares, or the label parts of one label) has a random sharing_id, which the servers’ partial decryptions carry. Shares of two sharings of the same key do not reconstruct it: combined, their partials would decode to a wrong value inside the decoding bound rather than fail. This happens when the label parts of one round are fetched on both sides of their eviction (LABEL_PARTS_KEPT); fetch them again for all servers. The check needs the ids: keep the sharing_id with every stored or transmitted key share and partial decryption (partials without one combine only with each other).

pyfe4ai.core.versions.key_share_sharing_id(dk)[source]

The sharing_id of a key share (None for key shares of earlier versions, which have none), which its partial decryptions carry.

Raises:

FEKeyError – For a sharing_id that is not a string.

Parameters:

dk (dict)

Return type:

str | None

pyfe4ai.core.versions.check_partials_sharing(partials)[source]

Raise unless the partial decryptions are of one sharing: shares of two sharings of one key do not reconstruct it (their partials would decode to a wrong value). Partials without a sharing_id combine only with each other.

Raises:
Parameters:

partials (list)

Return type:

None

pyfe4ai.core.versions.key_share_part(dk)[source]

The part of a tMCFE-Ring-LWE key share: "weights", "label", or None for a whole key share (versions <= 0.3.0 issued only those; key_part="full" still does).

Return type:

str | None

pyfe4ai.core.versions.FLOODING_NOISE_VERSION = 2

Version of the flooding-noise derivation in the decryption keys of the threshold schemes (tMIFE-LWE, tMCFE-LWE, tMCFE-Ring-LWE; noise_version): 2 since BIGINT_GUARD_BITS grew (keys without the field are version 1).

pyfe4ai.core.versions.check_flooding_version(dk)[source]

Refuse a threshold decryption key of another flooding derivation: it may have answered a request with the noise of the earlier derivation, and a second noise for the same request would let the answers be averaged.

Raises:

FEKeyError – For a key of another version (issue new keys).

Return type:

None

pyfe4ai.core.versions.LEGACY_FLOODING = 'gaussian'

The flooding of versions <= 0.3.0 and of public parameters (and key shares) without flooding.

pyfe4ai.core.versions.pp_flooding(pp)[source]

The flooding of tMCFE-Ring-LWE public parameters (absent: LEGACY_FLOODING).

Parameters:

pp (dict)

Return type:

str

pyfe4ai.core.versions.check_key_flooding(pp_value, dk, floodings)[source]

Raise unless the public parameters’ flooding pp_value is one of floodings and key share dk was issued for it (absent in either: LEGACY_FLOODING).

Raises:
Parameters:
Return type:

None

pyfe4ai.core.versions.label_hash_mode(value)[source]

value if it is one of LABEL_HASHES.

Raises:

FEValidationError – Otherwise.

Return type:

str

pyfe4ai.core.versions.pp_label_hash(pp)[source]

The label_hash of public parameters (absent: "shake256-wide", the hash of versions <= 0.3.0).

Raises:

FEValidationError – If it is not one of LABEL_HASHES.

Parameters:

pp (dict)

Return type:

str

pyfe4ai.core.versions.key_label_hash(key)[source]

The label_hash a key, key share or encryption key was issued for (absent: "shake256-wide").

Parameters:

key (dict)

Return type:

str

pyfe4ai.core.versions.check_key_label_hash(key, mode, subject='the key was')[source]

Raise unless key (a functional key or key share) was derived for the public parameters’ label hash mode (key_label_hash()).

Raises:

FESchemeError – "<subject> derived with another label hash than the     public parameters".

Parameters:
  • key (dict)

  • mode (str)

  • subject (str, default: 'the key was')

Return type:

None

pyfe4ai.core.versions.check_encryption_key_label_hash(sk, mode)[source]

mode if the encryption key sk was issued for that label hash (keys without label_hash: "shake256-wide").

Raises:

FEKeyError – If they differ (e.g. public parameters of another version than the key): the ciphertexts would decrypt to wrong values.

Parameters:
Return type:

str

pyfe4ai.core.versions.label_hash_code(mode)[source]

The code a ciphertext of label hash mode carries (LABEL_HASH_CODES), None for "shake256-wide": its ciphertexts carry none, as in versions <= 0.3.0.

Parameters:

mode (str)

Return type:

int | None

pyfe4ai.core.versions.ciphertext_label_hash(ct)[source]

The label hash a ciphertext or ndarray layer dict was produced with (no label_hash field: "shake256-wide"), or None for an unknown code.

Return type:

str | None

pyfe4ai.core.versions.check_ciphertext_label_hashes(cts, mode, who='a client')[source]

Raise unless every ciphertext dict of cts was produced with mode.

Raises:

FESchemeError – For a ciphertext of another (or an unknown) label hash.

Parameters:
  • mode (str)

  • who (str, default: 'a client')

Return type:

None

pyfe4ai.core.versions.check_lwe_ciphertext_label_hash(ct, nid, mode, absent)[source]

Raise unless a dense MCFE-LWE ciphertext carries the code of mode (absent: the code of a ciphertext without one – 0, the hash of versions <= 0.3.0, for a single ciphertext; its layer’s for an element of an ndarray layer, whose first element carries the code).

Raises:

FESchemeError – For a ciphertext of another label hash.

Parameters:
Return type:

None

pyfe4ai.core.versions.check_lwe_layer_label_hash(first, nid, mode)[source]

Raise unless the first element first of a dense MCFE-LWE ndarray layer carries the code of mode (none: "shake256-wide").

Raises:

FESchemeError – For a layer of another (or an unknown) label hash.

Parameters:

mode (str)

Return type:

None

pyfe4ai.core.versions.CT_FORMATS = ('json', 'binary')

The ciphertext formats of the Ring-LWE schemes, "json" (decimal strings) and "binary". For the MIFE / MCFE crypto objects (config ct_format, default "json") "binary" is format 1 (encode_binary_ciphertext()); for the threshold MCFE over Ring-LWE it is a public parameter (key generator config ct_format, default "binary"; pp_ct_format()): format 2 (encode_threshold_ciphertext()), tags over its digests, binary partial decryptions. "json" is the only format of versions <= 0.3.0 and that of threshold public parameters without ct_format.

pyfe4ai.core.versions.pp_ct_format(pp)[source]

The ciphertext format of threshold public parameters (absent: "json").

Raises:

FEValidationError – For another value.

Parameters:

pp (dict)

Return type:

str

pyfe4ai.core.versions.TMCFE_RING_LWE_STATE_VERSION = 'pyfe4ai/tmcfe-ring-lwe/state/2026-10-3'

The version of the pickled state of the tMCFE-Ring-LWE objects (a state pickled by another version of pyfe4ai, with other attributes or other derivations, is refused when loaded).

pyfe4ai.core.versions.versioned_state(state, version)[source]

state with its _state_version.

Parameters:
Return type:

dict

pyfe4ai.core.versions.check_state(obj, state, version)[source]

Load state into obj, refusing one pickled by another version.

Raises:

FESchemeError – For a state of another version (or of none).

Parameters:
Return type:

None

Configuration

The config classes and option rules (pyfe4ai.core.config) are documented on Configuration, every scheme’s options on Configuration options.

Offline Phases and One-Time Precomputations

One-time use of a precomputation (the offline phase of an encryption).

A precomputation holds the secret randomness or label masks of future ciphertexts; using it twice encrypts two plaintexts with the same randomness (or twice under one label), and their difference follows without any key. OneTimePrecomputation makes the use atomic and keeps it in one process:

  • _claim checks and sets used under a per-object lock and moves the secret parts out of the object, so of two threads exactly one gets them;

  • a precomputation records the process that made it and refuses to be used in another one; after os.fork() the child’s copies are also marked used and dropped (pyfe4ai.core.forksafe.track());

  • copy.copy, copy.deepcopy and pickling raise TypeError: a copy would be a second, unused handle on the same randomness. Code that clones the object deliberately (copying its attributes) is not prevented; the object is a handle on a secret, not a capability that cannot be forged.

The schemes validate their inputs before they claim the precomputation, so refused inputs do not consume it.

Offline / online encryption of the element-wise schemes with fresh randomness per ciphertext (OfflineRandomMixin): SIFE- and MIFE-Paillier (ALS16 over DCR) encrypt as (g^r, (1 + N)^x pk^r) and MIFE-DDH as (g^r, g^{x + u} h^r) with a fresh r per ciphertext: everything but the plaintext term depends on r and the key only, and costs full-size exponentiations. OfflineRandomMixin.precompute() draws r for every element of given layer shapes – in the order encrypt_lst_ndarray draws them – and computes those powers; encrypt_lst_ndarray(..., precomputed=...) then only multiplies in the plaintext term. With the same random source the ciphertexts are those of the plain call. The precomputation holds the secret randomness of future ciphertexts: keep it like a key. It is one-time (OneTimePrecomputation): the online phase validates its input, then claims the precomputation atomically; copy.copy, copy.deepcopy, pickling and use in another process are refused.

A scheme provides _random_part() (draws r; returns what the ciphertext needs of it) and _encrypt_with(lst_pt, part) (the ciphertext of encrypt for that part, with its checks), and names in _online_bound the public parameter that bounds the plaintexts, if _encrypt_with checks one (checked before the precomputation is used).

class pyfe4ai.core.one_time.OneTimePrecomputation[source]

Bases: object

Base of the offline phases’ results: secret, one-time, one process.

Subclasses list in _secret the attributes that hold the secret parts (dropped by _claim and in a forked child).

pyfe4ai.core.one_time.check_online_bound(scheme, layers)[source]

The plaintext bound pp[scheme._online_bound] of the online phase, checked on all layers before the precomputation is claimed.

Parameters:

layers (list)

Return type:

None

class pyfe4ai.core.one_time.RandomPrecomputation(owner, shapes, parts)[source]

Bases: OneTimePrecomputation

The randomness-dependent parts of future ciphertexts. Secret, one-time.

Parameters:
class pyfe4ai.core.one_time.OfflineRandomMixin[source]

Bases: object

precompute / precomputed= for the element-wise ndarray helpers.

precompute(shapes)[source]

Offline phase of encrypt_lst_ndarray for layers of shapes.

Return type:

RandomPrecomputation

Offline / online phases of the element-wise MCFE schemes over Z_p^* and Z_{N^2}^*.

In MCFE-DDH (CDGPP18), MCFE-Damgard and MCFE-Paillier (ABMPSW20 Fig. 3) a ciphertext of x under label l is X(x) M(l) mod P: X(x) is g^x or (1 + N)^x and the label mask M(l) a product of powers of the label’s hashes with the client’s secret, which does not depend on x. Decryption divides prod_i c_i^{y_i} by a key term of the label and the functional key. Both label terms are the expensive part (exponents of 256 to 3072 bits) and are known before the round, so:

  • OfflineMCFEMixin.precompute() computes a client’s masks for every element label of given layer shapes; encrypt_lst_ndarray(..., precomputed=...) then only computes X(x) and one product per element. The ciphertexts are those of the plain call (the encryption is deterministic). Secret and one-time, as the masks of the Ring-LWE MCFE (see pyfe4ai.core.one_time: claimed atomically after the input is validated; copy.copy, copy.deepcopy, pickling and use in another process are refused).

  • OfflineMCFEMixin.prepare_key() computes the key terms of every element label for a functional key; decrypt_lst_ndarray_ct with that key then only multiplies the ciphertexts and solves the discrete log.

A scheme provides _label_mask(label) (one mask per slot), _encrypt_masked(lst_pt, masks), _key_term(dk, label) and decrypt(..., term=...) with the checks of its plain methods, and names in _online_bound the public parameter that bounds the plaintexts, if _encrypt_masked checks one.

class pyfe4ai.schemes.mcfe.offline.LabelPrecomputation(owner, label, shapes, masks)[source]

Bases: OneTimePrecomputation

A client’s label masks for one label and fixed layer shapes. Secret, one-time.

Parameters:
class pyfe4ai.schemes.mcfe.offline.PreparedKeyTerms(label, shapes, terms)[source]

Bases: object

The key terms of every element label of a functional key (not secret beyond the key).

Parameters:
class pyfe4ai.schemes.mcfe.offline.OfflineMCFEMixin[source]

Bases: object

precompute / precomputed= / prepare_key for the element-wise MCFE schemes.

precompute(label, shapes)[source]

Offline phase of encrypt_lst_ndarray for label and layers of shapes.

Parameters:

label (str)

Return type:

LabelPrecomputation

prepare_key(dk, label, shapes)[source]

dk with the key terms of every element label of label and shapes: decrypt_lst_ndarray_ct then skips the label hashing and exponentiations.

Parameters:
Return type:

dict

Fork Safety

What a forked child renews; the process-wide state and what threads, copies, pickles and fork do to it are on Threads, Processes and Copies.

What a forked child process renews: the one fork handler of the library.

os.fork() copies the whole memory of the process but only the thread that called it. A lock that another thread held at the fork stays held for ever in the child, and per-process random state (buffered OS random bytes, the secret parts of one-time precomputations) would be used by both processes. This module registers the library’s only os.register_at_fork handler (after_in_child); in the child it runs, in the order they were registered:

and then track() – call _after_fork_in_child() of every tracked object still alive (e.g. mark the one-time precomputations used and drop their secret parts, pyfe4ai.core.one_time; give a PartialDecryptionBudget or a FESchemeWrapper a new lock).

Nothing runs in the parent, nor before the fork. A handler that raises is reported on stderr as an os.register_at_fork hook’s exception is (Exception ignored in: ... and the traceback), and the other handlers still run. The registrations are made at import of the modules that own the state, so the child renews what the parent had imported. The process-wide state of the library and what a fork, a copy or a pickle does to it are listed on the “Threads, processes and copies” page of the documentation.

pyfe4ai.core.forksafe.renew_lock(owner, name, factory=<built-in function allocate_lock>)[source]

In a forked child, replace owner.<name> (a module’s process-wide lock) with factory(): the parent’s may be held by another thread, which the child does not have.

The code using the lock must read owner.<name> at every use (with _LOCK: in the owning module does), not keep a reference to it.

Parameters:

name (str)

Return type:

None

pyfe4ai.core.forksafe.call_in_child(func)[source]

Call func() in a forked child (held strongly, like os.register_at_fork).

Return type:

None

pyfe4ai.core.forksafe.track(obj)[source]

Call obj._after_fork_in_child() in a forked child, if obj is still alive then (obj is held weakly: tracking does not extend its lifetime).

Return type:

None

Exceptions

Custom exception hierarchy for PyFE4AI.

All scheme-level exceptions inherit from FEError, allowing consumers to catch broad (except FEError) or narrow (except FEValidationError).

exception pyfe4ai.core.exceptions.FEError[source]

Bases: Exception

Base exception for all PyFE4AI errors.

exception pyfe4ai.core.exceptions.FEConfigError[source]

Bases: FEError

Configuration or parameter file error (missing, invalid, corrupt).

exception pyfe4ai.core.exceptions.FEKeyError[source]

Bases: FEError

Missing or invalid cryptographic keys / credentials.

exception pyfe4ai.core.exceptions.FEValidationError[source]

Bases: FEError, ValueError

Input validation failure (bound exceeded, shape mismatch, etc.).

exception pyfe4ai.core.exceptions.FESchemeError[source]

Bases: FEError, RuntimeError

Internal scheme logic error (unexpected state, unsupported operation).

exception pyfe4ai.core.exceptions.FESecurityWarning[source]

Bases: UserWarning

A scheme with a known security defect is being used.

See pyfe4ai.core.status and the README Scheme Status table. Like FEWarning, it is attributed to the application’s call (the first caller outside pyfe4ai, warn_at_caller()).

exception pyfe4ai.core.exceptions.FEWarning[source]

Bases: UserWarning

A condition an application should see that does not stop the call.

For example a cached parameter record that no longer matches its configuration and is regenerated (new parameters and seeds), a request answered with None (an unknown id, a decryption out of range) or a slower fallback. The library also logs them (logging.getLogger("pyfe4ai") has only a NullHandler, so without a logging configuration this warning is what an application sees). Not a subclass of FESecurityWarning: filtering one leaves the other.

It is attributed to the application’s call (the first caller outside pyfe4ai, see warn_at_caller()), so Python’s default filter shows it once per call site of the application, not once per library line. Its text holds no caller-supplied values (an unknown id is in the log record only).

pyfe4ai.core.exceptions.warn_at_caller(message, category=<class 'pyfe4ai.core.exceptions.FEWarning'>)[source]

Issue message as a category warning attributed to the first frame outside the pyfe4ai package – the application’s call, however deep the library’s own calls are – or, if every frame is inside it, to the library function that issues it. Used by the library for FEWarning.

Parameters:
  • message (str)

  • category (type, default: <class 'pyfe4ai.core.exceptions.FEWarning'>)

Return type:

None

Constants

Scheme-type constants and default parameter values used across PyFE4AI.

class pyfe4ai.core.constants.CryptoCONST[source]

Bases: object

TYPE_NONE = 'None'
TYPE_SIFE = 'SIFE'
TYPE_MIFE = 'MIFE'
TYPE_MCFE = 'MCFE'
TYPE_DMCFE = 'dMCFE'
TYPE_DMCFE_LWE = 'dMCFE_LWE'
TYPE_DMCFE_RING_LWE = 'dMCFE_RING_LWE'
TYPE_DMCFE_FH_MULTI_IPE = 'dMCFE_FH_MULTI_IPE'
TYPE_TMCFE = 'tMCFE'
TYPE_TMCFE_LWE = 'tMCFE_LWE'
TYPE_TMCFE_RING_LWE = 'tMCFE_RING_LWE'
TYPE_TMCFE_FH_MULTI_IPE = 'tMCFE_FH_MULTI_IPE'
TYPE_TMIFE = 'tMIFE'
TYPE_TMIFE_LWE = 'tMIFE_LWE'
TYPE_SIFE_PAILLIER = 'SIFE_PAILLIER'
TYPE_SIFE_DAMGARD = 'SIFE_DAMGARD'
TYPE_SIFE_LWE = 'SIFE_LWE'
TYPE_SIFE_FULLYSEC_LWE = 'SIFE_FULLYSEC_LWE'
TYPE_SIFE_RING_LWE = 'SIFE_RING_LWE'
TYPE_SIFE_FULLYSEC_RING_LWE = 'SIFE_FULLYSEC_RING_LWE'
TYPE_SIFE_FH_IPE = 'SIFE_FH_IPE'
TYPE_SIFE_PART_FH_IPE = 'SIFE_PART_FH_IPE'
TYPE_QUADRATIC_SGP = 'QUADRATIC_SGP'
TYPE_QUADRATIC_QUAD = 'QUADRATIC_QUAD'
TYPE_QUADRATIC_MIQFE = 'QUADRATIC_MIQFE'
TYPE_MIFE_PAILLIER = 'MIFE_PAILLIER'
TYPE_MIFE_DAMGARD = 'MIFE_DAMGARD'
TYPE_MIFE_LWE = 'MIFE_LWE'
TYPE_MIFE_FULLYSEC_LWE = 'MIFE_FULLYSEC_LWE'
TYPE_MIFE_FH_IPE = 'MIFE_FH_IPE'
TYPE_MIFE_FH_MULTI_IPE = 'MIFE_FH_MULTI_IPE'
TYPE_MIFE_RING_LWE = 'MIFE_RING_LWE'
TYPE_MCFE_PAILLIER = 'MCFE_PAILLIER'
TYPE_MCFE_DAMGARD = 'MCFE_DAMGARD'
TYPE_MCFE_LWE = 'MCFE_LWE'
TYPE_MCFE_FULLYSEC_LWE = 'MCFE_FULLYSEC_LWE'
TYPE_MCFE_RING_LWE = 'MCFE_RING_LWE'
TYPE_MCFE_FH_MULTI_IPE = 'MCFE_FH_MULTI_IPE'
DEC_STAGE_1 = 'partial_decryption'
DEC_STAGE_2 = 'final_decryption'
CT_STAGE_1 = 'ct_original'
CT_STAGE_2 = 'ct_prime'
SEC_PARAM = 128
SIFE_DEFAULT_ETA = 5
MIFE_ETA = 1
MCFE_ETA = 1
tMIFE_ETA = 1
tMIFE_T = 2
tMCFE_ETA = 1
tMCFE_N = 5
tMCFE_S = 3
tMCFE_T = 2

Input Validation

Input validation shared by the schemes.

pyfe4ai._validation.int_vector(values, name, length=None, bound=None)[source]

Return values as a list of Python ints, or raise FEValidationError.

Integer types (int, numpy.integer, gmpy2.mpz) and integral floats are accepted; booleans and non-integral numbers are rejected instead of being truncated silently.

Parameters:
  • values – Sequence of numbers.

  • name (str) – Name used in error messages.

  • length (int | None, default: None) – Required length, if any.

  • bound (default: None) – If given, every |v| must be at most bound.

Return type:

list[int]

pyfe4ai._validation.strict_int(value, name='input')[source]

value as an int; non-integral values raise (see int_vector()).

Parameters:

name (str, default: 'input')

Return type:

int

pyfe4ai._validation.scale_to_int(values, precision)[source]

Return round(values * 10^precision) as an int64 array.

The ndarray helpers encode real-valued plaintexts with this: it rounds to the nearest integer (ties to even) instead of truncating toward zero, multiplies integer arrays exactly, and refuses NaN, infinities and values whose scaled magnitude is not exactly representable.

Raises:

FEValidationError – For non-numeric, non-finite or too large values.

Parameters:

precision (int)

Return type:

ndarray