mirror of
https://github.com/luxfi/lattice.git
synced 2026-09-24 00:25:44 +00:00
109 lines
3.4 KiB
Go
109 lines
3.4 KiB
Go
package hebin
|
|
|
|
import (
|
|
"math/big"
|
|
|
|
"github.com/luxfi/lattice/v5/core/rgsw"
|
|
"github.com/luxfi/lattice/v5/core/rlwe"
|
|
"github.com/luxfi/lattice/v5/ring"
|
|
"github.com/luxfi/lattice/v5/utils"
|
|
)
|
|
|
|
const (
|
|
// Parameter w of Algorithm 3 in https://eprint.iacr.org/2022/198
|
|
windowSize = 10
|
|
)
|
|
|
|
// BlindRotationEvaluationKeySet is a interface implementing methods
|
|
// to load the blind rotation keys (RGSW) and automorphism keys
|
|
// (via the rlwe.EvaluationKeySet interface).
|
|
// Implementation of this interface must be safe for concurrent use.
|
|
type BlindRotationEvaluationKeySet interface {
|
|
|
|
// GetBlindRotationKey should return RGSW(X^{s[i]})
|
|
GetBlindRotationKey(i int) (brk *rgsw.Ciphertext, err error)
|
|
|
|
// GetEvaluationKeySet should return an rlwe.EvaluationKeySet
|
|
// providing access to all the required automorphism keys.
|
|
GetEvaluationKeySet() (evk rlwe.EvaluationKeySet, err error)
|
|
}
|
|
|
|
// MemBlindRotationEvaluationKeySet is a basic in-memory implementation of the BlindRotationEvaluationKeySet interface.
|
|
type MemBlindRotationEvaluationKeySet struct {
|
|
BlindRotationKeys []*rgsw.Ciphertext
|
|
AutomorphismKeys []*rlwe.GaloisKey
|
|
}
|
|
|
|
func (evk MemBlindRotationEvaluationKeySet) GetBlindRotationKey(i int) (*rgsw.Ciphertext, error) {
|
|
return evk.BlindRotationKeys[i], nil
|
|
}
|
|
|
|
func (evk MemBlindRotationEvaluationKeySet) GetEvaluationKeySet() (rlwe.EvaluationKeySet, error) {
|
|
return rlwe.NewMemEvaluationKeySet(nil, evk.AutomorphismKeys...), nil
|
|
}
|
|
|
|
// GenEvaluationKeyNew generates a new Blind Rotation evaluation key
|
|
func GenEvaluationKeyNew(paramsRLWE rlwe.ParameterProvider, skRLWE *rlwe.SecretKey, paramsLWE rlwe.ParameterProvider, skLWE *rlwe.SecretKey, evkParams ...rlwe.EvaluationKeyParameters) (key MemBlindRotationEvaluationKeySet) {
|
|
|
|
pRLWE := *paramsRLWE.GetRLWEParameters()
|
|
pLWE := *paramsLWE.GetRLWEParameters()
|
|
|
|
skLWECopy := skLWE.CopyNew()
|
|
pLWE.RingQ().AtLevel(0).INTT(skLWECopy.Value.Q, skLWECopy.Value.Q)
|
|
pLWE.RingQ().AtLevel(0).IMForm(skLWECopy.Value.Q, skLWECopy.Value.Q)
|
|
sk := make([]*big.Int, pLWE.N())
|
|
for i := range sk {
|
|
sk[i] = new(big.Int)
|
|
}
|
|
pLWE.RingQ().AtLevel(0).PolyToBigintCentered(skLWECopy.Value.Q, 1, sk)
|
|
|
|
encryptor := rgsw.NewEncryptor(pRLWE, skRLWE)
|
|
|
|
levelQ, levelP, BaseTwoDecomposition := rlwe.ResolveEvaluationKeyParameters(pRLWE, evkParams)
|
|
|
|
skiRGSW := make([]*rgsw.Ciphertext, pLWE.N())
|
|
|
|
ptXi := make(map[int]*rlwe.Plaintext)
|
|
|
|
for i, si := range sk {
|
|
|
|
siInt := int(si.Int64())
|
|
|
|
if _, ok := ptXi[siInt]; !ok {
|
|
|
|
pt := &rlwe.Plaintext{}
|
|
pt.MetaData = &rlwe.MetaData{}
|
|
pt.IsNTT = true
|
|
pt.Value = pRLWE.RingQ().NewMonomialXi(siInt)
|
|
pRLWE.RingQ().NTT(pt.Value, pt.Value)
|
|
|
|
ptXi[siInt] = pt
|
|
}
|
|
|
|
skiRGSW[i] = rgsw.NewCiphertext(pRLWE, levelQ, levelP, BaseTwoDecomposition)
|
|
|
|
// Sanity check, this error should never happen unless this algorithm
|
|
// has been improperly modified to provides invalid inputs.
|
|
if err := encryptor.Encrypt(ptXi[siInt], skiRGSW[i]); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
kgen := rlwe.NewKeyGenerator(pRLWE)
|
|
|
|
galEls := make([]uint64, windowSize)
|
|
for i := 0; i < windowSize; i++ {
|
|
galEls[i] = pRLWE.GaloisElement(i + 1)
|
|
}
|
|
|
|
galEls = append(galEls, pRLWE.RingQ().NthRoot()-ring.GaloisGen)
|
|
|
|
gks := kgen.GenGaloisKeysNew(galEls, skRLWE, rlwe.EvaluationKeyParameters{
|
|
LevelQ: utils.Pointy(levelQ),
|
|
LevelP: utils.Pointy(levelP),
|
|
BaseTwoDecomposition: utils.Pointy(BaseTwoDecomposition),
|
|
})
|
|
|
|
return MemBlindRotationEvaluationKeySet{BlindRotationKeys: skiRGSW, AutomorphismKeys: gks}
|
|
}
|