Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
kyber-k2so
Kyber-K2SO
Commits
df5b9d80
Commit
df5b9d80
authored
Jul 31, 2020
by
Nadim Kobeissi
💾
Browse files
Add code documentation
parent
58e8c60e
Changes
6
Hide whitespace changes
Inline
Side-by-side
byteops.go
View file @
df5b9d80
...
...
@@ -3,6 +3,7 @@
package
kyberk2so
// byteopsLoad32 returns a 32-bit unsigned integer loaded from byte x.
func
byteopsLoad32
(
x
[]
byte
)
uint32
{
var
r
uint32
r
=
uint32
(
x
[
0
])
...
...
@@ -12,6 +13,9 @@ func byteopsLoad32(x []byte) uint32 {
return
r
}
// byteopsCbd computers a polynomial with coefficients distributed
// according to a centered binomial distribution with parameter paramsETA,
// given an array of uniformly random bytes.
func
byteopsCbd
(
buf
[]
byte
)
poly
{
var
t
,
d
uint32
var
a
,
b
int16
...
...
@@ -22,13 +26,15 @@ func byteopsCbd(buf []byte) poly {
d
=
d
+
((
t
>>
1
)
&
0x55555555
)
for
j
:=
0
;
j
<
8
;
j
++
{
a
=
int16
((
d
>>
(
4
*
j
+
0
))
&
0x3
)
b
=
int16
((
d
>>
(
4
*
j
+
2
))
&
0x3
)
b
=
int16
((
d
>>
(
4
*
j
+
paramsETA
))
&
0x3
)
r
[
8
*
i
+
j
]
=
a
-
b
}
}
return
r
}
// byteopsMontgomeryReduce computes a Montgomery reduction; given
// a 32-bit integer `a`, returns `a * R^-1 mod Q` where `R=2^16`.
func
byteopsMontgomeryReduce
(
a
int32
)
int16
{
u
:=
int16
(
a
*
int32
(
paramsQinv
))
t
:=
int32
(
u
)
*
int32
(
paramsQ
)
...
...
@@ -37,6 +43,9 @@ func byteopsMontgomeryReduce(a int32) int16 {
return
int16
(
t
)
}
// byteopsBarrettReduce computes a Barrett reduction; given
// a 16-bit integer `a`, returns a 16-bit integer congruent to
// `a mod Q` in {0,...,Q}.
func
byteopsBarrettReduce
(
a
int16
)
int16
{
var
t
int16
var
v
int16
=
int16
(((
uint32
(
1
)
<<
26
)
+
uint32
(
paramsQ
/
2
))
/
uint32
(
paramsQ
))
...
...
@@ -45,6 +54,7 @@ func byteopsBarrettReduce(a int16) int16 {
return
a
-
t
}
// byteopsCSubQ conditionally subtracts Q from a.
func
byteopsCSubQ
(
a
int16
)
int16
{
a
=
a
-
int16
(
paramsQ
)
a
=
a
+
((
a
>>
15
)
&
int16
(
paramsQ
))
...
...
indcpa.go
View file @
df5b9d80
...
...
@@ -9,56 +9,72 @@ import (
"golang.org/x/crypto/sha3"
)
// indcpaPackPublicKey serializes the public key as a concatenation of the
// serialized vector of polynomials of the public key, and the public seed
// used to generate the matrix `A`.
func
indcpaPackPublicKey
(
publicKey
polyvec
,
seed
[]
byte
,
paramsK
int
)
[]
byte
{
return
append
(
polyvecToBytes
(
publicKey
,
paramsK
),
seed
...
)
}
// indcpaUnpackPublicKey de-serializes the public key from a byte array
// and represents the approximate inverse of indcpaPackPublicKey.
func
indcpaUnpackPublicKey
(
packedPublicKey
[]
byte
,
paramsK
int
)
(
polyvec
,
[]
byte
)
{
switch
paramsK
{
case
2
:
publicKeyPolyvec
:=
polyvecFromBytes
(
packedPublicKey
[
:
paramsPolyvecBytesK2
],
paramsK
)
seed
:=
packedPublicKey
[
paramsPolyvecBytesK2
:
]
publicKeyPolyvec
:=
polyvecFromBytes
(
packedPublicKey
[
:
paramsPolyvecBytesK
51
2
],
paramsK
)
seed
:=
packedPublicKey
[
paramsPolyvecBytesK
51
2
:
]
return
publicKeyPolyvec
,
seed
case
3
:
publicKeyPolyvec
:=
polyvecFromBytes
(
packedPublicKey
[
:
paramsPolyvecBytesK
3
],
paramsK
)
seed
:=
packedPublicKey
[
paramsPolyvecBytesK
3
:
]
publicKeyPolyvec
:=
polyvecFromBytes
(
packedPublicKey
[
:
paramsPolyvecBytesK
768
],
paramsK
)
seed
:=
packedPublicKey
[
paramsPolyvecBytesK
768
:
]
return
publicKeyPolyvec
,
seed
default
:
publicKeyPolyvec
:=
polyvecFromBytes
(
packedPublicKey
[
:
paramsPolyvecBytesK4
],
paramsK
)
seed
:=
packedPublicKey
[
paramsPolyvecBytesK4
:
]
publicKeyPolyvec
:=
polyvecFromBytes
(
packedPublicKey
[
:
paramsPolyvecBytesK
102
4
],
paramsK
)
seed
:=
packedPublicKey
[
paramsPolyvecBytesK
102
4
:
]
return
publicKeyPolyvec
,
seed
}
}
// indcpaPackPrivateKey serializes the private key.
func
indcpaPackPrivateKey
(
privateKey
polyvec
,
paramsK
int
)
[]
byte
{
return
polyvecToBytes
(
privateKey
,
paramsK
)
}
// indcpaUnpackPrivateKey de-serializes the private key and represents
// the inverse of indcpaPackPrivateKey.
func
indcpaUnpackPrivateKey
(
packedPrivateKey
[]
byte
,
paramsK
int
)
polyvec
{
return
polyvecFromBytes
(
packedPrivateKey
,
paramsK
)
}
// indcpaPackCiphertext serializes the ciphertext as a concatenation of
// the compressed and serialized vector of polynomials `b` and the
// compressed and serialized polynomial `v`.
func
indcpaPackCiphertext
(
b
polyvec
,
v
poly
,
paramsK
int
)
[]
byte
{
return
append
(
polyvecCompress
(
b
,
paramsK
),
polyCompress
(
v
,
paramsK
)
...
)
}
// indcpaUnpackCiphertext de-serializes and decompresses the ciphertext
// from a byte array, and represents the approximate inverse of
// indcpaPackCiphertext.
func
indcpaUnpackCiphertext
(
c
[]
byte
,
paramsK
int
)
(
polyvec
,
poly
)
{
switch
paramsK
{
case
2
:
b
:=
polyvecDecompress
(
c
[
:
paramsPolyvecCompressedBytesK2
],
paramsK
)
v
:=
polyDecompress
(
c
[
paramsPolyvecCompressedBytesK2
:
],
paramsK
)
b
:=
polyvecDecompress
(
c
[
:
paramsPolyvecCompressedBytesK
51
2
],
paramsK
)
v
:=
polyDecompress
(
c
[
paramsPolyvecCompressedBytesK
51
2
:
],
paramsK
)
return
b
,
v
case
3
:
b
:=
polyvecDecompress
(
c
[
:
paramsPolyvecCompressedBytesK
3
],
paramsK
)
v
:=
polyDecompress
(
c
[
paramsPolyvecCompressedBytesK
3
:
],
paramsK
)
b
:=
polyvecDecompress
(
c
[
:
paramsPolyvecCompressedBytesK
768
],
paramsK
)
v
:=
polyDecompress
(
c
[
paramsPolyvecCompressedBytesK
768
:
],
paramsK
)
return
b
,
v
default
:
b
:=
polyvecDecompress
(
c
[
:
paramsPolyvecCompressedBytesK4
],
paramsK
)
v
:=
polyDecompress
(
c
[
paramsPolyvecCompressedBytesK4
:
],
paramsK
)
b
:=
polyvecDecompress
(
c
[
:
paramsPolyvecCompressedBytesK
102
4
],
paramsK
)
v
:=
polyDecompress
(
c
[
paramsPolyvecCompressedBytesK
102
4
:
],
paramsK
)
return
b
,
v
}
}
// indcpaRejUniform runs rejection sampling on uniform random bytes
// to generate uniform random integers modulo `Q`.
func
indcpaRejUniform
(
buf
[]
byte
,
bufl
int
)
(
poly
,
int
)
{
var
r
poly
var
val
uint16
...
...
@@ -76,6 +92,9 @@ func indcpaRejUniform(buf []byte, bufl int) (poly, int) {
return
r
,
ctr
}
// indcpaGenMatrix deterministically generates a matrix `A` (or the transpose of `A`)
// from a seed. Entries of the matrix are polynomials that look uniformly random.
// Performs rejection sampling on the output of an extendable-output function (XOF).
func
indcpaGenMatrix
(
seed
[]
byte
,
transposed
bool
,
paramsK
int
)
([]
polyvec
,
error
)
{
r
:=
make
([]
polyvec
,
paramsK
)
buf
:=
make
([]
byte
,
4
*
168
)
...
...
@@ -115,12 +134,17 @@ func indcpaGenMatrix(seed []byte, transposed bool, paramsK int) ([]polyvec, erro
return
r
,
nil
}
// indcpaPrf provides a pseudo-random function (PRF) which returns
// a byte array of length `l`, using the provided key and nonce
// to instantiate the PRF's underlying hash function.
func
indcpaPrf
(
l
int
,
key
[]
byte
,
nonce
byte
)
[]
byte
{
hash
:=
make
([]
byte
,
l
)
sha3
.
ShakeSum256
(
hash
,
append
(
key
,
nonce
))
return
hash
}
// indcpaKeypair generates public and private keys for the CPA-secure
// public-key encryption scheme underlying Kyber.
func
indcpaKeypair
(
paramsK
int
)
([]
byte
,
[]
byte
,
error
)
{
skpv
:=
polyvecNew
(
paramsK
)
pkpv
:=
polyvecNew
(
paramsK
)
...
...
@@ -161,6 +185,8 @@ func indcpaKeypair(paramsK int) ([]byte, []byte, error) {
return
indcpaPackPrivateKey
(
skpv
,
paramsK
),
indcpaPackPublicKey
(
pkpv
,
publicSeed
,
paramsK
),
nil
}
// indcpaEncrypt is the encryption function of the CPA-secure
// public-key encryption scheme underlying Kyber.
func
indcpaEncrypt
(
m
[]
byte
,
publicKey
[]
byte
,
coins
[]
byte
,
paramsK
int
)
([]
byte
,
error
)
{
sp
:=
polyvecNew
(
paramsK
)
ep
:=
polyvecNew
(
paramsK
)
...
...
@@ -189,6 +215,8 @@ func indcpaEncrypt(m []byte, publicKey []byte, coins []byte, paramsK int) ([]byt
return
indcpaPackCiphertext
(
bp
,
polyReduce
(
v
),
paramsK
),
nil
}
// indcpaDecrypt is the decryption function of the CPA-secure
// public-key encryption scheme underlying Kyber.
func
indcpaDecrypt
(
c
[]
byte
,
privateKey
[]
byte
,
paramsK
int
)
[]
byte
{
bp
,
v
:=
indcpaUnpackCiphertext
(
c
,
paramsK
)
privateKeyPolyvec
:=
indcpaUnpackPrivateKey
(
privateKey
,
paramsK
)
...
...
kem.go
View file @
df5b9d80
...
...
@@ -183,9 +183,9 @@ func KemDecrypt512(
const
paramsK
int
=
2
var
sharedSecretFixedLength
[
KyberSSBytes
]
byte
sharedSecret
:=
make
([]
byte
,
KyberSSBytes
)
indcpaPrivateKey
:=
privateKey
[
:
paramsIndcpaSecretKeyBytesK2
]
pki
:=
paramsIndcpaSecretKeyBytesK2
+
paramsIndcpaPublicKeyBytesK2
publicKey
:=
privateKey
[
paramsIndcpaSecretKeyBytesK2
:
pki
]
indcpaPrivateKey
:=
privateKey
[
:
paramsIndcpaSecretKeyBytesK
51
2
]
pki
:=
paramsIndcpaSecretKeyBytesK
51
2
+
paramsIndcpaPublicKeyBytesK
51
2
publicKey
:=
privateKey
[
paramsIndcpaSecretKeyBytesK
51
2
:
pki
]
buf
:=
indcpaDecrypt
(
ciphertext
[
:
],
indcpaPrivateKey
,
paramsK
)
ski
:=
Kyber512SKBytes
-
2
*
paramsSymBytes
kr
:=
sha3
.
Sum512
(
append
(
buf
,
privateKey
[
ski
:
ski
+
paramsSymBytes
]
...
))
...
...
@@ -212,9 +212,9 @@ func KemDecrypt768(
const
paramsK
int
=
3
var
sharedSecretFixedLength
[
KyberSSBytes
]
byte
sharedSecret
:=
make
([]
byte
,
KyberSSBytes
)
indcpaPrivateKey
:=
privateKey
[
:
paramsIndcpaSecretKeyBytesK
3
]
pki
:=
paramsIndcpaSecretKeyBytesK
3
+
paramsIndcpaPublicKeyBytesK
3
publicKey
:=
privateKey
[
paramsIndcpaSecretKeyBytesK
3
:
pki
]
indcpaPrivateKey
:=
privateKey
[
:
paramsIndcpaSecretKeyBytesK
768
]
pki
:=
paramsIndcpaSecretKeyBytesK
768
+
paramsIndcpaPublicKeyBytesK
768
publicKey
:=
privateKey
[
paramsIndcpaSecretKeyBytesK
768
:
pki
]
buf
:=
indcpaDecrypt
(
ciphertext
[
:
],
indcpaPrivateKey
,
paramsK
)
ski
:=
Kyber768SKBytes
-
2
*
paramsSymBytes
kr
:=
sha3
.
Sum512
(
append
(
buf
,
privateKey
[
ski
:
ski
+
paramsSymBytes
]
...
))
...
...
@@ -241,9 +241,9 @@ func KemDecrypt1024(
const
paramsK
int
=
4
var
sharedSecretFixedLength
[
KyberSSBytes
]
byte
sharedSecret
:=
make
([]
byte
,
KyberSSBytes
)
indcpaPrivateKey
:=
privateKey
[
:
paramsIndcpaSecretKeyBytesK4
]
pki
:=
paramsIndcpaSecretKeyBytesK4
+
paramsIndcpaPublicKeyBytesK4
publicKey
:=
privateKey
[
paramsIndcpaSecretKeyBytesK4
:
pki
]
indcpaPrivateKey
:=
privateKey
[
:
paramsIndcpaSecretKeyBytesK
102
4
]
pki
:=
paramsIndcpaSecretKeyBytesK
102
4
+
paramsIndcpaPublicKeyBytesK
102
4
publicKey
:=
privateKey
[
paramsIndcpaSecretKeyBytesK
102
4
:
pki
]
buf
:=
indcpaDecrypt
(
ciphertext
[
:
],
indcpaPrivateKey
,
paramsK
)
ski
:=
Kyber1024SKBytes
-
2
*
paramsSymBytes
kr
:=
sha3
.
Sum512
(
append
(
buf
,
privateKey
[
ski
:
ski
+
paramsSymBytes
]
...
))
...
...
ntt.go
View file @
df5b9d80
...
...
@@ -29,10 +29,14 @@ var nttZetasInv [128]int16 = [128]int16{
3127
,
3042
,
1907
,
1836
,
1517
,
359
,
758
,
1441
,
}
// nttFqMul performs multiplication followed by Montgomery reduction
// and returns a 16-bit integer congruent to `a*b*R^{-1} mod Q`.
func
nttFqMul
(
a
int16
,
b
int16
)
int16
{
return
byteopsMontgomeryReduce
(
int32
(
a
)
*
int32
(
b
))
}
// ntt performs an inplace number-theoretic transform (NTT) in `Rq`.
// The input is in standard order, the output is in bit-reversed order.
func
ntt
(
r
poly
)
poly
{
j
:=
0
k
:=
1
...
...
@@ -50,6 +54,9 @@ func ntt(r poly) poly {
return
r
}
// nttInv performs an inplace inverse number-theoretic transform (NTT)
// in `Rq` and multiplication by Montgomery factor 2^16.
// The input is in bit-reversed order, the output is in standard order.
func
nttInv
(
r
poly
)
poly
{
j
:=
0
k
:=
0
...
...
@@ -71,6 +78,9 @@ func nttInv(r poly) poly {
return
r
}
// nttBaseMul performs the multiplication of polynomials
// in `Zq[X]/(X^2-zeta)`. Used for multiplication of elements
// in `Rq` in the number-theoretic transformation domain.
func
nttBaseMul
(
a0
int16
,
a1
int16
,
b0
int16
,
b1
int16
,
...
...
params.go
View file @
df5b9d80
...
...
@@ -9,48 +9,48 @@ const paramsQinv int = 62209
const
paramsETA
int
=
2
const
paramsSymBytes
int
=
32
const
paramsPolyBytes
int
=
384
const
paramsPolyvecBytesK2
int
=
2
*
paramsPolyBytes
const
paramsPolyvecBytesK
3
int
=
3
*
paramsPolyBytes
const
paramsPolyvecBytesK4
int
=
4
*
paramsPolyBytes
const
paramsPolyCompressedBytesK2
int
=
96
const
paramsPolyCompressedBytesK
3
int
=
128
const
paramsPolyCompressedBytesK4
int
=
160
const
paramsPolyvecCompressedBytesK2
int
=
2
*
320
const
paramsPolyvecCompressedBytesK
3
int
=
3
*
320
const
paramsPolyvecCompressedBytesK4
int
=
4
*
352
const
paramsIndcpaPublicKeyBytesK2
int
=
paramsPolyvecBytesK2
+
paramsSymBytes
const
paramsIndcpaPublicKeyBytesK
3
int
=
paramsPolyvecBytesK
3
+
paramsSymBytes
const
paramsIndcpaPublicKeyBytesK4
int
=
paramsPolyvecBytesK4
+
paramsSymBytes
const
paramsIndcpaSecretKeyBytesK2
int
=
2
*
paramsPolyBytes
const
paramsIndcpaSecretKeyBytesK
3
int
=
3
*
paramsPolyBytes
const
paramsIndcpaSecretKeyBytesK4
int
=
4
*
paramsPolyBytes
const
paramsPolyvecBytesK
51
2
int
=
2
*
paramsPolyBytes
const
paramsPolyvecBytesK
768
int
=
3
*
paramsPolyBytes
const
paramsPolyvecBytesK
102
4
int
=
4
*
paramsPolyBytes
const
paramsPolyCompressedBytesK
51
2
int
=
96
const
paramsPolyCompressedBytesK
768
int
=
128
const
paramsPolyCompressedBytesK
102
4
int
=
160
const
paramsPolyvecCompressedBytesK
51
2
int
=
2
*
320
const
paramsPolyvecCompressedBytesK
768
int
=
3
*
320
const
paramsPolyvecCompressedBytesK
102
4
int
=
4
*
352
const
paramsIndcpaPublicKeyBytesK
51
2
int
=
paramsPolyvecBytesK
51
2
+
paramsSymBytes
const
paramsIndcpaPublicKeyBytesK
768
int
=
paramsPolyvecBytesK
768
+
paramsSymBytes
const
paramsIndcpaPublicKeyBytesK
102
4
int
=
paramsPolyvecBytesK
102
4
+
paramsSymBytes
const
paramsIndcpaSecretKeyBytesK
51
2
int
=
2
*
paramsPolyBytes
const
paramsIndcpaSecretKeyBytesK
768
int
=
3
*
paramsPolyBytes
const
paramsIndcpaSecretKeyBytesK
102
4
int
=
4
*
paramsPolyBytes
// Kyber512SKBytes is a constant representing the byte length of private keys in Kyber-512.
const
Kyber512SKBytes
int
=
paramsPolyvecBytesK2
+
((
paramsPolyvecBytesK2
+
paramsSymBytes
)
+
2
*
paramsSymBytes
)
const
Kyber512SKBytes
int
=
paramsPolyvecBytesK
51
2
+
((
paramsPolyvecBytesK
51
2
+
paramsSymBytes
)
+
2
*
paramsSymBytes
)
// Kyber768SKBytes is a constant representing the byte length of private keys in Kyber-768.
const
Kyber768SKBytes
int
=
paramsPolyvecBytesK
3
+
((
paramsPolyvecBytesK
3
+
paramsSymBytes
)
+
2
*
paramsSymBytes
)
const
Kyber768SKBytes
int
=
paramsPolyvecBytesK
768
+
((
paramsPolyvecBytesK
768
+
paramsSymBytes
)
+
2
*
paramsSymBytes
)
// Kyber1024SKBytes is a constant representing the byte length of private keys in Kyber-1024.
const
Kyber1024SKBytes
int
=
paramsPolyvecBytesK4
+
((
paramsPolyvecBytesK4
+
paramsSymBytes
)
+
2
*
paramsSymBytes
)
const
Kyber1024SKBytes
int
=
paramsPolyvecBytesK
102
4
+
((
paramsPolyvecBytesK
102
4
+
paramsSymBytes
)
+
2
*
paramsSymBytes
)
// Kyber512PKBytes is a constant representing the byte length of public keys in Kyber-512.
const
Kyber512PKBytes
int
=
paramsPolyvecBytesK2
+
paramsSymBytes
const
Kyber512PKBytes
int
=
paramsPolyvecBytesK
51
2
+
paramsSymBytes
// Kyber768PKBytes is a constant representing the byte length of public keys in Kyber-768.
const
Kyber768PKBytes
int
=
paramsPolyvecBytesK
3
+
paramsSymBytes
const
Kyber768PKBytes
int
=
paramsPolyvecBytesK
768
+
paramsSymBytes
// Kyber1024PKBytes is a constant representing the byte length of public keys in Kyber-1024.
const
Kyber1024PKBytes
int
=
paramsPolyvecBytesK4
+
paramsSymBytes
const
Kyber1024PKBytes
int
=
paramsPolyvecBytesK
102
4
+
paramsSymBytes
// Kyber512CTBytes is a constant representing the byte length of ciphertexts in Kyber-512.
const
Kyber512CTBytes
int
=
paramsPolyvecCompressedBytesK2
+
paramsPolyCompressedBytesK2
const
Kyber512CTBytes
int
=
paramsPolyvecCompressedBytesK
51
2
+
paramsPolyCompressedBytesK
51
2
// Kyber768CTBytes is a constant representing the byte length of ciphertexts in Kyber-768.
const
Kyber768CTBytes
int
=
paramsPolyvecCompressedBytesK
3
+
paramsPolyCompressedBytesK
3
const
Kyber768CTBytes
int
=
paramsPolyvecCompressedBytesK
768
+
paramsPolyCompressedBytesK
768
// Kyber1024CTBytes is a constant representing the byte length of ciphertexts in Kyber-1024.
const
Kyber1024CTBytes
int
=
paramsPolyvecCompressedBytesK4
+
paramsPolyCompressedBytesK4
const
Kyber1024CTBytes
int
=
paramsPolyvecCompressedBytesK
102
4
+
paramsPolyCompressedBytesK
102
4
// KyberSSBytes is a constant representing the byte length of shared secrets in Kyber.
const
KyberSSBytes
int
=
32
poly.go
View file @
df5b9d80
...
...
@@ -4,21 +4,16 @@
package
kyberk2so
type
poly
[
paramsPolyBytes
]
int16
type
polyvec
[]
poly
func
polyvecNew
(
paramsK
int
)
polyvec
{
var
pv
polyvec
=
make
([]
poly
,
paramsK
)
return
pv
}
// polyCompress lossily compresses and subsequently serializes a polynomial.
func
polyCompress
(
a
poly
,
paramsK
int
)
[]
byte
{
t
:=
make
([]
byte
,
8
)
a
=
polyCSubQ
(
a
)
rr
:=
0
switch
paramsK
{
case
2
:
r
:=
make
([]
byte
,
paramsPolyCompressedBytesK2
)
r
:=
make
([]
byte
,
paramsPolyCompressedBytesK
51
2
)
for
i
:=
0
;
i
<
paramsN
/
8
;
i
++
{
for
j
:=
0
;
j
<
8
;
j
++
{
t
[
j
]
=
byte
(((
uint16
(
a
[
8
*
i
+
j
])
<<
3
)
+
uint16
(
paramsQ
)
/
2
)
/
uint16
(
paramsQ
))
&
7
...
...
@@ -30,7 +25,7 @@ func polyCompress(a poly, paramsK int) []byte {
}
return
r
case
3
:
r
:=
make
([]
byte
,
paramsPolyCompressedBytesK
3
)
r
:=
make
([]
byte
,
paramsPolyCompressedBytesK
768
)
for
i
:=
0
;
i
<
paramsN
/
8
;
i
++
{
for
j
:=
0
;
j
<
8
;
j
++
{
t
[
j
]
=
byte
(((
uint16
(
a
[
8
*
i
+
j
])
<<
4
)
+
uint16
(
paramsQ
/
2
))
/
uint16
(
paramsQ
))
&
15
...
...
@@ -43,7 +38,7 @@ func polyCompress(a poly, paramsK int) []byte {
}
return
r
default
:
r
:=
make
([]
byte
,
paramsPolyCompressedBytesK4
)
r
:=
make
([]
byte
,
paramsPolyCompressedBytesK
102
4
)
for
i
:=
0
;
i
<
paramsN
/
8
;
i
++
{
for
j
:=
0
;
j
<
8
;
j
++
{
t
[
j
]
=
byte
(((
uint32
(
a
[
8
*
i
+
j
])
<<
5
)
+
uint32
(
paramsQ
/
2
))
/
uint32
(
paramsQ
))
&
31
...
...
@@ -59,6 +54,10 @@ func polyCompress(a poly, paramsK int) []byte {
}
}
// polyDecompress de-serializes and subsequently decompresses a polynomial,
// representing the approximate inverse of polyCompress.
// Note that compression is lossy, and thus decompression will not match the
// original input.
func
polyDecompress
(
a
[]
byte
,
paramsK
int
)
poly
{
var
r
poly
t
:=
make
([]
byte
,
8
)
...
...
@@ -104,6 +103,7 @@ func polyDecompress(a []byte, paramsK int) poly {
return
r
}
// polyToBytes serializes a polynomial into an array of bytes.
func
polyToBytes
(
a
poly
)
[]
byte
{
var
t0
,
t1
uint16
r
:=
make
([]
byte
,
paramsPolyBytes
)
...
...
@@ -118,6 +118,8 @@ func polyToBytes(a poly) []byte {
return
r
}
// polyFromBytes de-serialises an array of bytes into a polynomial,
// and represents the inverse of polyToBytes.
func
polyFromBytes
(
a
[]
byte
)
poly
{
var
r
poly
for
i
:=
0
;
i
<
paramsN
/
2
;
i
++
{
...
...
@@ -127,6 +129,7 @@ func polyFromBytes(a []byte) poly {
return
r
}
// polyFromMsg converts a 32-byte message to a polynomial.
func
polyFromMsg
(
msg
[]
byte
)
poly
{
var
r
poly
var
mask
int16
...
...
@@ -139,6 +142,8 @@ func polyFromMsg(msg []byte) poly {
return
r
}
// polyToMsg converts a polynomial to a 32-byte message
// and represents the inverse of polyFromMsg.
func
polyToMsg
(
a
poly
)
[]
byte
{
msg
:=
make
([]
byte
,
paramsSymBytes
)
var
t
uint16
...
...
@@ -153,20 +158,31 @@ func polyToMsg(a poly) []byte {
return
msg
}
// polyGetNoise samples a polynomial deterministically from a seed
// and nonce, with the output polynomial being close to a centered
// binomial distribution with parameter paramsETA = 2.
func
polyGetNoise
(
seed
[]
byte
,
nonce
byte
)
poly
{
l
:=
paramsETA
*
paramsN
/
4
p
:=
indcpaPrf
(
l
,
seed
,
nonce
)
return
byteopsCbd
(
p
)
}
// polyNtt computes a negacyclic number-theoretic transform (NTT) of
// a polynomial in-place; the input is assumed to be in normal order,
// while the output is in bit-reversed order.
func
polyNtt
(
r
poly
)
poly
{
return
polyReduce
(
ntt
(
r
))
}
// polyInvNttToMont computes the inverse of a negacyclic number-theoretic
// transform (NTT) of a polynomial in-place; the input is assumed to be in
// bit-reversed order, while the output is in normal order.
func
polyInvNttToMont
(
r
poly
)
poly
{
return
nttInv
(
r
)
}
// polyBaseMulMontgomery performs the multiplication of two polynomials
// in the number-theoretic transform (NTT) domain.
func
polyBaseMulMontgomery
(
a
poly
,
b
poly
)
poly
{
for
i
:=
0
;
i
<
paramsN
/
4
;
i
++
{
rx
:=
nttBaseMul
(
...
...
@@ -187,6 +203,8 @@ func polyBaseMulMontgomery(a poly, b poly) poly {
return
a
}
// polyToMont performs the in-place conversion of all coefficients
// of a polynomial from the normal domain to the Montgomery domain.
func
polyToMont
(
r
poly
)
poly
{
var
f
int16
=
int16
((
uint64
(
1
)
<<
32
)
%
uint64
(
paramsQ
))
for
i
:=
0
;
i
<
paramsN
;
i
++
{
...
...
@@ -195,6 +213,7 @@ func polyToMont(r poly) poly {
return
r
}
// polyReduce applies Barrett reduction to all coefficients of a polynomial.
func
polyReduce
(
r
poly
)
poly
{
for
i
:=
0
;
i
<
paramsN
;
i
++
{
r
[
i
]
=
byteopsBarrettReduce
(
r
[
i
])
...
...
@@ -202,6 +221,8 @@ func polyReduce(r poly) poly {
return
r
}
// polyCSubQ applies the conditional subtraction of `Q` to each coefficient
// of a polynomial.
func
polyCSubQ
(
r
poly
)
poly
{
for
i
:=
0
;
i
<
paramsN
;
i
++
{
r
[
i
]
=
byteopsCSubQ
(
r
[
i
])
...
...
@@ -209,6 +230,7 @@ func polyCSubQ(r poly) poly {
return
r
}
// polyAdd adds two polynomials.
func
polyAdd
(
a
poly
,
b
poly
)
poly
{
for
i
:=
0
;
i
<
paramsN
;
i
++
{
a
[
i
]
=
a
[
i
]
+
b
[
i
]
...
...
@@ -216,6 +238,7 @@ func polyAdd(a poly, b poly) poly {
return
a
}
// polySub subtracts two polynomials.
func
polySub
(
a
poly
,
b
poly
)
poly
{
for
i
:=
0
;
i
<
paramsN
;
i
++
{
a
[
i
]
=
a
[
i
]
-
b
[
i
]
...
...
@@ -223,17 +246,24 @@ func polySub(a poly, b poly) poly {
return
a
}
// polyvecNew instantiates a new vector of polynomials.
func
polyvecNew
(
paramsK
int
)
polyvec
{
var
pv
polyvec
=
make
([]
poly
,
paramsK
)
return
pv
}
// polyvecCompress lossily compresses and serializes a vector of polynomials.
func
polyvecCompress
(
a
polyvec
,
paramsK
int
)
[]
byte
{
var
r
[]
byte
polyvecCSubQ
(
a
,
paramsK
)
rr
:=
0
switch
paramsK
{
case
2
:
r
=
make
([]
byte
,
paramsPolyvecCompressedBytesK2
)
r
=
make
([]
byte
,
paramsPolyvecCompressedBytesK
51
2
)
case
3
:
r
=
make
([]
byte
,
paramsPolyvecCompressedBytesK
3
)
r
=
make
([]
byte
,
paramsPolyvecCompressedBytesK
768
)
case
4
:
r
=
make
([]
byte
,
paramsPolyvecCompressedBytesK4
)
r
=
make
([]
byte
,
paramsPolyvecCompressedBytesK
102
4
)
}
switch
paramsK
{
case
2
,
3
:
...
...
@@ -277,6 +307,9 @@ func polyvecCompress(a polyvec, paramsK int) []byte {
}
}
// polyvecDecompress de-serializes and decompresses a vector of polynomials and
// represents the approximate inverse of polyvecCompress. Since compression is lossy,
// the results of decompression will may not match the original vector of polynomials.
func
polyvecDecompress
(
a
[]
byte
,
paramsK
int
)
polyvec
{
r
:=
polyvecNew
(
paramsK
)
aa
:=
0
...
...
@@ -317,6 +350,7 @@ func polyvecDecompress(a []byte, paramsK int) polyvec {
return
r
}
// polyvecToBytes serializes a vector of polynomials.
func
polyvecToBytes
(
a
polyvec
,
paramsK
int
)
[]
byte
{
r
:=
[]
byte
{}
for
i
:=
0
;
i
<
paramsK
;
i
++
{
...
...
@@ -325,6 +359,7 @@ func polyvecToBytes(a polyvec, paramsK int) []byte {
return
r
}
// polyvecFromBytes deserializes a vector of polynomials.
func
polyvecFromBytes
(
a
[]
byte
,
paramsK
int
)
polyvec
{
r
:=
polyvecNew
(
paramsK
)
for
i
:=
0
;
i
<
paramsK
;
i
++
{
...
...
@@ -335,18 +370,25 @@ func polyvecFromBytes(a []byte, paramsK int) polyvec {
return
r
}
// polyvecNtt applies forward number-theoretic transforms (NTT)
// to all elements of a vector of polynomials.
func
polyvecNtt
(
r
polyvec
,
paramsK
int
)
{
for
i
:=
0
;
i
<
paramsK
;
i
++
{
r
[
i
]
=
polyNtt
(
r
[
i
])
}
}
// polyvecInvNttToMont applies the inverse number-theoretic transform (NTT)
// to all elements of a vector of polynomials and multiplies by Montgomery
// factor `2^16`.
func
polyvecInvNttToMont
(
r
polyvec
,
paramsK
int
)
{
for
i
:=
0
;
i
<
paramsK
;
i
++
{
r
[
i
]
=
polyInvNttToMont
(
r
[
i
])
}
}
// polyvecPointWiseAccMontgomery pointwise-multiplies elements of polynomial-vectors
// `a` and `b`, accumulates the results into `r`, and then multiplies by `2^-16`.
func
polyvecPointWiseAccMontgomery
(
a
polyvec
,
b
polyvec
,
paramsK
int
)
poly
{
r
:=
polyBaseMulMontgomery
(
a
[
0
],
b
[
0
])
for
i
:=
1
;
i
<
paramsK
;
i
++
{
...
...
@@ -356,18 +398,23 @@ func polyvecPointWiseAccMontgomery(a polyvec, b polyvec, paramsK int) poly {
return
polyReduce
(
r
)
}
// polyvecReduce applies Barrett reduction to each coefficient of each element
// of a vector of polynomials.
func
polyvecReduce
(
r
polyvec
,
paramsK
int
)
{
for
i
:=
0
;
i
<
paramsK
;
i
++
{
r
[
i
]
=
polyReduce
(
r
[
i
])
}
}
// polyvecCSubQ applies the conditional subtraction of `Q` to each coefficient
// of each element of a vector of polynomials.
func
polyvecCSubQ
(
r
polyvec
,
paramsK
int
)
{
for
i
:=
0
;
i
<
paramsK
;
i
++
{
r
[
i
]
=
polyCSubQ
(
r
[
i
])
}
}
// polyvecAdd adds two vectors of polynomials.
func
polyvecAdd
(
a
polyvec
,
b
polyvec
,
paramsK
int
)
{
for
i
:=
0
;
i
<
paramsK
;
i
++
{
a
[
i
]
=
polyAdd
(
a
[
i
],
b
[
i
])
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment