Skip to content

v6.0.0

Compare
Choose a tag to compare
@qantik qantik released this 06 Aug 13:43
· 9 commits to main since this release

Release Overview

The sixth major release of Lattigo marks a departure from some of the abstractions
introduced in version five by refocusing the library onto the scheme level meaning the
implemented RLWE- and RGSW-based cryptosystems. This pivot comes at the expense of the
he package introduced in the previous version. In short, he provided abstractions of
the CKKS and BGV schemes from the schemes package with the intended goal of offering
a quick access to homomorphic encryption functionalities without requiring an extensive
amount of background knowledge of RLWE/RGSW-based cryptography and its accompanying
literature. Under the hood the he package was merely a thin wrapper around important
objects from schemes/ckks and schemes/bgv, which effectively constituted an elaborate
renaming/aliasing of structures such a parameters, encoders and evaluators. However,
the core focus of Lattigo has always been the implementation of common homomorphic
cryptosystems. Writing as well as utilizing circuits without at least a surface
knowledge of the underlying schemes is not a realistic goal at this stage in the life
cycle of homomorphic encryption. Unlike other cryptographic fields such a symmetric
cryptographic whose primitives can be safely utilized without domain knowledge, the
lacking maturity of homomorphic encryption does not permit a similar level of
abstraction. Moreover, the abstraction in he was leaky, e.g., schemes had to be
instantiated using the parameters objects from schemes/*, which basically voided the
raison d'être of the package.

The circuits Package

The removal of the he package has consequences for the homomorphic circuits such as CKKS
bootstrapping that were also part of he. All of them have been moved to a newly created
package termed circuits organized by scheme resulting in the following directory
structure.

circuits
├── bgv
│   ├── lintrans
│   └── polynomial
├── ckks
│   ├── bootstrapping
│   ├── comparison
│   ├── dft
│   ├── inverse
│   ├── lintrans
│   ├── minimax
│   ├── mod1
│   └── polynomial
└── common
    ├── lintrans
    └── polynomial

Note that both linear transformations and the polynomial evaluator support both the BGV
and CKKS schemes and thus scheme-generic structures are found in the circuits/common
sub-directory.

Removal of Circuit-Specific Evaluator Interfaces

All supported circuits in the new circuits package are instantiated with an
evaluator. In Lattigo-v5, such an evaluator had to conform to a circuit-specific interface
that for certain circuits appeared dauntingly complex (see e.g.,
EvaluatorForLinearTransformation). It is not clear how a user (layman and expert) was
supposed to make use of such interfaces without total knowledge of the entire Lattigo code
base down to the ring level. It is more likely, if a custom evaluator was required for a
particular circuit, then a user would simply adapt an existing scheme evaluator from
schemes to his needs. With the refocus of the sixth version of Lattigo onto the scheme
level, we tend to this use case by removing all EvaluatorFor[*] interfaces in the
circuit package and replacing them with a scheme-agnostic evaluator interface in
schemes/scheme.go. This design choice should streamline the creation of custom
evaluators based on existing ones making the hacking of new and existing circuits simpler.

HERMES-Inspired Ring Packing

Aa fresh ring packing routine based on the
HERMES work by Bae et al. (https://eprint.iacr.org/2023/1244) has been added which improves the time and
memory by a significant margin compared to the existing baseline packing implementation.
This operation adds to new operations to the packing facilities:

  • Extraction. Recursively split the ciphertexts into left and right part of half
    the ring degree until the minimum ring degree defined by the user is reached before
    applying the extraction procedure.

  • Repacking. Apply the sample repacking procedure in the small ring over multiple
    ciphertexts before merging them recursively back to the larger ring.

The new ring packing implementation has been moved from the removed he package into the
existing core/rlwe package and can be invoked through an updated API:

  • New Evaluator rlwe.RingPackingEvaluator:
    • NewRingPackingEvaluator(evk *RingPackingEvaluationKey)
    • Extract(ct *rlwe.Ciphertext, idx []int, naive bool) (cts map[int]*rlwe.Ciphertext, err error)
    • Repack(cts map[int]*rlwe.Ciphertext, naive bool) (ct *rlwe.Ciphertext, err error)
    • Split(ctN, ctEvenNHalf, ctOddNHalf *rlwe.Ciphertext) (err error)
    • Merge(ctEvenNHalf, ctOddNHalf, ctN *rlwe.Ciphertext) (err error)
    • ShallowCopy() *RingPackingEvaluator
  • New Evaluation Key rlwe.RingPackingEvaluationKey

Permutations

A second new feature are slot-wise permutations to
the linear transformation circuits in circuits/*/lintrans. Permutations provide the
ability to arbitrarily reorder ciphertext slots through a linear transformation. The exact
nature of the permutation is determined via the new lintrans.PermtuationMapping and
lintrans.Permutation objects:

type PermutationMapping[T bgv.Integer | ckks.Float] struct {
	From    int
	To      int
	Scaling T
}

type Permutation[T bgv.Integer | ckks.Float] []PermutationMapping[T]

func (p Permutation[T]) GetDiagonals(logSlots int) Diagonals[T] {}

Here, PermutationMapping specify the origin and destination index of a single ciphertext
slot. A slice of permutations mapping then yields a Permutation from which the diagonals
can be extracted to be passed to the initializer of the linear transformation.

Absorption of BFV

The implementation of the BFV cryptosystem simply wraps the BGV scheme by redefining
the multiplication methods of the evaluator. This introduced a significant amount of code
duplication. The new way of instantiating BFV is through the BGV evaluator by setting the
scaleInvariant flag. See the READMEs of schemes/bfv and schemes/bgv for more information.

bfvEvaluator := bgv.NewEvaluator(params, evaluationKeys, true)

Refactored Unit Test Context

Lattigo-v6 provides an improved unit test context generations skeleton that reduces the amount of
boilerplate code duplication for the creation of Lattigo objects such as parameters and
evaluators for the usage in unit tests. The files schemes/*/test_utils.go now contain
scheme-specific functions to be reused in unit tests of all packages that depend on
schemes.

Miscellaneous

  • The lintrans.Parameters struct now allows for a fine-grained instantiation of the both
    the $Q$ and $P$ levels with the new lintrans.Parameters.LevelQ and
    lintrans.Parameters.LevelP fields.
  • Moving the masking operation in rlwe.Evaluator.gadgetProductSinglePAndBitDecompLazy
    to an earlier point in the computation reduces the number of required masking
    invocations and thus accelerates the gadget product.
  • A small refactor of the linearization key generation in the multi-party protocol
    reduces the degree of the ciphertext. This change reduces the size of some of the keys
    that need to passed over the channel.
  • Docstrings at various points in the code base have been fixed and amended with godoc
    references using the [*] operator. This allows for a quick navigation of the
    documentation when viewed in a browser.
  • The mhe package has been renamed to multiparty containing packages
    multiparty/mpbgv and multiparty/mpckks to better reflect the removal of the
    he package.
  • RGSW blind rotations have been moved to core/rlwe leading the complete deletion of
    the he/bin package.
  • Several bugfixes have been included since version five.
  • A large set of linter warnings have been fixed.

Switching to Lattigo-v6

Lattigo-v6 now requires a minimum Golang version of 1.21. The support for earlier
versions has been deprecate. The principal reason for this change is the usage of the
newly introduces slices package in the standard library whose functions replace some of
the procedures in utils/slices.go.

The removal of the he package necessitate some changes in projects that relied
on Lattigo-v5. However, since he was only renaming key structures from schemes/* the
required changes are straightforward.

  • hefloat. Any code that used the he/hefloat package needs to rename the imports to
    schemes/ckks with the exception of code that made us of circuits that formerly were
    also part of he/hefloat. This circuits now have to be imported separately, for
    example circuits/ckks/lintrans.
  • heint. Any code that used the he/heint package needs to rename the imports to
    schemes/ckks with the exception of code that made us of circuits that formerly were
    also part of he/heint. This circuits now have to be imported separately, for
    example circuits/bgv/polynomial.

Acknowledgements

The Lattigo team would like to thank Christian Mouchet @ChristianMct for his insightful reviews
and comments during the development phase.

Relevant PRs and Commits