forked from tuneinsight/lattigo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
decryptor.go
111 lines (90 loc) · 2.88 KB
/
decryptor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package rlwe
import (
"github.com/tuneinsight/lattigo/v4/ring"
"github.com/tuneinsight/lattigo/v4/utils"
)
// Decryptor is an RLWE decryption interface.
type Decryptor interface {
Decrypt(ct *Ciphertext, pt *Plaintext)
DecryptNew(ct *Ciphertext) (pt *Plaintext)
ShallowCopy() Decryptor
WithKey(sk *SecretKey) Decryptor
}
// decryptor is a structure used to decrypt Ciphertext. It stores the secret-key.
type decryptor struct {
params Parameters
ringQ *ring.Ring
buff *ring.Poly
sk *SecretKey
}
// NewDecryptor instantiates a new generic RLWE Decryptor.
func NewDecryptor(params Parameters, sk *SecretKey) Decryptor {
if sk.Value.Q.N() != params.N() {
panic("cannot NewDecryptor: secret_key is invalid for the provided parameters")
}
return &decryptor{
params: params,
ringQ: params.RingQ(),
buff: params.RingQ().NewPoly(),
sk: sk,
}
}
// Decrypt decrypts the Ciphertext and returns the result in a new Plaintext.
// Output pt MetaData will match the input ct MetaData.
func (d *decryptor) DecryptNew(ct *Ciphertext) (pt *Plaintext) {
pt = NewPlaintext(d.params, ct.Level())
d.Decrypt(ct, pt)
return
}
// Decrypt decrypts the Ciphertext and writes the result in pt.
// The level of the output Plaintext is min(ct.Level(), pt.Level())
// Output pt MetaData will match the input ct MetaData.
func (d *decryptor) Decrypt(ct *Ciphertext, pt *Plaintext) {
ringQ := d.ringQ
level := utils.MinInt(ct.Level(), pt.Level())
pt.Value.Resize(level)
pt.MetaData = ct.MetaData
if ct.IsNTT {
ring.CopyLvl(level, ct.Value[ct.Degree()], pt.Value)
} else {
ringQ.NTTLazyLvl(level, ct.Value[ct.Degree()], pt.Value)
}
for i := ct.Degree(); i > 0; i-- {
ringQ.MulCoeffsMontgomeryLvl(level, pt.Value, d.sk.Value.Q, pt.Value)
if !ct.IsNTT {
ringQ.NTTLazyLvl(level, ct.Value[i-1], d.buff)
ringQ.AddLvl(level, pt.Value, d.buff, pt.Value)
} else {
ringQ.AddLvl(level, pt.Value, ct.Value[i-1], pt.Value)
}
if i&7 == 7 {
ringQ.ReduceLvl(level, pt.Value, pt.Value)
}
}
if (ct.Degree())&7 != 7 {
ringQ.ReduceLvl(level, pt.Value, pt.Value)
}
if !ct.IsNTT {
ringQ.InvNTTLvl(level, pt.Value, pt.Value)
}
}
// ShallowCopy creates a shallow copy of Decryptor in which all the read-only data-structures are
// shared with the receiver and the temporary buffers are reallocated. The receiver and the returned
// Decryptor can be used concurrently.
func (d *decryptor) ShallowCopy() Decryptor {
return &decryptor{
ringQ: d.ringQ,
buff: d.ringQ.NewPoly(),
sk: d.sk,
}
}
// WithKey creates a shallow copy of Decryptor with a new decryption key, in which all the
// read-only data-structures are shared with the receiver and the temporary buffers
// are reallocated. The receiver and the returned Decryptor can be used concurrently.
func (d *decryptor) WithKey(sk *SecretKey) Decryptor {
return &decryptor{
ringQ: d.ringQ,
buff: d.ringQ.NewPoly(),
sk: sk,
}
}