fhelium.values.keys
Tensor-backed CKKS key value types.
SecretKey
class View source
SecretKey(data: torch.Tensor, prime_ids: tuple[int, ...], polynomial_domain: PolynomialDomain = 'ntt', modulus_basis: ModulusBasis = 'QP', residue_representation: ResidueRepresentation = 'montgomery')Bases: TensorResident
RNS storage for the secret polynomial
data is a dense integral [limb, coefficient_or_ntt_index] tensor; row prime_ids[i]. Engine-generated keys are depth-zero Q or QP values in NTT domain and Montgomery form on the engine device, with final extent clone allocates independent storage; residency views may alias their source. The key carries representation metadata but no device owner or persistence policy.
Attributes
| Name | Type | Default/value |
|---|---|---|
data | torch.Tensor | |
prime_ids | tuple[int, ...] | |
polynomial_domain | PolynomialDomain | 'ntt' |
modulus_basis | ModulusBasis | 'QP' |
residue_representation | ResidueRepresentation | 'montgomery' |
clone
method
def clone() -> SecretKey: ...Return the same key value in independent tensor storage.
PublicKey
class View source
PublicKey(data: torch.Tensor, prime_ids: tuple[int, ...], polynomial_domain: PolynomialDomain = 'ntt', modulus_basis: ModulusBasis = 'Q', residue_representation: ResidueRepresentation = 'montgomery')Bases: TensorResident
Public encryption key for one destination secret polynomial.
data is a dense integral [key_component=2, limb, coefficient_or_ntt_index] tensor. In each RNS row the generated components satisfy
where modulus_basis. Row prime_ids[i]; generated keys are depth-zero NTT-domain Montgomery residues on one device. The object does not record a symbolic key-lineage identifier, so callers must keep the key paired with its destination secret key. Direct construction and component access retain/share storage; clone allocates independent storage.
Attributes
| Name | Type | Default/value |
|---|---|---|
data | torch.Tensor | |
prime_ids | tuple[int, ...] | |
polynomial_domain | PolynomialDomain | 'ntt' |
modulus_basis | ModulusBasis | 'Q' |
residue_representation | ResidueRepresentation | 'montgomery' |
k0
property
k0: torch.Tensork1
property
k1: torch.Tensorcomponent
method
def component(component_id: int) -> torch.Tensor: ...Return a storage-sharing [limb, ntt_index] component view.
clone
method
def clone() -> PublicKey: ...KeySwitchKey
class View source
KeySwitchKey(data: torch.Tensor, prime_ids: tuple[int, ...], digit_prime_ids: tuple[tuple[int, ...], ...], polynomial_domain: PolynomialDomain = 'ntt', modulus_basis: ModulusBasis = 'QP', residue_representation: ResidueRepresentation = 'montgomery')Bases: TensorResident
Hybrid-RNS material for one source-to-destination key relation.
A key generated from
to an equivalent destination phase
up to configured key-switch error. The object does not store symbolic source/destination identifiers; the caller must preserve that direction.
data is a dense integral [key_digit, key_component=2, limb, coefficient_or_ntt_index] tensor. key_digit is stable key-storage identity, not the local active digit_index used at a later depth. Limb row prime_ids[i]. digit_prime_ids[d] is the Q support encrypted by stored plane d. Storage lists the supported Q rows first, followed by the selected auxiliary rows; global prime IDs need not increase across that Q/P join. On row i its phase is clone allocates independent storage.
Attributes
| Name | Type | Default/value |
|---|---|---|
data | torch.Tensor | |
prime_ids | tuple[int, ...] | |
digit_prime_ids | tuple[tuple[int, ...], ...] | |
polynomial_domain | PolynomialDomain | 'ntt' |
modulus_basis | ModulusBasis | 'QP' |
residue_representation | ResidueRepresentation | 'montgomery' |
digit_count
property
digit_count: intdigit
method
def digit(key_digit_index: int) -> torch.Tensor: ...Return a storage-sharing [key_component, limb, index] view.
digit_component
method
def digit_component(key_digit_index: int, component_id: int) -> torch.Tensor: ...Return a storage-sharing [limb, index] key-component view.
clone
method
def clone() -> Self: ...RotationKey
class View source
RotationKey(data: torch.Tensor, prime_ids: tuple[int, ...], digit_prime_ids: tuple[tuple[int, ...], ...], polynomial_domain: PolynomialDomain = 'ntt', modulus_basis: ModulusBasis = 'QP', residue_representation: ResidueRepresentation = 'montgomery', *, rotation_step: int)Bases: KeySwitchKey
Key-switch material from
rotation_step is the normalized signed user-visible displacement torch.roll(m, shifts=r).
Attributes
| Name | Type | Default/value |
|---|---|---|
rotation_step | int |
normalize_step
method
def normalize_step(step: int, *, ring_dimension: int) -> int: ...Map a step modulo [-S/2, S/2).
RelinearizationKey
class View source
RelinearizationKey(data: torch.Tensor, prime_ids: tuple[int, ...], digit_prime_ids: tuple[tuple[int, ...], ...], polynomial_domain: PolynomialDomain = 'ntt', modulus_basis: ModulusBasis = 'QP', residue_representation: ResidueRepresentation = 'montgomery')Bases: KeySwitchKey
Key-switch material from source key
It replaces the
ConjugationKey
class View source
ConjugationKey(data: torch.Tensor, prime_ids: tuple[int, ...], digit_prime_ids: tuple[tuple[int, ...], ...], polynomial_domain: PolynomialDomain = 'ntt', modulus_basis: ModulusBasis = 'QP', residue_representation: ResidueRepresentation = 'montgomery')Bases: KeySwitchKey
Key-switch material from
After the conjugation automorphism it restores the original key relation, producing semantic slots
RotationKeySet
class View source
RotationKeySet(table: dict[int, RotationKey] = field(default_factory=dict))Bases: MutableMapping[int, RotationKey]
Mapping from normalized signed rotation steps to matching local keys.
Attributes
| Name | Type | Default/value |
|---|---|---|
table | dict[int, RotationKey] | field(default_factory=dict) |
add
method
def add(key: RotationKey) -> RotationKeySet: ...Install a key under its self-described normalized rotation step.
EvaluationKeyRequirements
class View source
EvaluationKeyRequirements(rotation_steps: frozenset[int] = frozenset(), requires_relinearization: bool = False, requires_conjugation: bool = False)Evaluation-key roles and rotations required by one evaluator.
This is a value-independent capability description. It contains no key tensors, device placement, generation policy, or secret-key material. Consumers derive requirements; applications decide how to generate, load, distribute, and retain matching keys.
Attributes
| Name | Type | Default/value |
|---|---|---|
rotation_steps | frozenset[int] | frozenset() |
requires_relinearization | bool | False |
requires_conjugation | bool | False |
EvaluationKeySet
class View source
EvaluationKeySet(keys: Iterable[_EvaluationKey]=())Application-owned references to evaluation keys with different layouts.
Entries are ordinary rotation, relinearization and conjugation key values. Adding an existing object retains one reference; distinct objects remain distinct even when they share storage or represented metadata. The inventory never generates, transfers or copies keys. Callers keep every entry paired with its intended secret relation and modulus parameters; prime identifiers and structural selection do not establish those cryptographic identities.
Selection uses active Q/P rows, ring dimension, dtype and device supplied by the consumer. With all facts known, rotation groups prefer fewer primitive rotations, then fewer active-digit applications. Single-role selection prefers fewer active digits. Both then prefer smaller stored payloads and insertion order. Missing facts permit a unique candidate only. A selected RotationKeySet is a step-to-key mapping, while this inventory may retain several candidates for the same step. Selection returns references without changing entries.
add
method
def add(key: _EvaluationKey) -> EvaluationKeySet: ...Retain one reference to a supported evaluation-key object.
update
method
def update(keys: Iterable[_EvaluationKey]) -> EvaluationKeySet: ...Add supplied objects without replacing or moving existing keys.
remove
method
def remove(key: _EvaluationKey) -> None: ...Remove this object reference, raising KeyError when it is absent.
clear
method
def clear() -> None: ...Drop inventory references while preserving references held by consumers.
rotation_keys
property
rotation_keys: tuple[RotationKey, ...]relinearization_keys
property
relinearization_keys: tuple[RelinearizationKey, ...]conjugation_keys
property
conjugation_keys: tuple[ConjugationKey, ...]select_rotations
method
def select_rotations(steps: Iterable[int], *, allow_composed: bool=False, q_prime_ids: tuple[int, ...] | None=None, p_prime_ids: tuple[int, ...] | None=None, ring_dimension: int | None=None, dtype: torch.dtype | None=None, device: torch.device | str | None=None, key_prime_ids: tuple[int, ...] | None=None, digit_prime_ids: tuple[tuple[int, ...], ...] | None=None) -> RotationKeySet | None: ...Select a complete shared-layout rotation group, or leave it unresolved.
With allow_composed, each requested step uses a direct key when available in that layout group, otherwise its signed-power-of-two path. The returned mapping contains the primitive keys for those paths. Group comparison counts each path invocation, including repeated use of the same primitive key; payload size counts each selected key once. Existing key operands may constrain key_prime_ids and digit_prime_ids. Zero steps require no key. Active Q intersections retain stored plane identities; selection never repartitions key data. Omitted p_prime_ids leaves auxiliary rows unconstrained; each candidate supplies its own known P. Unknown source geometry remains unresolved.
select_relinearization
method
def select_relinearization(*, q_prime_ids: tuple[int, ...] | None=None, p_prime_ids: tuple[int, ...] | None=None, ring_dimension: int | None=None, dtype: torch.dtype | None=None, device: torch.device | str | None=None, key_prime_ids: tuple[int, ...] | None=None, digit_prime_ids: tuple[tuple[int, ...], ...] | None=None) -> RelinearizationKey | None: ...Select relinearization material, with an optional auxiliary-row constraint.
select_conjugation
method
def select_conjugation(*, q_prime_ids: tuple[int, ...] | None=None, p_prime_ids: tuple[int, ...] | None=None, ring_dimension: int | None=None, dtype: torch.dtype | None=None, device: torch.device | str | None=None, key_prime_ids: tuple[int, ...] | None=None, digit_prime_ids: tuple[tuple[int, ...], ...] | None=None) -> ConjugationKey | None: ...Select conjugation material, with an optional auxiliary-row constraint.