v6.0.0
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 newlintrans.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 tomultiparty
containing packages
multiparty/mpbgv
andmultiparty/mpckks
to better reflect the removal of the
he
package. - RGSW blind rotations have been moved to
core/rlwe
leading the complete deletion of
thehe/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 thehe/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 ofhe/hefloat
. This circuits now have to be imported separately, for
examplecircuits/ckks/lintrans
.heint
. Any code that used thehe/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 ofhe/heint
. This circuits now have to be imported separately, for
examplecircuits/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
- Bugfixes #427 by @Pro7ech in #428
- Bugfixes #437 by @Pro7ech in #438
- Update README with CLA for contributions by @romainbou in #442
- Bugfixes April 2024 by @qantik in #456
- Add Go v1.22 to the CI tests and update
staticcheck
by @romainbou in #462 - Bugfixes May 2024 Part 1 by @qantik in #474
- Bugfixes #457 by @romainbou in #473
- Bugfixes May 2024 Part 2 by @qantik in #482
- Godoc Formatting Cleanup by @qantik in #486
- Bugfixes June 2024 Part 1 by @qantik in #483
- Bugfixes June 2024 Part 2 by @qantik in #484
- Permutations & Packing #485 by @Pro7ech in #485
- Removal of the
he
package by @qantik (c2c6f71 to e2e3721) - Absorption of the
bfv
package by @qantik (1487afa)