Skip to content

CKKS concepts

CKKS represents approximate real or complex values. Ren's CKKS layer handles encoding, encryption, arithmetic, key switching, levels, rescale, and optional bootstrapping on top of the polynomial engine. Read CKKS workflow first if you need the runnable path.

Objects

Object Role
CKKSParams Ring, levels, scales, key-switching primes, bootstrap settings, and runtime flags.
CKKSContext Active parameter and key context used by encode, encrypt, decrypt, rotations, and level transitions.
Plaintext Encoded slot vector backed by one Poly.
Ciphertext Encrypted value backed by two Poly components, a and b.

Use with ctx: around CKKS operations that need the active context. That includes encryption, decryption, level lookup, key switching, and many arithmetic alignment paths.

Levels

Ren uses an explicit level schedule. The level model is:

levels[level] = (active moduli, nominal scale)
default_level = fresh-encryption level
highest_level = top level in the full schedule

Levels index active modulus bases. Level 0 is the bottom of the schedule. Fresh encryptions start at default_level for normal computation. Parameter sets with a bootstrap tail reserve levels above default_level for bootstrapping support.

Multiplication grows scale and noise. Rescale and level-transition work drops moduli and moves the ciphertext down the schedule. to_level(level) explicitly drops a plaintext or ciphertext to a lower level when operands need alignment. Bootstrapping uses support levels above the normal compute range when the parameter set enables it.

Scale

Scale is CKKS's fixed-point denominator. Encoding a slot value stores something close to value * scale in the polynomial representation, then decoding divides by the current scale to recover an approximate value.

Each level has a nominal scale. Multiplication multiplies the represented values, but it also grows the internal scale and noise. Rescale drops part of the modulus basis and moves the ciphertext to the next level so the decoded value remains approximately the same while the bookkeeping scale returns to the level schedule.

The main invariant to keep in mind is:

same represented value ~= polynomial coefficients / current scale

Ren tracks polynomial-ratio and message-ratio terms inside CKKSTransition.rescale_step(...) to preserve that invariant. The polynomial ratio describes how rescale transforms coefficients; the message ratio describes how callers interpret the decoded value against the destination scale.

Message bounds

msg_bound is public operation metadata. Ren uses it for correctness and noise checks. Do not compute it from secret values.

Message bounds are public

Do not write msg_bound=max(abs(v) for v in secret_values). Choose a bound from the public input contract.

Keys

Fresh encryption needs encryption key material in the active context. Multiplication needs a relinearization key after ciphertext-ciphertext multiplication introduces an extra secret-power component. Rotation needs the matching rotation key. Conjugation needs a conjugation key.

keygen(params) creates a local context with a secret key, public key, relinearization keys, rotation keys, and a conjugation key when the parameter set supports conjugation. Use derive_context(...) when a caller already has a secret key or public key.

Parameter sets

CKKSParams.python_test() is fast and not secure. Use it for small examples and unit tests.

CKKSParams.default() and CKKSParams.high_precision_default() are larger presets. Treat them as starting points, not a substitute for reviewing the security, precision, depth, bootstrap, and deployment requirements of a real application.