SIFE — Single-Input Functional Encryption¶
Single-input functional encryption schemes: the key generator and crypto class of every
scheme of the family (the registry: pyfe4ai.core.registry).
The key generator and crypto class of every scheme below are importable
from pyfe4ai.schemes.sife under their own names (one name per class,
no aliases; the naming rule is in pyfe4ai.core.registry).
DDH¶
Simple Single Input Functional Encryption | From “Simple Functional Encryption Schemes for Inner Products” | Published in: PKC 2015 | By Michel Abdalla, Florian Bourse, Angelo De Caro, and David Pointcheval | URL: https://eprint.iacr.org/2015/017.pdf
type: public-key encryption
setting: Integer based (order-q subgroup of Z_p^*, p = 2q + 1)
Construction 1 of ABDP15 (DDH): mpk = (g, h_i = g^{s_i}); the key for
y is sk_y = <s, y> mod q; ct = (g^r, h_i^r g^{x_i}); decryption
computes prod ct_i^{y_i} / ct_0^{sk_y} = g^{<x, y>} and a bounded discrete
log (dlog_bound, default 10^(precision + 2)). Every ciphertext
component is reduced modulo p – versions <= 0.2.0 published the integer
(h_i^r mod p)(g^{x_i} mod p), from which x_i follows by trial
division – and keys are reduced modulo q.
- class pyfe4ai.schemes.sife.ddh.SIFEDDHKeyGenerator(config, **kwargs)[source]¶
Bases:
DDHKeyGeneratorBaseKey generator for DDH-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:sec_param,eta(plaintext vector length).- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters (g, p, eta, sec_param).
- Return type:
- Returns:
Dict of public parameters.
- get_decryption_keys(sid, **kwargs)[source]¶
Derive a functional decryption key for the given fusion weights.
- Parameters:
sid (
str) – Session identifier.**kwargs – Must include
credentialswithfusion_weight(list of int).
- Return type:
- Returns:
Dict with
z(<s, y> mod q) and the weightsy.- Raises:
FEKeyError – If credentials are missing.
FEValidationError – If fusion weights are invalid.
- class pyfe4ai.schemes.sife.ddh.SIFEDDH(config, **kwargs)[source]¶
Bases:
IPFEAbsCryptoCrypto operations for DDH-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE crypto system.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters) and eithersk(encryption keys) ordk(decryption key);dlog_bound(default10^(precision + 2)) bounds the inner products decryption recovers.- Return type:
None
- encrypt(lst_pt)[source]¶
Encrypt a plaintext vector under the DDH-based scheme.
- Parameters:
lst_pt (
list) – Integer plaintext vector of lengtheta.- Return type:
- Returns:
Dict with
ct0(group element) andct1(list of group elements).- Raises:
FEKeyError – If public parameters or private keys are missing.
FEValidationError – If the plaintext is not
etaintegers.
- decrypt(dct_ct, dk, fusion_weight)[source]¶
Decrypt a ciphertext to recover the inner product ⟨x, y⟩.
- Parameters:
dk (
dict) – Decryption key dict fromSIFEDDHKeyGenerator.get_decryption_keys().fusion_weight (
list) – Integer weight vector y (the key’s weights).
- Returns:
The inner product as an integer, or
Noneif|<x, y>|exceedsdlog_bound.- Raises:
FEKeyError – If public parameters or decryption key is missing.
FESchemeError – If fusion_weight are not the key’s weights.
FEValidationError – If the ciphertext is malformed.
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Not implemented for this scheme; raises
NotImplementedError.
DDH over ristretto255¶
Simple Single Input Functional Encryption over ristretto255 | From “Simple Functional Encryption Schemes for Inner Products” | Published in: PKC 2015 | By Michel Abdalla, Florian Bourse, Angelo De Caro, and David Pointcheval | URL: https://eprint.iacr.org/2015/017.pdf
type: public-key encryption
setting: the prime-order group ristretto255 (RFC 9496), written additively
Construction 1 of ABDP15 (DDH), as pyfe4ai.schemes.sife.ddh but in
ristretto255: mpk = (G, H_i = s_i G); the key for y is
sk_y = <s, y> mod L; ct = (r G, r H_i + x_i G); decryption computes
sum_i y_i ct_i - sk_y ct_0 = <x, y> G and a bounded discrete log
(dlog_bound, default 10^(precision + 2)). See
pyfe4ai.schemes.common.ec_ddh_base.
- class pyfe4ai.schemes.sife.ddh_ristretto255.SIFEDDHRistretto255KeyGenerator(config, **kwargs)[source]¶
Bases:
ECDDHKeyGeneratorBaseKey generator for DDH-based single-input inner-product FE over ristretto255.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Check the configuration.
- Parameters:
config (
dict) –eta(plaintext vector length);group(optional,"ristretto255").- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
A dict of public parameters, or
Noneon error.
- class pyfe4ai.schemes.sife.ddh_ristretto255.SIFEDDHRistretto255(config, **kwargs)[source]¶
Bases:
ECDDHCryptoBaseCrypto operations for DDH-based single-input inner-product FE over ristretto255.
- Parameters:
config (
dict)
- decrypt(dct_ct, dk, fusion_weight)[source]¶
<x, y>, orNoneif|<x, y>|exceedsdlog_bound.- Raises:
FEKeyError – If the decryption key is missing.
FESchemeError – If fusion_weight are not the key’s weights.
FEValidationError – If the ciphertext is malformed.
- Parameters:
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Not implemented for this scheme; raises
NotImplementedError.
- compute_lst_ndarray_ct(dict_ndarray_ct, **kwargs)[source]¶
Aggregate ciphertexts from multiple clients.
- 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:
- Returns:
One float array of decrypted results per layer.
- Raises:
FESchemeError – If an element does not decrypt (see
decoded_layer()).
DDH Dynamic¶
Simple Single Input Functional Encryption, variable-length vectors | From “Simple Functional Encryption Schemes for Inner Products” | Published in: PKC 2015 | By Michel Abdalla, Florian Bourse, Angelo De Caro, and David Pointcheval | URL: https://eprint.iacr.org/2015/017.pdf
type: public-key encryption
setting: Integer based (order-q subgroup of Z_p^*, p = 2q + 1)
ABDP15 Construction 1 (pyfe4ai.schemes.sife.ddh) for vectors of any
length up to eta: a key for y of length k <= eta is the key of
(y, 0, ..., 0), and a plaintext of length m <= eta is encrypted as a
prefix of (x, 0, ..., 0) (the omitted components are a function of a full
ciphertext). The key decrypts any ciphertext with at least k components.
Security reduces to ABDP15 by this zero padding; there is no separate paper.
- class pyfe4ai.schemes.sife.ddh_dynamic.SIFEDDHDynamicKeyGenerator(config, **kwargs)[source]¶
Bases:
SIFEDDHKeyGeneratorABDP15 key generator issuing keys for weight vectors of length <=
eta.- Parameters:
config (
dict)
Damgård DDH¶
Single-Input Inner-Product Functional Encryption (Damgard / DDH) | From “Fully Secure Functional Encryption for Inner Products, | from Standard Assumptions” | By Shweta Agrawal, Benoit Libert, and Damien Stehle | Published in: CRYPTO 2016 – the DDH scheme, as recalled (D_k-MDDH, here | k = 1) in Abdalla, Catalano, Fiore, Gay, Ursu, CRYPTO 2018, Fig. 7.
type: public-key encryption
setting: Integer based (order-q subgroup of Z_p^*, p = 2q + 1)
h = g^a with a discarded ([A] with A = (1, a)); per coordinate
(s_i, t_i) <- Z_q^2 and pk_i = g^{s_i} h^{t_i}. The key for y is
(<s, y>, <t, y>) mod q; ct = (g^r, h^r, g^{x_i} pk_i^r); decryption
computes prod e_i^{y_i} / (c^{k1} d^{k2}) = g^{<x, y>} and a discrete log
bounded by eta B^2, with 2 eta B^2 < q so that signed results are
unique.
- class pyfe4ai.schemes.sife.damgard_ddh.SIFEDamgardKeyGenerator(config, **kwargs)[source]¶
Bases:
DamgardDDHKeyGeneratorBaseKey generator for Damgard DDH-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE Damgård DDH key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:sec_param,eta,modulus_length(defaultsec_param) andbound(on inputs and weights).- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
A dict of public parameters, or
Noneon error.
- class pyfe4ai.schemes.sife.damgard_ddh.SIFEDamgard(config, **kwargs)[source]¶
Bases:
IPFEAbsCryptoCrypto operations for Damgard DDH-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE Damgård DDH crypto object.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters) and optionallysk(encryption keys).- Return type:
None
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Encrypt a list of ndarrays element-wise (requires
eta = 1).- Parameters:
lst_ndarray (
list) – List of numpy arrays, scaled by10^precision.- Return type:
- Returns:
One object array of ciphertexts per input array.
- Raises:
NotImplementedError – If
eta != 1.
LWE¶
LWE-Based Single-Input Inner-Product Functional Encryption | From “Simple Functional Encryption Schemes for Inner Products” | By Michel Abdalla, Florian Bourse, Angelo De Caro, David Pointcheval | Published in: PKC 2015; full version ePrint 2015/017 (revised 2015-03-28, 2015-10-01) | | This module implements the generic simple FE construction instantiated | under the LWE assumption as a research-oriented Python prototype.
type: public-key encryption
setting: Integer based
note: prototype implementation with the common key generator / crypto API
The scheme is the LWE instantiation as revised in the full version
(Construction 4.1 over the Regev scheme of Construction 6.5, Sec. 6.2;
F. Bourse, PhD thesis, ENS 2017, Fig. 8.1): uniform secrets, binary
r, t(x) = x floor(q / p) and no r-ary decomposition of the
message. Theorem 2 of the proceedings version does not cover it: its
simulation reuses encryption randomness through the secret key and changes
the basis of noisy public keys with coefficients in Z_q, and both steps
fail for keys A s + e.
The full version proves selective IND-CPA with its Thm. 4.4, through public-key
and ciphertext reproducibility (Thms. 6.6 and 6.7; Bourse, Thm. 4.3.5 with
Thms. 8.2.2, 8.2.3, 8.3.2). The proof assumes LWE with errors of width
sigma' = sigma / (1 + 2 X sqrt(eta)), the condition derived in the proof of
Thm. 6.6; Sec. 6.2 lists the stronger (l B + 1) sigma'. It also needs
m >= (n + eta + 1) log2 q + 2 log2(1 / eps) (proof of Thm. 6.7). See
pyfe4ai.schemes.common.abdp15_lwe for the hypotheses that the library meets
differently.
The public matrix A is published as a seed and expanded with SHAKE-128;
encryption computes A^T r and pk^T r exactly with numpy, either over
an A kept in memory or expanded for every batch (matrix_mode). See
pyfe4ai.schemes.common.abdp15_lwe, which also covers the standard
parameters. Versions <= 0.2.0 published A entry by entry.
- class pyfe4ai.schemes.sife.lwe.SIFELWEKeyGenerator(config, **kwargs)[source]¶
Bases:
IPFEAbsKeyGenerator,ABDP15KeyGeneratorMixinKey generator for LWE-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE LWE key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:sec_param,eta,lwe_n(default 32;"auto"for the smallest dimension meeting the 128-bit table, thestandardprofile’s choice),bound_x,bound_yandmatrix_mode("memory"or"stream", seepyfe4ai.schemes.common.abdp15_lwe).- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
Dict containing
A_seed,m,lwe_n,p,q,eta,bound_x,bound_y,sec_param.
- get_private_keys(nid='nid_default', **kwargs)[source]¶
Return encryption keys (public-key matrix
pk).
- get_decryption_keys(sid, **kwargs)[source]¶
Derive a functional decryption key for the given fusion weights.
- Parameters:
sid (
str) – Session identifier.**kwargs – Must include
credentialswithfusion_weight(list of int).
- Return type:
- Returns:
Dict with
sk_y(the projected secret key).- Raises:
FEKeyError – If credentials are missing.
FEValidationError – If fusion weights are invalid or exceed
bound_y.
- class pyfe4ai.schemes.sife.lwe.SIFELWE(config, **kwargs)[source]¶
Bases:
IPFEAbsCrypto,ABDP15CryptoMixinCrypto operations for LWE-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE LWE crypto system.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters) and optionallysk(encryption keys); optionalmatrix_mode("memory"or"stream").- Return type:
None
- encrypt(lst_pt)[source]¶
Encrypt a plaintext vector under the LWE-based scheme.
- Parameters:
lst_pt (
list) – Integer plaintext vector of lengtheta.- Return type:
- Returns:
Dict with
ct0andct1(serialised LWE ciphertext vectors).- Raises:
FEKeyError – If public parameters or encryption keys are missing.
FEValidationError – If plaintext length or values are invalid.
- decrypt(dct_ct, dk, fusion_weight)[source]¶
Decrypt a ciphertext to recover the inner product ⟨x, y⟩.
- Parameters:
dk (
dict) – Decryption key dict fromSIFELWEKeyGenerator.get_decryption_keys().fusion_weight (
list) – Integer weight vector y.
- Returns:
The inner product as an integer.
- Raises:
FEKeyError – If decryption key is missing.
FEValidationError – If fusion weight length or values are invalid.
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Encrypt a list of ndarrays element-wise (requires
eta=1).
- compute_lst_ndarray_ct(dict_ndarray_ct, **kwargs)[source]¶
Aggregate ndarray ciphertexts (delegates to
decrypt_lst_ndarray_ct()).
Fully-Secure LWE¶
Fully Secure LWE-Based Single-Input Inner-Product Functional Encryption
| Based on the LWE variant of
| “Fully Secure Functional Encryption for Inner Products,
| from Standard Assumptions”
| By Shweta Agrawal, Benoit Libert, Damien Stehle
| Published in: CRYPTO 2016
|
| as recalled in Abdalla, Catalano, Fiore, Gay, Ursu, CRYPTO 2018, Fig. 8.
| Parameters follow GoFE’s innerprod/fullysec/lwe.go.
type: public-key encryption
setting: Integer based
A <- Z_q^{m x n}; Z has D_{sigma1} entries in its first m/2
columns and D_{sigma2} entries plus the identity in the others; U = Z A.
The key for y is Z^T y; ct = (A s + e0, U s + e1 + floor(q/K) x);
decryption decodes <y, ct1> - <Z^T y, ct0>. Signed messages and weights:
K = 2 eta X Y + 1 (versions <= 0.2.0 used 2 eta X Y, so +-eta X Y
decoded with a random sign), centred decoding.
- class pyfe4ai.schemes.sife.fullysec_lwe.SIFEFullySecLWEKeyGenerator(config, **kwargs)[source]¶
Bases:
IPFEAbsKeyGenerator,ParameterCacheMixinKey generator for fully secure LWE-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the fully secure SIFE LWE key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:sec_param,eta,lwe_n,bound_x,bound_y.- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
Dict containing
A,k,q,m,eta,lwe_n,bound_x,bound_y, and noise parameters.
- get_private_keys(nid='nid_default', **kwargs)[source]¶
Return encryption keys (public-key matrix
pk).
- get_decryption_keys(sid, **kwargs)[source]¶
Derive a functional decryption key for the given fusion weights.
- Parameters:
sid (
str) – Session identifier.**kwargs – Must include
credentialswithfusion_weight(list of int).
- Return type:
- Returns:
Dict with
sk_y(Z^T y) and the weightsy.- Raises:
FEKeyError – If credentials are missing.
FEValidationError – If fusion weights are invalid or exceed
bound_y.
- class pyfe4ai.schemes.sife.fullysec_lwe.SIFEFullySecLWE(config, **kwargs)[source]¶
Bases:
IPFEAbsCryptoCrypto operations for fully secure LWE-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the fully secure SIFE LWE crypto system.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters) and optionallysk(encryption keys).- Return type:
None
- encrypt(lst_pt)[source]¶
Encrypt a plaintext vector under the fully-secure LWE scheme.
- Parameters:
lst_pt (
list) – Integer plaintext vector of lengtheta.- Return type:
- Returns:
Dict with
ct0andct1(serialised LWE ciphertext vectors).- Raises:
FEKeyError – If public parameters or encryption keys are missing.
FEValidationError – If plaintext length or values are invalid.
- decrypt(dct_ct, dk, fusion_weight)[source]¶
Decrypt a ciphertext to recover the inner product ⟨x, y⟩.
- Parameters:
dk (
dict) – Decryption key fromSIFEFullySecLWEKeyGenerator.get_decryption_keys().fusion_weight (
list) – Integer weight vector y.
- Returns:
The inner product, or
Noneif it decodes beyondeta X Y(wrong key or ciphertext).- Raises:
FEKeyError – If decryption key is missing.
FESchemeError – If fusion_weight are not the key’s weights.
FEValidationError – If fusion weight or ciphertext are malformed.
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Encrypt a list of ndarrays element-wise (requires
eta=1).
- compute_lst_ndarray_ct(dict_ndarray_ct, **kwargs)[source]¶
Aggregate ndarray ciphertexts (delegates to
decrypt_lst_ndarray_ct()).
Ring-LWE¶
Ring-LWE-Based Single-Input Inner-Product Functional Encryption
| Based on
| “Efficient Lattice-Based Inner-Product Functional Encryption”
| By Bermudo Mera, Karmakar, Marc, Soleimanian
| ePrint: 2021/046
|
| (PKC 2022), Section 4 (selectively secure Ring-LWE IPFE) with the batching
| of Remark 1; also informed by GoFE’s innerprod/simple/ringlwe.go.
type: public-key encryption
setting: R_q = Z_q[x] / (x^ring_n + 1), ring_n a power of two
Public a; s_i, e_i <- D_sigma1, pk_i = a s_i + e_i. The key for y
is sk_y = sum y_i s_i. A plaintext is an eta x k matrix (k <= ring_n,
column j in coefficient j): ct0 = a r + f0,
ct_i = pk_i r + f_i + Delta x_i with r, f0 <- D_sigma2,
f_i <- D_sigma3; decryption rounds sum y_i ct_i - ct0 sk_y. Parameters
come from pyfe4ai.primitives.lattice.ring_lwe_utils.bmms21_parameters(); ring_n
defaults to the toy value DEFAULT_RING_N (versions <= 0.2.0 claimed to
derive it but always chose 32).
- class pyfe4ai.schemes.sife.ring_lwe.SIFERingLWEKeyGenerator(config, **kwargs)[source]¶
Bases:
IPFEAbsKeyGenerator,ParameterCacheMixinKey generator for Ring-LWE-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE Ring-LWE key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:sec_param(kappaof the noise bounds),eta,bound_x,bound_yandring_n(defaultDEFAULT_RING_N;"auto"for the smallest dimension meeting the 128-bit table, thestandardprofile’s choice) andgaussian_sampler("facct", the default, or"rounded"; seescheme_sampler()).ring_modulusmust stay"prime": the opt-in RNS modulus is implemented for the MIFE / MCFE family only.- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
A dict of public parameters, or
Noneon error.
- class pyfe4ai.schemes.sife.ring_lwe.SIFERingLWE(config, **kwargs)[source]¶
Bases:
IPFEAbsCryptoCrypto operations for Ring-LWE-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE Ring-LWE crypto object.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters) and optionallysk(encryption keys);gaussian_sampler: that of the encryption noise (default: that ofpp, else"facct").- Return type:
None
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Not implemented for this scheme; raises
NotImplementedError.
Adaptively Secure Ring-LWE¶
Adaptively secure Ring-LWE single-input inner-product FE.
pyfe4ai.schemes.sife.fullysec_lwe).type: public-key encryption, adaptive IND security
setting: R_q = Z_q[x] / (x^ring_n + 1), q an NTT-friendly prime
Construction (l = eta slots, m key polynomials, Delta = floor(q / p)):
Setup:
a = (a_1, ..., a_m) <- R_q^muniform with somea_jinvertible;s_i = (s_i1, ..., s_im),s_ij <- D_sigma1;pk_i = <a, s_i>(no error term).Encrypt:
r <- D_sigma2,f0 <- D_sigma2^m,f_i <- D_sigma3;ct0 = a r + f0,ct_i = pk_i r + f_i + Delta x_i(constant coefficient,Delta x_ilinear inx_ias the proof needs); resampled until somect0_jis invertible andct0is proportional toain no CRT slot.KeyGen:
sk_y = sum_i y_i s_i(mpolynomials).Decrypt:
d = sum_i y_i ct_i - <ct0, sk_y>; round its constant coefficient.
Deviations from the paper:
m >= 5key polynomials instead ofm = 3. With the constraints of Appendix C.1,m = 3admits no modulus: Theorem 2 (k = 2) needs thes*of game G4 -> G5 to have widthsigma' >= sqrt(n ln(2mn(1 + 1/delta)) / pi) q^(2/m + eps/2), G3 -> G4 needssigma1 >= sqrt(l) 2X sigma', Theorem 1 needssigma2 > sigma n C sqrt(l + 2)withC = sqrt(kappa) sigma1, and the decryption noisel Y (sqrt(kappa) sigma3 + m n kappa sigma1 sigma2)then grows likeq^(4/m)while it must stay belowq / 2p. Theorem 2 holds for everym >= 3, so the proof is unchanged.m = "auto"(default) takes the smallestmthat admits a modulus;pyfe4ai.primitives.lattice.ring_lwe_utils.bmms21_adaptive_parameters()derives the widths andq.Signed inputs
|x| <= X,|y| <= Y:p = 2 l X Y + 2with centred decoding,||x1 - x0||_inf <= 2X, and complexity leveraging over(2X + 1)^(2l)challenge pairs.Gaussian samples (keys and encryption noise) are exact
D_{Z,sigma}by default (gaussian_sampler = "facct",discrete_gaussian_facct()), whatever the library-wide default;"rounded"(a rounded continuous Gaussian, the library default) stays selectable. Rounded keys are0.02 / sigma1^2per sample, overm n etasamples, fromD_{Z,sigma1}in statistical distance for an ideal rounded Gaussian – in the standard configurations from about2^-47(elementwiseeta = 1,X = 100) over2^-44.5(packedeta = 1) to2^-40.5(eta = 4,X = Y = 4), negligible abovesigma1 = 2^40– and about2^-12ateta = 1with the double-precision path’s artifacts (crypto review, October 2026), terms the proof does not account for. Python FACCT is slower than the rounded sampler at the key widthsigma1but faster beyond2^40(the encryption widths), where the rounded sampler needs MPFR Box-Muller.
Ciphertext layouts (ndarray_layout):
"elementwise"(default): one vector per ciphertext; the ndarray helper encrypts every element on its own."packed"(opt-in, experimental, its own parameter record; the leveraging argument below is this project’s own, checked independently but not published or externally reviewed): a ciphertext holds aneta x kmatrix,k <= ring_n(Remark 1:Delta x_ijis added to coefficientjofct_i), and decrypts to thekinner products<x_j, y>of its columns. The ndarray helper packsring_nelements per ciphertext. The statistical games G3* - G5* of the proof depend on the challenge only through the spanVof the differencesx1_j - x0_j, so the leveraging ranges over the possibleV,(D + 1) (4X + 1)^(l D)withD = min(l, ring_n), whateverkis (guessing both challenge matrices would give(2X + 1)^(2lk)); G3 -> G4 decomposes along a basisBofV,||B|| <= 2X sqrt(l D), whichsigma1absorbs, and G4 -> G5 applies Theorem 2 once per basis vector (pyfe4ai.primitives.lattice.ring_lwe_utils.bmms21_adaptive_leveraging()). G5* writes the differences in that basis modq, soqmust exceed the minors of the basis,(2X sqrt(D))^D; the parameters enforce it (it moves e.g.eta = 24,X = 4to a larger ring). Foreta = 1,Vis{0}orQ: two guesses, and the basis[1]of norm 1 instead of2X(X = 100,Y = 1:m = 12and a 107-bitqagainstm = 19and 111 bits elementwise, whose parameters stay as they are). Encryptors and decryptors acceptppflagged"packed"only if itsq,pand widths are the packed derivation.
Under the standard profile ring_n = "auto" takes the smallest ring
dimension (with the smallest m) whose q meets
RING_LWE_128_LOG_Q at the width
sigma (about 8) of the RLWE problem of Theorem 1.
- pyfe4ai.schemes.sife.fullysec_ring_lwe.LAYOUTS = ('elementwise', 'packed')¶
Values of the
ndarray_layoutoption; the first is the default.
- pyfe4ai.schemes.sife.fullysec_ring_lwe.DEFAULT_SAMPLER = 'facct'¶
the exact
D_{Z,sigma}of the proof, whatever the library-wide default is.- Type:
Default Gaussian sampler of this scheme (
gaussian_sampleroption)
- pyfe4ai.schemes.sife.fullysec_ring_lwe.encode_message(x, q, p)[source]¶
floor(q / p) x mod q: linear inx, as the last game of the proof needs.
- pyfe4ai.schemes.sife.fullysec_ring_lwe.independent_at_every_slot(a_ntt, c_ntt, q)[source]¶
Trueiff(a(t), c(t))has rank 2 overZ_qin every CRT slott.a_ntt and c_ntt hold
mNTT vectors each. Thenx -> (<a, x>, <c, x>)mapsR_q^montoR_q^2(the condition of the Ring-LHL step, which the paper states as “ct0is not a multiple ofa”).
- class pyfe4ai.schemes.sife.fullysec_ring_lwe.SIFEFullySecRingLWEKeyGenerator(config, **kwargs)[source]¶
Bases:
IPFEAbsKeyGenerator,ParameterCacheMixinKey generator for the adaptively secure Ring-LWE IPFE of BMMS21 (Sec. 5).
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:sec_param(kappa),eta,bound_x,bound_y,ring_n(power of two,"auto", orNonefor the toy default),m(number of key polynomials, at least 5, or"auto", the default),ndarray_layout("elementwise", the default, or"packed": up toring_nvectors per ciphertext, with parameters of their own) andgaussian_sampler("facct", the default, or"rounded") for the keys, also published inppas the encryptors’ default.- Raises:
FEValidationError – For an unknown
ndarray_layoutor sampler, or aring_modulusother than"prime"(the adaptive proof’s Ring-LHL, Theorem 2, is for a primeq; see RNS modulus for the Ring-LWE schemes: security review).- Return type:
None
- get_public_parameters()[source]¶
Return
a,p,q,ring_n,m,eta, the bounds and the encryption widthssigma2,sigma3, thegaussian_sampler(andndarray_layoutwhen packed).- Return type:
- class pyfe4ai.schemes.sife.fullysec_ring_lwe.SIFEFullySecRingLWE(config, **kwargs)[source]¶
Bases:
IPFEAbsCryptoCrypto operations for the adaptively secure Ring-LWE IPFE of BMMS21 (Sec. 5).
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise with
keys.ppand, for encryptors,keys.sk; the optionalgaussian_sampler("facct"or"rounded") of the encryption noise defaults to that ofpp, else"facct".- Raises:
FEValidationError – For an unknown sampler.
- Parameters:
config (
dict)- Return type:
None
- encrypt(lst_pt)[source]¶
Encrypt an integer vector of length
etaor, with packed parameters, aneta x kmatrix (etarows ofk <= ring_nintegers; columnjgoes to coefficientj).- Return type:
- Returns:
Dict with
ct0(mpolynomials) andct(etapolynomials); for a matrix alsok.- Raises:
FEKeyError – If public parameters or the encryption key are missing.
FEValidationError – If the plaintext is malformed or out of bound, or is a matrix without packed parameters (their
sigma1and leveraging cover only one vector per ciphertext).
- Parameters:
lst_pt (
list)
- decrypt(dct_ct, dk, fusion_weight)[source]¶
Return
<x, y>, orNoneif the decoded value exceedseta X Y; for a packed ciphertext (one withk) the list of thekinner products, orNoneif one of them exceeds the bound.- Raises:
FEKeyError – If the key is missing.
FESchemeError – If fusion_weight differs from the key’s weights.
FEValidationError – If the ciphertext does not match the parameters.
- Parameters:
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Encrypt ndarrays (
eta = 1): one ciphertext per element, or with packed parametersring_nconsecutive elements (row-major) per ciphertext.A packed layer is
{"shape", "first_chunk", "chunks"}, its chunks packed ciphertexts numbered consecutively across the layers (the layout of the MCFE Ring-LWE schemes, whichEncryptedGradientserialises).
- compute_lst_ndarray_ct(dict_ndarray_ct, **kwargs)[source]¶
Decrypt ndarray ciphertexts (delegates to
decrypt_lst_ndarray_ct()).
Paillier¶
Paillier-Based Single-Input Inner-Product Functional Encryption | From “Fully Secure Functional Encryption for Inner Products, | from Standard Assumptions” | By Shweta Agrawal, Benoit Libert, and Damien Stehle | Published in: CRYPTO 2016 (DCR instantiation; recalled as Fig. 9 of | ABMPSW20, https://eprint.iacr.org/2020/788, Appendix B.1)
type: public-key encryption
setting: Integer based (Z_{N^2}^*, N = p q with safe primes)
Construction: g = g'^{2N} mod N^2; s <- D_{Z^eta, sigma} with
sigma > sqrt(kappa) * N^{5/2}; h_i = g^{s_i}; ct = (g^r,
(1 + N)^{x_i} h_i^r) with r <- {0..N/4}; sk_y = <s, y> over Z;
<x, y> = (prod ct_i^{y_i} ct_0^{-sk_y} - 1 mod N^2) / N. The Gaussian
is a rounded continuous Gaussian at bits(sigma) + 128 bits of precision
and kappa is the config key stat_param (default 64).
- class pyfe4ai.schemes.sife.paillier.SIFEPaillierKeyGenerator(config, **kwargs)[source]¶
Bases:
IPFEAbsKeyGenerator,ParameterCacheMixinKey generator for Paillier-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE Paillier key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:eta,bit_length(bits of each prime ofN, default 128),bound_x,bound_yandstat_param(default 64).- Return type:
None
- setup()[source]¶
Sample
s <- D_{Z^eta, sigma}withsigma > sqrt(kappa) N^{5/2}(ALS16).Versions <= 0.2.0 drew
|s_i| <= max(sec_param, bound_y * eta), soscould be recovered from the public key by brute force.- Return type:
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
A dict of public parameters, or
Noneon error.
- class pyfe4ai.schemes.sife.paillier.SIFEPaillier(config, **kwargs)[source]¶
Bases:
OfflineRandomMixin,IPFEAbsCryptoCrypto operations for Paillier-based single-input inner-product FE.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE Paillier crypto object.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters) and optionallysk(encryption keys).- Return type:
None
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Encrypt a list of ndarrays element-wise (requires
eta = 1).- Parameters:
lst_ndarray (
list) – List of numpy arrays, scaled by10^precision.- Return type:
- Returns:
One object array of ciphertexts per input array.
- Raises:
NotImplementedError – If
eta != 1.
FH-IPE (Pairing)¶
Function-Hiding Inner-Product Encryption over Pairings
| “Function-Hiding Inner Product Encryption is Practical”
| By Kim, Lewi, Mandal, Montgomery, Roy, Wu, SCN 2018 (ePrint 2016/440),
| Section 3; structure as in GoFE’s innerprod/fullysec/fhipe.go.
type: secret-key encryption with function-hiding keys
setting: asymmetric pairing group (default BLS12-381); secure in the generic bilinear group model
B <- GL_n(Z_q) (rejection sampling), B* = det(B) (B^{-1})^T. The key for
y is (g1^{alpha det B}, g1^{alpha B y}), a ciphertext of x is
(g2^beta, g2^{beta B* x}); decryption pairs them and solves a bounded
discrete log of e(g1, g2)^{alpha beta det B <x, y>} to base
e(g1, g2)^{alpha beta det B}. Keys live in G1 and ciphertexts in G2, as in
the paper (B used transposed, which is identically distributed).
Deviation: every vector is padded as x' = (x, 1, 0), y' = (y, 0, 1)
(<x', y'> = <x, y>) so that n = eta + 2 >= 3 and no vector is zero: with
n = 1 (B* = 1) ciphertexts and keys revealed x and y directly,
and an all-zero vector was recognisable without a key – the paper requires
non-zero vectors. The encryption key (g2, B*) determines B up to a
scalar and is master-secret equivalent.
- class pyfe4ai.schemes.sife.fh_ipe_pairing.SIFEFHIPEPairingKeyGenerator(config, **kwargs)[source]¶
Bases:
IPFEAbsKeyGenerator,ParameterCacheMixinKey generator for function-hiding inner-product encryption over pairings.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE FH-IPE key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:eta,bound_x,bound_yandpairing_group_param(asymmetric group, default"BLS12-381").- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
A dict of public parameters, or
Noneon error.
- class pyfe4ai.schemes.sife.fh_ipe_pairing.SIFEFHIPEPairing(config, **kwargs)[source]¶
Bases:
IPFEAbsCryptoCrypto operations for function-hiding inner-product encryption over pairings.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE FH-IPE crypto object.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters) and optionallysk(encryption keys).- Return type:
None
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Not implemented for this scheme; raises
NotImplementedError.
Partial FH-IPE (Pairing)¶
Partially Function-Hiding Inner-Product Encryption over Pairings
| “A New Paradigm for Public-Key Functional Encryption for Degree-2 Polynomials”
| By Romain Gay, PKC 2020 (ePrint 2020/093) – Fig. 8, CPA variant (no
| QANIZK), with k = 1 (SXDH); structure as in GoFE’s
| innerprod/fullysec/part_fh_ipe.go.
type: public-key encryption for vectors in the span of a public matrix
M; secret-key encryption (Enc') of arbitrary vectorssetting: asymmetric pairing group (default BLS12-381)
a, b <- (1, Z_q), U in Z_q^{(eta+2) x 2}, V in Z_q^{eta x 2} and a
random full-rank M in Z^{eta x k} with k = subspace_dim < eta; the
public key is ([a]_1, [U a]_1, V^T M, M) and msk = (b, U, V).
Enc(t):
[c = a r ; (-V^T M t ; M t) + U c]_1fort in Z^k.Enc’(x): the same with
(-V^T x ; x); needsV, so it is run by the key generator (SIFEPartFHIPEPairingKeyGenerator.sec_encrypt()).KeyGen(y):
[(-U^T w ; w)]_2withw = (b s ; y + V b s).Dec:
prod_j e(ct_j, sk_j) = [<x, y>]_Tand a bounded discrete log.
Every key holder learns M^T y (encrypt the unit vectors t = e_j and
decrypt), the leakage the paper allows; for an integer y with
|y_i| <= bound this often determines y unless eta - k is large, so
k defaults to 1 – the public encryption space and the leakage have the
same dimension k. Public encryption requires |t_i| <= coeff_bound and
|M t| <= bound so that the final discrete log is feasible. Versions
<= 0.2.0 handed the master secret key to every encryptor and, by default,
used a square M (k = eta), which reveals V and with it y.
Deviations: M and V^T M are published in the clear instead of in G1.
- class pyfe4ai.schemes.sife.part_fh_ipe_pairing.SIFEPartFHIPEPairingKeyGenerator(config, **kwargs)[source]¶
Bases:
IPFEAbsKeyGenerator,ParameterCacheMixinKey generator for partially function-hiding inner-product encryption over pairings.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE partially FH-IPE key generator.
- Parameters:
config (
dict) – Scheme configuration. Recognised keys:eta,bound(orbound_x),subspace_dim(1 <= subspace_dim < eta, default 1),coeff_bound(bound on the coefficientstof public encryption, default 1) andpairing_group_param(asymmetric group, default"BLS12-381").- Return type:
None
- get_public_parameters()[source]¶
Return serialisable public parameters.
- Return type:
- Returns:
A dict of public parameters, or
Noneon error.
- get_private_keys(nid='nid_default', **kwargs)[source]¶
Public-key scheme: encryptors need the public parameters only.
Returns
None; versions <= 0.2.0 returned the master secret key.
- class pyfe4ai.schemes.sife.part_fh_ipe_pairing.SIFEPartFHIPEPairing(config, **kwargs)[source]¶
Bases:
IPFEAbsCryptoCrypto operations for partially function-hiding inner-product encryption over pairings.
- Parameters:
config (
dict)
- __init__(config, **kwargs)[source]¶
Initialise the SIFE partially FH-IPE crypto object.
- Parameters:
config (
dict) – Must containkeyswithpp(public parameters); encryption is public-key.- Return type:
None
- encrypt_lst_ndarray(lst_ndarray, **kwargs)[source]¶
Not implemented for this scheme; raises
NotImplementedError.