fhelium.backend.ckks.crypto._key_generation
CKKS secret, public, rotation, conjugation, and key-switch key generation.
KeyGenerationResource
class View source
KeyGenerationResource(config: CkksConfig, rng: Csprng, rns_context: RnsContext, ntt_context: NttContext, p_product_montgomery_q: torch.Tensor)Bind context, arithmetic, and random resources for one key device.
Attributes
| Name | Type | Default/value |
|---|---|---|
config | CkksConfig | |
rng | Csprng | |
rns_context | RnsContext | |
ntt_context | NttContext | |
p_product_montgomery_q | torch.Tensor |
create
method
def create(*, config: CkksConfig, rng: Csprng, rns_context: RnsContext, ntt_context: NttContext) -> KeyGenerationResource: ...Build key-generation scalars on one concrete context device.
for_config
method
def for_config(config: CkksConfig, *, dtype: torch.dtype | None=None) -> KeyGenerationResource: ...Prepare another modulus basis on this device and random stream.
device
property
device: torch.deviceReturn the concrete device shared by all key-generation resources.
CkksKeyGenerator
class View source
CkksKeyGenerator()Construct CKKS keys from caller-supplied device resources and secret relations.
Key payloads use configured integral dtype and prime-row order. Secret-key data is [limb, ntt_index]; public keys are [key_component, limb, ntt_index]; key-switch keys are [key_digit, key_component, limb, ntt_index]. Returned keys are always NTT/Montgomery/lazy at depth zero in the stated Q or QP basis and own their payload storage. Local digit_index is resolved to stable key_digit_index before key tensor indexing.
convert_secret_key
method
def convert_secret_key(resources: KeyGenerationResource, target: KeyGenerationResource, secret_key: SecretKey) -> SecretKey: ...Re-express the centered secret polynomial in another RNS basis.
Inverse NTT, centered CRT extension and target NTT preserve the polynomial modulo the target primes. The original source basis defines its centered representative. Destination storage and Montgomery radix belong to target; no sampling or input mutation occurs.
prepare_secret_key
method
def prepare_secret_key(resources: KeyGenerationResource, coefficients: torch.Tensor, *, modulus_basis: ModulusBasis='QP') -> SecretKey: ...Lift caller-supplied integer coefficients and compute NTT(s)R.
coefficients has shape [N] on the resource device and uses an integral dtype. The returned key owns Q or QP storage. This operation does not sample, infer a secret distribution, or alter the source.
create_secret_key
method
def create_secret_key(resources: KeyGenerationResource, *, modulus_basis: ModulusBasis='QP', hamming_weight: int | None=None) -> SecretKey: ...Sample ternary s and return its depth-zero NTT/Montgomery RNS.
With no weight, coefficients are independent uniform {-1,0,1}. A supplied h selects a uniform h-element support with independent uniform signs. Sorting distinct 64-bit CSPRNG labels samples a uniform permutation; collisions cause the labels to be resampled. Both label and sign sampling consume the supplied cryptographic random stream. The output owns [limb, ntt_index] storage on its resource device.
create_public_key
method
def create_public_key(resources: KeyGenerationResource, secret_key: SecretKey, *, modulus_basis: ModulusBasis='Q', uniform_component: torch.Tensor | None=None, error_coefficients: torch.Tensor | None=None) -> PublicKey: ...Generate (k_0,k_1) satisfying
Output is integral [key_component=2, limb, ntt_index] in depth-zero NTT/Montgomery form with Q or QP rows. secret_key and optional sampled uniform/error coefficients are read-only and never alias the returned stacked tensor. When error coefficients are omitted, the generator samples its configured discrete Gaussian.
create_key_switch_key
method
def create_key_switch_key(resources: KeyGenerationResource, source_secret_key: SecretKey, destination_secret_key: SecretKey, *, uniform_component_by_key_digit: torch.Tensor | None=None, digit_prime_ids: tuple[tuple[int, ...], ...] | None=None, p_prime_ids: tuple[int, ...] | None=None, source_depth: int=0, source_multiplier: int=1, error_coefficients_by_key_digit: torch.Tensor | None=None) -> KeySwitchKey: ...Create a hybrid-RNS key from source to destination secret relation.
Each hybrid digit is constructed through a public-key encryption.
Stable key digit [key_digit, key_component=2, QP_limb, ntt_index] in NTT/Montgomery lazy form and source-depth Q followed by the selected P. Omitted p_prime_ids preserves the original auxiliary basis. Supplied auxiliary IDs select distinct catalog primes outside active Q; all planes are newly sampled for that P relation. Input keys and optional sampled uniform/error coefficients are not mutated or aliased.
create_encapsulation_keys
method
def create_encapsulation_keys(resources: KeyGenerationResource, source_secret_key: SecretKey, intermediate_secret_key: SecretKey, *, source_depth: int, low_p_moduli: tuple[int, ...], return_prime: int, return_p_moduli: tuple[int, ...]) -> tuple[KeySwitchKey, KeySwitchKey]: ...Generate low s→t digits and one guard-scaled t→s return hint.
Low digits encrypt P_lowE_js under t. The return digit encrypts guardP_returnt under s across [guard,Q,P_return]. Both secrets are supplied by the caller; this factory samples only public-key randomness and error on the shared CSPRNG. It returns ordinary KeySwitchKey values.
create_relinearization_key
method
def create_relinearization_key(resources: KeyGenerationResource, secret_key: SecretKey, *, source_depth: int=0, digit_prime_ids: tuple[tuple[int, ...], ...] | None=None, p_prime_ids: tuple[int, ...] | None=None) -> RelinearizationKey: ...Return QP key material that switches the
The returned state and layout equal create_key_switch_key; the input secret key remains NTT/Montgomery QP and is not mutated.
create_rotation_key
method
def create_rotation_key(resources: KeyGenerationResource, rotation_step: int, *, uniform_component_by_key_digit: torch.Tensor | None=None, secret_key: SecretKey, source_depth: int=0, digit_prime_ids: tuple[tuple[int, ...], ...] | None=None, p_prime_ids: tuple[int, ...] | None=None) -> RotationKey: ...Construct QP key material from
rotation_step follows signed slot displacement and is stored as metadata. The distinct galois_element
create_conjugation_key
method
def create_conjugation_key(resources: KeyGenerationResource, secret_key: SecretKey, *, source_depth: int=0, digit_prime_ids: tuple[tuple[int, ...], ...] | None=None, p_prime_ids: tuple[int, ...] | None=None) -> ConjugationKey: ...Construct QP key material from
Output uses key-switch-key axes and NTT/Montgomery QP state; the input secret key remains unchanged.