mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-27 00:55:17 +00:00
1291 lines
32 KiB
Go
1291 lines
32 KiB
Go
/*
|
|
* Copyright (c) 2012-2020 MIRACL UK Ltd.
|
|
*
|
|
* This file is part of MIRACL Core
|
|
* (see https://github.com/miracl/core).
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
|
|
Arwa Alblooshi 15/12/2022
|
|
*/
|
|
package core
|
|
|
|
//import "fmt"
|
|
|
|
//q = 8380417
|
|
const DL_LGN = 8
|
|
const DL_DEGREE = (1 << DL_LGN)
|
|
const DL_PRIME = 0x7fe001
|
|
const DL_D = 13
|
|
const DL_TD = (23 - DL_D)
|
|
|
|
const DL_ONE = 0x3FFE00 // R mod Q
|
|
const DL_COMBO = 0xA3FA // ONE*inv mod Q
|
|
const DL_R2MODP = 0x2419FF // R^2 mod Q
|
|
const DL_ND = 0xFC7FDFFF // 1/(R-Q) mod R
|
|
|
|
const DL_MAXLG = 19
|
|
const DL_MAXK = 8 // could reduce these if not using highest security
|
|
const DL_MAXL = 7
|
|
const DL_YBYTES = (((DL_MAXLG + 1) * DL_DEGREE) / 8)
|
|
|
|
const DL_SK_SIZE_2 = (32*3+DL_DEGREE* (4*13+4*3+4*3)/8)
|
|
const DL_PK_SIZE_2 = ((4*DL_DEGREE*DL_TD)/8 + 32)
|
|
const DL_SIG_SIZE_2 = ((DL_DEGREE*4*(17+1))/8 + 80 + 4 + 32)
|
|
|
|
const DL_SK_SIZE_3 = (32*3 + DL_DEGREE*(6*13+5*4+6*4)/8)
|
|
const DL_PK_SIZE_3 = ((6*DL_DEGREE*DL_TD)/8 + 32)
|
|
const DL_SIG_SIZE_3 = ((DL_DEGREE*5*(19+1))/8 + 55 + 6 + 32)
|
|
|
|
const DL_SK_SIZE_5 = (32*3 + DL_DEGREE*(8*13+7*3+8*3)/8)
|
|
const DL_PK_SIZE_5 = ((8*DL_DEGREE*DL_TD)/8 + 32)
|
|
const DL_SIG_SIZE_5 = ((DL_DEGREE*7*(19+1))/8 + 75 + 8 + 32)
|
|
|
|
// parameters for each security level
|
|
// tau,gamma1,gamma2,K,L,eta,lg(2*eta+1),omega
|
|
|
|
var DL_PARAMS_2 = []int{39, 17, 88, 4, 4, 2, 3, 80}
|
|
var DL_PARAMS_3 = []int{49, 19, 32, 6, 5, 4, 4, 55}
|
|
var DL_PARAMS_5 = []int{60, 19, 32, 8, 7, 2, 3, 75}
|
|
|
|
var DL_roots = []int32{0x3ffe00, 0x64f7, 0x581103, 0x77f504, 0x39e44, 0x740119, 0x728129, 0x71e24, 0x1bde2b, 0x23e92b, 0x7a64ae, 0x5ff480, 0x2f9a75, 0x53db0a, 0x2f7a49, 0x28e527, 0x299658, 0xfa070, 0x6f65a5, 0x36b788, 0x777d91, 0x6ecaa1, 0x27f968, 0x5fb37c, 0x5f8dd7, 0x44fae8, 0x6a84f8, 0x4ddc99, 0x1ad035, 0x7f9423, 0x3d3201, 0x445c5, 0x294a67, 0x17620, 0x2ef4cd, 0x35dec5, 0x668504, 0x49102d, 0x5927d5, 0x3bbeaf, 0x44f586, 0x516e7d, 0x368a96, 0x541e42, 0x360400, 0x7b4a4e, 0x23d69c, 0x77a55e, 0x65f23e, 0x66cad7, 0x357e1e, 0x458f5a, 0x35843f, 0x5f3618, 0x67745d, 0x38738c, 0xc63a8, 0x81b9a, 0xe8f76, 0x3b3853, 0x3b8534, 0x58dc31, 0x1f9d54, 0x552f2e, 0x43e6e6, 0x688c82, 0x47c1d0, 0x51781a, 0x69b65e, 0x3509ee, 0x2135c7, 0x67afbc, 0x6caf76, 0x1d9772, 0x419073, 0x709cf7, 0x4f3281, 0x4fb2af, 0x4870e1, 0x1efca, 0x3410f2, 0x70de86, 0x20c638, 0x296e9f, 0x5297a4, 0x47844c, 0x799a6e, 0x5a140a, 0x75a283, 0x6d2114, 0x7f863c, 0x6be9f8, 0x7a0bde, 0x1495d4, 0x1c4563, 0x6a0c63, 0x4cdbea, 0x40af0, 0x7c417, 0x2f4588, 0xad00, 0x6f16bf, 0xdcd44, 0x3c675a, 0x470bcb, 0x7fbe7f, 0x193948, 0x4e49c1, 0x24756c, 0x7ca7e0, 0xb98a1, 0x6bc809, 0x2e46c, 0x49a809, 0x3036c2, 0x639ff7, 0x5b1c94, 0x7d2ae1, 0x141305, 0x147792, 0x139e25, 0x67b0e1, 0x737945, 0x69e803, 0x51cea3, 0x44a79d, 0x488058, 0x3a97d9, 0x1fea93, 0x33ff5a, 0x2358d4, 0x3a41f8, 0x4cdf73, 0x223dfb, 0x5a8ba0, 0x498423, 0x412f5, 0x252587, 0x6d04f1, 0x359b5d, 0x4a28a1, 0x4682fd, 0x6d9b57, 0x4f25df, 0xdbe5e, 0x1c5e1a, 0xde0e6, 0xc7f5a, 0x78f83, 0x67428b, 0x7f3705, 0x77e6fd, 0x75e022, 0x503af7, 0x1f0084, 0x30ef86, 0x49997e, 0x77dcd7, 0x742593, 0x4901c3, 0x53919, 0x4610c, 0x5aad42, 0x3eb01b, 0x3472e7, 0x4ce03c, 0x1a7cc7, 0x31924, 0x2b5ee5, 0x291199, 0x585a3b, 0x134d71, 0x3de11c, 0x130984, 0x25f051, 0x185a46, 0x466519, 0x1314be, 0x283891, 0x49bb91, 0x52308a, 0x1c853f, 0x1d0b4b, 0x6fd6a7, 0x6b88bf, 0x12e11b, 0x4d3e3f, 0x6a0d30, 0x78fde5, 0x1406c7, 0x327283, 0x61ed6f, 0x6c5954, 0x1d4099, 0x590579, 0x6ae5ae, 0x16e405, 0xbdbe7, 0x221de8, 0x33f8cf, 0x779935, 0x54aa0d, 0x665ff9, 0x63b158, 0x58711c, 0x470c13, 0x910d8, 0x463e20, 0x612659, 0x251d8b, 0x2573b7, 0x7d5c90, 0x1ddd98, 0x336898, 0x2d4bb, 0x6d73a8, 0x4f4cbf, 0x27c1c, 0x18aa08, 0x2dfd71, 0xc5ca5, 0x19379a, 0x478168, 0x646c3e, 0x51813d, 0x35c539, 0x3b0115, 0x41dc0, 0x21c4f7, 0x70fbf5, 0x1a35e7, 0x7340e, 0x795d46, 0x1a4cd0, 0x645caf, 0x1d2668, 0x666e99, 0x6f0634, 0x7be5db, 0x455fdc, 0x530765, 0x5dc1b0, 0x7973de, 0x5cfd0a, 0x2cc93, 0x70f806, 0x189c2a, 0x49c5aa, 0x776a51, 0x3bcf2c, 0x7f234f, 0x6b16e0, 0x3c15ca, 0x155e68, 0x72f6b7, 0x1e29ce}
|
|
var DL_iroots = []int32{0x3ffe00, 0x7f7b0a, 0x7eafd, 0x27cefe, 0x78c1dd, 0xd5ed8, 0xbdee8, 0x7c41bd, 0x56fada, 0x5065b8, 0x2c04f7, 0x50458c, 0x1feb81, 0x57b53, 0x5bf6d6, 0x6401d6, 0x7b9a3c, 0x42ae00, 0x4bde, 0x650fcc, 0x320368, 0x155b09, 0x3ae519, 0x20522a, 0x202c85, 0x57e699, 0x111560, 0x86270, 0x492879, 0x107a5c, 0x703f91, 0x5649a9, 0x2ab0d3, 0x6042ad, 0x2703d0, 0x445acd, 0x44a7ae, 0x71508b, 0x77c467, 0x737c59, 0x476c75, 0x186ba4, 0x20a9e9, 0x4a5bc2, 0x3a50a7, 0x4a61e3, 0x19152a, 0x19edc3, 0x83aa3, 0x5c0965, 0x495b3, 0x49dc01, 0x2bc1bf, 0x49556b, 0x2e7184, 0x3aea7b, 0x442152, 0x26b82c, 0x36cfd4, 0x195afd, 0x4a013c, 0x50eb34, 0x7e69e1, 0x56959a, 0x454828, 0x375fa9, 0x3b3864, 0x2e115e, 0x15f7fe, 0xc66bc, 0x182f20, 0x6c41dc, 0x6b686f, 0x6bccfc, 0x2b520, 0x24c36d, 0x1c400a, 0x4fa93f, 0x3637f8, 0x7cfb95, 0x1417f8, 0x744760, 0x33821, 0x5b6a95, 0x319640, 0x66a6b9, 0x2182, 0x38d436, 0x4378a7, 0x7212bd, 0x10c942, 0x7f3301, 0x509a79, 0x781bea, 0x7bd511, 0x330417, 0x15d39e, 0x639a9e, 0x6b4a2d, 0x5d423, 0x13f609, 0x59c5, 0x12beed, 0xa3d7e, 0x25cbf7, 0x64593, 0x385bb5, 0x2d485d, 0x567162, 0x5f19c9, 0xf017b, 0x4bcf0f, 0x7df037, 0x376f20, 0x302d52, 0x30ad80, 0xf430a, 0x3e4f8e, 0x62488f, 0x13308b, 0x183045, 0x5eaa3a, 0x4ad613, 0x1629a3, 0x2e67e7, 0x381e31, 0x17537f, 0x3bf91b, 0x61b633, 0xce94a, 0x6a8199, 0x43ca37, 0x14c921, 0xbcb2, 0x4410d5, 0x875b0, 0x361a57, 0x6743d7, 0xee7fb, 0x7d136e, 0x22e2f7, 0x66c23, 0x221e51, 0x2cd89c, 0x3a8025, 0x3fa26, 0x10d9cd, 0x197168, 0x62b999, 0x1b8352, 0x659331, 0x682bb, 0x78abf3, 0x65aa1a, 0xee40c, 0x5e1b0a, 0x7bc241, 0x44deec, 0x4a1ac8, 0x2e5ec4, 0x1b73c3, 0x385e99, 0x66a867, 0x73835c, 0x51e290, 0x6735f9, 0x7d63e5, 0x309342, 0x126c59, 0x7d0b46, 0x4c7769, 0x620269, 0x28371, 0x5a6c4a, 0x5ac276, 0x1eb9a8, 0x39a1e1, 0x76cf29, 0x38d3ee, 0x276ee5, 0x1c2ea9, 0x198008, 0x2b35f4, 0x846cc, 0x4be732, 0x5dc219, 0x74041a, 0x68fbfc, 0x14fa53, 0x26da88, 0x629f68, 0x1386ad, 0x1df292, 0x4d6d7e, 0x6bd93a, 0x6e21c, 0x15d2d1, 0x32a1c2, 0x6cfee6, 0x145742, 0x10095a, 0x62d4b6, 0x635ac2, 0x2daf77, 0x362470, 0x57a770, 0x6ccb43, 0x397ae8, 0x6785bb, 0x59efb0, 0x6cd67d, 0x41fee5, 0x6c9290, 0x2785c6, 0x56ce68, 0x54811c, 0x7cc6dd, 0x65633a, 0x32ffc5, 0x4b6d1a, 0x412fe6, 0x2532bf, 0x7b7ef5, 0x7aa6e8, 0x36de3e, 0xbba6e, 0x8032a, 0x364683, 0x4ef07b, 0x60df7d, 0x2fa50a, 0x9ffdf, 0x7f904, 0xa8fc, 0x189d76, 0x78507e, 0x7360a7, 0x71ff1b, 0x6381e7, 0x7221a3, 0x30ba22, 0x1244aa, 0x395d04, 0x35b760, 0x4a44a4, 0x12db10, 0x5aba7a, 0x7bcd0c, 0x365bde, 0x255461, 0x5da206, 0x33008e, 0x459e09, 0x5c872d, 0x4be0a7, 0x5ff56e}
|
|
|
|
func DL_round(a int32, b int32) int32 {
|
|
return (a + b/2) / b
|
|
}
|
|
|
|
// constant time absolute vaue
|
|
func DL_nabs(x int32) int32 {
|
|
mask := (x >> 31)
|
|
return (x + mask)^mask
|
|
}
|
|
|
|
// Montgomery stuff
|
|
func DL_redc(T uint64) int32 {
|
|
m := uint32(T) * (uint32(DL_ND))
|
|
return int32((uint64(m)*DL_PRIME + T) >> 32)
|
|
}
|
|
|
|
func DL_nres(x uint32) int32 {
|
|
return DL_redc(uint64(x)*DL_R2MODP)
|
|
}
|
|
|
|
func DL_modmul(a uint32, b uint32) int32 {
|
|
return DL_redc(uint64(a)*uint64(b))
|
|
}
|
|
|
|
//make all elements +ve
|
|
func DL_poly_pos(p []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p[i] += (p[i] >> 31)&DL_PRIME
|
|
}
|
|
}
|
|
|
|
// NTT code
|
|
|
|
// Important!
|
|
// DL_nres(x); DL_ntt(x)
|
|
// DL_nres(y); DL_ntt(y)
|
|
// z=x*y
|
|
// DL_intt(z);
|
|
// DL_redc(z);
|
|
|
|
// is equivalent to (note that DL_nres() and DL_redc() cancel out)
|
|
|
|
// DL_ntt(x);
|
|
// DL_nres(y); DL_ntt(y);
|
|
// z=x*y
|
|
// DL_intt(z)
|
|
|
|
// is equivalent to
|
|
|
|
// DL_ntt(x)
|
|
// DL_ntt(y)
|
|
// z=x*y
|
|
// DL_intt(z)
|
|
// DL_nres(z)
|
|
|
|
// In all cases z ends up in normal (non-Montgomery) form!
|
|
// So the conversion to Montgomery form can be "pushed" through the calculation.
|
|
|
|
// Here DL_intt(z) <- DL_intt(z);DL_nres(z);
|
|
// Combining is more efficient
|
|
// note that DL_ntt() and DL_intt() are not mutually inverse
|
|
|
|
/* NTT code */
|
|
/* Cooley-Tukey NTT */
|
|
/* Excess of 2 allowed on input - coefficients must be < 2*PRIME */
|
|
|
|
func DL_ntt(x []int32) {
|
|
|
|
var start int
|
|
len := DL_DEGREE/2
|
|
|
|
var S, V int32
|
|
var q int32 = DL_PRIME
|
|
|
|
//Make positive
|
|
DL_poly_pos(x)
|
|
m := 1
|
|
for m < DL_DEGREE {
|
|
start = 0
|
|
for i := 0; i < m; i++ {
|
|
S = DL_roots[m+i]
|
|
for j := start; j < start+len; j++ {
|
|
V = DL_modmul(uint32(x[j+len]), uint32(S))
|
|
x[j+len] = x[j] + 2 * q - V
|
|
x[j] = x[j] + V
|
|
}
|
|
start += 2 * len
|
|
}
|
|
len /= 2
|
|
m *= 2
|
|
}
|
|
}
|
|
|
|
// Gentleman-Sande INTT
|
|
// Excess of 2 allowed on input - coefficients must be < 2*PRIME
|
|
// Output fully reduced
|
|
const NTTL = 1
|
|
|
|
func DL_intt(x []int32) {
|
|
var k,lim int
|
|
t := 1
|
|
var S,U,V,W int32
|
|
var q int32 = DL_PRIME
|
|
m := DL_DEGREE/2
|
|
n := DL_LGN
|
|
for m >= 1 {
|
|
lim = NTTL >> n
|
|
n--
|
|
k = 0
|
|
for i := 0; i < m; i++ {
|
|
S = DL_iroots[m+i]
|
|
for j := k; j < k+t; j++ {
|
|
if NTTL > 1 {
|
|
if m < NTTL && j < k+lim {
|
|
U = DL_modmul(uint32(x[j]), DL_ONE)
|
|
V = DL_modmul(uint32(x[j+t]), DL_ONE)
|
|
} else {
|
|
U = x[j]
|
|
V = x[j+t]
|
|
}
|
|
} else {
|
|
U = x[j]
|
|
V = x[j+t]
|
|
}
|
|
x[j] = U + V
|
|
W = U + (DL_DEGREE/NTTL)*q - V
|
|
x[j+t] = DL_modmul(uint32(W), uint32(S))
|
|
//T := int64(W)*int64(S)
|
|
//var M int64 = (T*DL_ND) & 0xffffffff
|
|
//R := int((M * int64(DL_PRIME+T)) >> 32)
|
|
//fmt.Printf("x,W,S= %d %d %d %x %x %d\n",x[j+t],W,S,T,M,R)
|
|
}
|
|
k += 2 * t
|
|
}
|
|
t *= 2
|
|
m /= 2
|
|
}
|
|
//fmt.Printf("\nx[0]= %d\n",x[0])
|
|
//fmt.Printf("x[1]= %d\n",x[1])
|
|
for j := 0; j < DL_DEGREE; j++ {
|
|
//fully reduce, DL_nres combined with 1/DEGREE
|
|
x[j] = DL_modmul(uint32(x[j]), DL_COMBO)
|
|
x[j] -= q
|
|
x[j] += (x[j] >> 31)&q
|
|
}
|
|
}
|
|
|
|
func DL_nres_it(p []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p[i] = DL_nres(uint32(p[i]))
|
|
}
|
|
}
|
|
|
|
func DL_redc_it(p []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p[i] = DL_redc(uint64(p[i]))
|
|
}
|
|
}
|
|
|
|
//copy polynomial
|
|
func DL_poly_copy(p1 []int32, p2 []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = p2[i]
|
|
}
|
|
}
|
|
|
|
//copy from small polynomial
|
|
func DL_poly_scopy(p1 []int32, p2 []int8) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = int32(p2[i])
|
|
}
|
|
}
|
|
|
|
//copy from medium polynomial
|
|
func DL_poly_mcopy(p1 []int32, p2 []int16) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = int32(p2[i])
|
|
}
|
|
}
|
|
|
|
func DL_poly_zero(p1 []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = 0
|
|
}
|
|
}
|
|
|
|
func DL_poly_negate(p1 []int32, p2 []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = DL_PRIME - p2[i]
|
|
}
|
|
}
|
|
|
|
func DL_poly_mul(p1 []int32, p2 []int32, p3 []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = DL_modmul(uint32(p2[i]), uint32(p3[i]))
|
|
}
|
|
}
|
|
|
|
func DL_poly_add(p1 []int32, p2 []int32, p3 []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = p2[i] + p3[i]
|
|
}
|
|
}
|
|
|
|
func DL_poly_sub(p1 []int32, p2 []int32, p3 []int32) {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
p1[i] = p2[i] + DL_PRIME - p3[i]
|
|
}
|
|
}
|
|
|
|
//reduce inputs that are already < 2q
|
|
func DL_poly_soft_reduce(poly []int32) {
|
|
var e int32
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
e = poly[i] - DL_PRIME
|
|
poly[i] = e + ((e >> 31)&DL_PRIME)
|
|
|
|
}
|
|
}
|
|
|
|
//fully reduces modulo q
|
|
func DL_poly_hard_reduce(poly []int32) {
|
|
var e int32
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
e = DL_modmul(uint32(poly[i]), DL_ONE) //reduces to < 2q
|
|
e = e - DL_PRIME
|
|
poly[i] = e + ((e >> 31)&DL_PRIME) //finishes it off
|
|
}
|
|
}
|
|
|
|
//Generate A[i][j] from rho
|
|
func DL_ExpandAij(rho []byte, Aij []int32, i int, j int) {
|
|
sh := NewSHA3(SHA3_SHAKE128)
|
|
var cf int32
|
|
//var b0, b1, b2 uint32
|
|
var buff [4*DL_DEGREE]byte // should be plenty
|
|
|
|
for m := 0; m < 32; m++ {
|
|
sh.Process(rho[m])
|
|
}
|
|
sh.Process(byte(j & 0xFF))
|
|
sh.Process(byte(i & 0xff))
|
|
sh.Shake(buff[:], 4*DL_DEGREE)
|
|
m := 0
|
|
n := 0
|
|
for m < DL_DEGREE {
|
|
b0 := uint32(buff[n]&0xff)
|
|
n++
|
|
b1 := uint32(buff[n]&0xff)
|
|
n++
|
|
b2 := uint32(buff[n]&0xff)
|
|
n++
|
|
cf = int32(((b2 & 0x7f) << 16) + (b1 << 8) + b0)
|
|
if cf >= DL_PRIME {
|
|
continue
|
|
}
|
|
Aij[m] = cf
|
|
m++
|
|
}
|
|
}
|
|
|
|
// array t has ab active bits per word
|
|
// extract bytes from array of words
|
|
// if max!=0 then -max<=t[i]<=+max
|
|
func DL_nextbyte32(ab int, max int, t []int32, position []int) byte {
|
|
ptr := position[0] // index in array
|
|
bts := position[1] // bit index in word
|
|
left := ab - bts // number of bits left in this word
|
|
i := 0
|
|
k := ptr % 256
|
|
var r int32
|
|
var w int32 = t[k]
|
|
|
|
if max != 0 {
|
|
w = int32(max) - w
|
|
}
|
|
r = w >> bts
|
|
for left < 8 {
|
|
i++
|
|
w = t[k+i]
|
|
if max != 0 {
|
|
w = int32(max) - w
|
|
}
|
|
r |= w << left
|
|
left += ab
|
|
}
|
|
bts += 8
|
|
for bts >= ab {
|
|
bts -= ab
|
|
ptr++
|
|
}
|
|
position[0] = ptr
|
|
position[1] = bts
|
|
|
|
return byte(r & 0xff)
|
|
}
|
|
|
|
// array t has ab active bits per word
|
|
// extract dense bytes from array of words
|
|
// if max!=0 then -max<=t[i]<=+max
|
|
func DL_nextbyte16(ab int, max int, t []int16, position []int) byte {
|
|
ptr := position[0] // index in array
|
|
bts := position[1] // bit index in word
|
|
left := ab - bts // number of bits left in this word
|
|
i := 0
|
|
k := ptr % 256
|
|
var r int32
|
|
var w int32 = int32(t[k])
|
|
if max != 0 {
|
|
w = int32(max) - w
|
|
}
|
|
r = w >> bts
|
|
for left < 8 {
|
|
i++
|
|
w = int32(t[k+i])
|
|
if max != 0 {
|
|
w = int32(max) - w
|
|
}
|
|
r |= w << left
|
|
left += ab
|
|
}
|
|
bts += 8
|
|
for bts >= ab {
|
|
bts -= ab
|
|
ptr++
|
|
}
|
|
position[0] = ptr
|
|
position[1] = bts
|
|
|
|
return byte(r & 0xff)
|
|
}
|
|
|
|
// array t has ab active bits per word
|
|
// extract dense bytes from array of words
|
|
// if max!=0 then -max<=t[i]<=+max
|
|
func DL_nextbyte8(ab int, max int, t []int8, position []int) byte {
|
|
ptr := position[0] // index in array
|
|
bts := position[1] // bit index in word
|
|
left := ab - bts // number of bits left in this word
|
|
i := 0
|
|
k := ptr % 256
|
|
var r int32
|
|
var w int32 = int32(t[k])
|
|
if max != 0 {
|
|
w = int32(max) - w
|
|
}
|
|
r = w >> bts
|
|
for left < 8 {
|
|
i++
|
|
w = int32(t[k+i])
|
|
if max != 0 {
|
|
w = int32(max) - w
|
|
}
|
|
r |= w << left
|
|
left += ab
|
|
}
|
|
bts += 8
|
|
for bts >= ab {
|
|
bts -= ab
|
|
ptr++
|
|
}
|
|
position[0] = ptr
|
|
position[1] = bts
|
|
|
|
return byte(r&0xff)
|
|
}
|
|
|
|
// extract ab bits into word from dense byte stream
|
|
func DL_nextword(ab int, max int, t []byte, position []int) int32 {
|
|
ptr := position[0] // index in array
|
|
bts := position[1] // bit index in word
|
|
r := int32(t[ptr]>>bts)
|
|
mask := int32((1<<ab)-1)
|
|
var w int32
|
|
i := 0
|
|
gotbits := 8 - bts // bits left in current byte
|
|
for gotbits < ab {
|
|
i++
|
|
w = int32(t[ptr+i])
|
|
r |= w<<gotbits
|
|
gotbits += 8
|
|
}
|
|
bts += ab
|
|
for bts >= 8 {
|
|
bts -= 8
|
|
ptr++
|
|
}
|
|
w = r&mask
|
|
if max != 0 {
|
|
w = int32(max) - w
|
|
}
|
|
position[0] = ptr
|
|
position[1] = bts
|
|
return w
|
|
}
|
|
|
|
//pack public key
|
|
func DL_pack_pk(params []int, pk []byte, rho []byte, t1 [][DL_DEGREE]int16) int {
|
|
var pos [2]int
|
|
pos[0] = 0; pos[1] = 0
|
|
ck := params[3]
|
|
for i := 0; i < 32; i++ {
|
|
pk[i] = rho[i]
|
|
}
|
|
n := 32
|
|
for j := 0; j < ck; j++ {
|
|
for i := 0; i < (DL_DEGREE*DL_TD)/8; i++ {
|
|
pk[n] = DL_nextbyte16(DL_TD, 0, t1[j][:], pos[:])
|
|
n++
|
|
}
|
|
}
|
|
return n
|
|
}
|
|
|
|
//unpack public key
|
|
func DL_unpack_pk(params []int, rho []byte, t1 [][DL_DEGREE]int16, pk []byte) {
|
|
var pos [2]int
|
|
pos[0] = 32; pos[1] = 0
|
|
ck := params[3]
|
|
for i := 0; i < 32; i++ {
|
|
rho[i] = pk[i]
|
|
}
|
|
for j := 0; j < ck; j++ {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
t1[j][i] = int16(DL_nextword(DL_TD, 0, pk, pos[:]))
|
|
}
|
|
}
|
|
}
|
|
|
|
// secret key of size 32*3+DEGREE*(K*D+L*LG2ETA1+K*LG2ETA1)/8
|
|
func DL_pack_sk(params []int, sk []byte, rho []byte, bK []byte, tr []byte, s1 [][DL_DEGREE]int8, s2 [][DL_DEGREE]int8, t0 [][DL_DEGREE]int16) int {
|
|
n := 32
|
|
ck := params[3]
|
|
el := params[4]
|
|
eta := params[5]
|
|
lg2eta1 := params[6]
|
|
|
|
for i := 0; i < 32; i++ {
|
|
sk[i] = rho[i]
|
|
}
|
|
for i := 0; i < 32; i++ {
|
|
sk[n] = bK[i]
|
|
n++
|
|
}
|
|
for i := 0; i < 32; i++ {
|
|
sk[n] = tr[i]
|
|
n++
|
|
}
|
|
|
|
var pos [2]int
|
|
pos[0] = 0; pos[1] = 0
|
|
|
|
for j := 0; j < el; j++ {
|
|
for i := 0; i < (DL_DEGREE*lg2eta1)/8; i++ {
|
|
sk[n] = DL_nextbyte8(lg2eta1, eta, s1[j][:], pos[:])
|
|
n++
|
|
}
|
|
}
|
|
pos[0] = 0; pos[1] = 0
|
|
for j := 0; j < ck; j++ {
|
|
for i := 0; i < (DL_DEGREE*lg2eta1)/8; i++ {
|
|
sk[n] = DL_nextbyte8(lg2eta1, eta, s2[j][:], pos[:])
|
|
n++
|
|
}
|
|
}
|
|
pos[0] = 0; pos[1] = 0
|
|
for j := 0; j < ck; j++ {
|
|
for i := 0; i < (DL_DEGREE*DL_D)/8; i++ {
|
|
sk[n] = DL_nextbyte16(DL_D, (1 << (DL_D - 1)), t0[j][:], pos[:])
|
|
n++
|
|
}
|
|
}
|
|
return n
|
|
}
|
|
|
|
func DL_unpack_sk(params []int, rho []byte, bK []byte, tr []byte, s1 [][DL_DEGREE]int8, s2 [][DL_DEGREE]int8, t0 [][DL_DEGREE]int16, sk []byte) {
|
|
n := 32
|
|
ck := params[3]
|
|
el := params[4]
|
|
eta := params[5]
|
|
lg2eta1 := params[6]
|
|
|
|
for i := 0; i < 32; i++ {
|
|
rho[i] = sk[i]
|
|
}
|
|
for i := 0; i < 32; i++ {
|
|
bK[i] = sk[n]
|
|
n++
|
|
}
|
|
for i := 0; i < 32; i++ {
|
|
tr[i] = sk[n]
|
|
n++
|
|
}
|
|
|
|
var pos [2]int
|
|
pos[0] = n; pos[1] = 0
|
|
for j := 0; j < el; j++ {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
s1[j][i] = int8(DL_nextword(lg2eta1, eta, sk, pos[:]))
|
|
}
|
|
}
|
|
//fmt.Printf("lg2eta1 = %d eta= %d\n",lg2eta1,eta)
|
|
//fmt.Printf("s1[0][0]= %d sk[0] = %d\n",s1[0][0],sk[n])
|
|
for j := 0; j < ck; j++ {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
s2[j][i] = int8(DL_nextword(lg2eta1, eta, sk, pos[:]))
|
|
}
|
|
}
|
|
for j := 0; j < ck; j++ {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
t0[j][i] = int16(DL_nextword(DL_D, (1 << (DL_D - 1)), sk, pos[:]))
|
|
}
|
|
}
|
|
}
|
|
|
|
// pack signature - change z
|
|
func DL_pack_sig(params []int, sig []byte, z [][DL_DEGREE]int32, ct []byte, h []byte) int {
|
|
lg := params[1]
|
|
gamma1 := 1 << lg
|
|
ck := params[3]
|
|
el := params[4]
|
|
omega := params[7]
|
|
|
|
var t int32
|
|
|
|
for i := 0; i < 32; i++ {
|
|
sig[i] = ct[i]
|
|
}
|
|
|
|
n := 32
|
|
var pos [2]int
|
|
pos[0] = 0; pos[1] = 0
|
|
//pre-process z
|
|
for i := 0; i < el; i++ {
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
t = z[i][m]
|
|
if t > DL_PRIME/2 {
|
|
t -= DL_PRIME
|
|
}
|
|
t = int32(gamma1) - t
|
|
z[i][m] = t
|
|
}
|
|
}
|
|
for j := 0; j < el; j++ {
|
|
for i := 0; i < (DL_DEGREE*(lg+1))/8; i++ {
|
|
sig[n] = DL_nextbyte32(lg+1, 0, z[j][:], pos[:])
|
|
n++
|
|
}
|
|
}
|
|
for i := 0; i < omega+ck; i++ {
|
|
sig[n] = h[i]
|
|
n++
|
|
}
|
|
return n
|
|
}
|
|
|
|
func DL_unpack_sig(params []int, z [][DL_DEGREE]int32, ct []byte, h []byte, sig []byte) {
|
|
lg := params[1]
|
|
gamma1 := 1 << lg
|
|
ck := params[3]
|
|
el := params[4]
|
|
omega := params[7]
|
|
var t int32
|
|
m := 32 + (el*DL_DEGREE*(lg+1))/8
|
|
|
|
for i := 0; i < 32; i++ {
|
|
ct[i] = sig[i]
|
|
}
|
|
|
|
var pos [2]int
|
|
pos[0] = 32; pos[1] = 0
|
|
for j := 0; j < el; j++ {
|
|
for i := 0; i < DL_DEGREE; i++ {
|
|
t = DL_nextword(lg+1, 0, sig, pos[:])
|
|
t = int32(gamma1)-t
|
|
if t < 0 {
|
|
t += DL_PRIME
|
|
}
|
|
z[j][i] = t
|
|
}
|
|
}
|
|
for i := 0; i < omega+ck; i++ {
|
|
h[i] = sig[m]
|
|
m++
|
|
}
|
|
}
|
|
|
|
// rejection sampling in range -ETA to +ETA
|
|
func DL_sample_Sn(params []int, rhod []byte, s []int8, n int) {
|
|
eta := int8(params[5])
|
|
lg2eta1 := params[6]
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
var buff [272]byte
|
|
|
|
for m := 0; m < 64; m++ {
|
|
sh.Process(rhod[m])
|
|
}
|
|
sh.Process(byte(n & 0xff))
|
|
sh.Process(byte((n >> 8) & 0xff))
|
|
sh.Shake(buff[:], 272)
|
|
|
|
var pos [2]int
|
|
pos[0] = 0; pos[1] = 0
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
for next := true; next; next = s[m] > 2*eta {
|
|
s[m] = int8(DL_nextword(lg2eta1, 0, buff[:], pos[:]))
|
|
}
|
|
s[m] = int8(eta - s[m])
|
|
}
|
|
}
|
|
|
|
//uniform random sampling
|
|
func DL_sample_Y(params []int, k int, rhod []byte, y [][DL_DEGREE]int32) {
|
|
lg := params[1]
|
|
gamma1 := 1 << lg
|
|
el := params[4]
|
|
var ki int
|
|
var w, t int32
|
|
var buff [DL_YBYTES]byte
|
|
|
|
for i := 0; i < el; i++ {
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
for j := 0; j < 64; j++ {
|
|
sh.Process(rhod[j])
|
|
}
|
|
ki = k + i
|
|
sh.Process(byte(ki & 0xff))
|
|
sh.Process(byte(ki >> 8))
|
|
sh.Shake(buff[:], DL_YBYTES)
|
|
|
|
var pos [2]int
|
|
pos[0] = 0; pos[1] = 0
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
//take in LG+1 bits at a time
|
|
w = DL_nextword(lg+1, 0, buff[:], pos[:])
|
|
w = int32(gamma1) - w
|
|
t = w >> 31
|
|
y[i][m] = w + (DL_PRIME & t)
|
|
}
|
|
}
|
|
}
|
|
|
|
//CRH(rho,t1)
|
|
func DL_CRH1(params []int, H []byte, rho []byte, t1 [][DL_DEGREE]int16) {
|
|
var pos [2]int
|
|
pos[0] = 0; pos[1] = 0
|
|
ck := params[3]
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
//fmt.Printf("rho[1]= %d\n",rho[1])
|
|
for i := 0; i < 32; i++ {
|
|
sh.Process(rho[i])
|
|
}
|
|
for j := 0; j < ck; j++ {
|
|
//fmt.Printf("X t1[j][0]= %d\n",t1[j][0])
|
|
//fmt.Printf("Y t1[j][1]= %d\n",t1[j][1])
|
|
//fmt.Printf("Z t1[j][2]= %d\n",t1[j][2])
|
|
for i := 0; i < (DL_DEGREE*DL_TD)/8; i++ {
|
|
nxt := DL_nextbyte16(DL_TD, 0, t1[j][:], pos[:])
|
|
/* if i==0 && j==0 {
|
|
//fmt.Printf(" nxt= %d",nxt)
|
|
}
|
|
*/
|
|
sh.Process(nxt)
|
|
}
|
|
}
|
|
sh.Shake(H, 32)
|
|
//fmt.Printf("H[0]= %d\n",H[0])
|
|
}
|
|
|
|
//CRH(tr,M)
|
|
func DL_CRH2(H []byte, tr []byte, mess []byte, mlen int) {
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
for i := 0; i < 32; i++ {
|
|
sh.Process(tr[i])
|
|
}
|
|
for i := 0; i < mlen; i++ {
|
|
sh.Process(mess[i])
|
|
}
|
|
sh.Shake(H, 64)
|
|
}
|
|
|
|
//CRH(K,mu)
|
|
func DL_CRH3(H []byte, bK []byte, mu []byte) {
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
for i := 0; i < 32; i++ {
|
|
sh.Process(bK[i])
|
|
}
|
|
for i := 0; i < 64; i++ {
|
|
sh.Process(mu[i])
|
|
}
|
|
sh.Shake(H, 64)
|
|
}
|
|
|
|
//H(mu,w1)
|
|
func DL_H4(params []int, CT []byte, mu []byte, w1 [][DL_DEGREE]int8) {
|
|
var pos [2]int
|
|
pos[0] = 0; pos[1] = 0
|
|
ck := params[3]
|
|
dv := params[2]
|
|
w1b := 4
|
|
if dv == 88 {
|
|
w1b = 6
|
|
}
|
|
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
for i := 0; i < 64; i++ {
|
|
sh.Process(mu[i])
|
|
}
|
|
for j := 0; j < ck; j++ {
|
|
for i := 0; i < (DL_DEGREE*w1b)/8; i++ {
|
|
sh.Process(DL_nextbyte8(w1b, 0, w1[j][:], pos[:]))
|
|
}
|
|
}
|
|
sh.Shake(CT, 32)
|
|
}
|
|
|
|
func DL_SampleInBall(params []int, ct []byte, c []int32) {
|
|
tau := params[0]
|
|
var signs [8]byte
|
|
var buff [136]byte
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
|
|
for i := 0; i < 32; i++ {
|
|
sh.Process(ct[i])
|
|
}
|
|
sh.Shake(buff[:], 136)
|
|
|
|
for i := 0; i < 8; i++ {
|
|
signs[i] = buff[i]
|
|
}
|
|
|
|
k := 8
|
|
b := 0
|
|
DL_poly_zero(c)
|
|
var sn int = int(signs[0])
|
|
n := 1
|
|
var j int
|
|
|
|
for i := DL_DEGREE - tau; i < DL_DEGREE; i++ {
|
|
for next := true; next; next = j > i {
|
|
j = int(buff[k])
|
|
k++
|
|
}
|
|
c[i] = c[j]
|
|
c[j] = 1 - 2*(int32(sn&1))
|
|
sn >>= 1
|
|
b++
|
|
if b == 8 {
|
|
sn = int(signs[n])
|
|
n++
|
|
b = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
func DL_Power2Round(t []int32, t0 []int16, t1 []int16) {
|
|
var w, d, r int32
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
w = t[m]
|
|
d = 1 << DL_D
|
|
r = (w + d/2 - 1) >> DL_D
|
|
w -= r << DL_D
|
|
t1[m] = int16(r)
|
|
t0[m] = int16(w)
|
|
}
|
|
}
|
|
|
|
// ALPHA = (Q-1)/16 - borrowed from dilithium ref implementation
|
|
func DL_decompose_lo(params []int, a int32) int32 {
|
|
var gamma2 int
|
|
dv := params[2]
|
|
var a0, a1 int32
|
|
a1 = (a + 127) >> 7
|
|
if dv == 32 {
|
|
a1 = (a1*1025 + (1 << 21)) >> 22
|
|
a1 &= 15
|
|
gamma2 = (DL_PRIME - 1) / 32
|
|
} else { //88
|
|
a1 = (a1*11275 + (1 << 23)) >> 24
|
|
a1 ^= ((43 - a1) >> 31) & a1
|
|
gamma2 = (DL_PRIME - 1) / 88
|
|
}
|
|
|
|
a0 = a - a1 * 2 * int32(gamma2)
|
|
a0 -= (((DL_PRIME-1)/2 - a0) >> 31) & DL_PRIME
|
|
a0 += (a0 >> 31) & DL_PRIME
|
|
|
|
return a0
|
|
}
|
|
|
|
// ALPHA = (Q-1)/16
|
|
func DL_decompose_hi(params []int, a int32) int8 {
|
|
dv := params[2]
|
|
var a1 int32 = (a + 127) >> 7
|
|
|
|
if dv == 32 {
|
|
a1 = (a1*1025 + (1 << 21)) >> 22
|
|
a1 &= 15
|
|
} else {
|
|
a1 = (a1*11275 + (1 << 23)) >> 24
|
|
a1 ^= ((43 - a1) >> 31) & a1
|
|
}
|
|
return int8(a1)
|
|
}
|
|
|
|
func DL_lobits(params []int, r0 []int32, r []int32) {
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
r0[m] = DL_decompose_lo(params, r[m])
|
|
}
|
|
}
|
|
|
|
func DL_hibits(params []int, r1 []int8, r []int32) {
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
r1[m] = DL_decompose_hi(params, r[m])
|
|
}
|
|
}
|
|
|
|
// before h initialised to zeros, hptr=0
|
|
// after new hptr returned and h[OMEGA+i]= hptr
|
|
func DL_MakePartialHint(params []int, h []byte, hptr int, z []int32, r []int32) int {
|
|
var a0, a1 int8
|
|
var rz int32
|
|
omega := params[7]
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
a0 = DL_decompose_hi(params, r[m])
|
|
rz = r[m] + z[m]
|
|
rz -= DL_PRIME
|
|
rz = rz + ((rz >> 31) & DL_PRIME)
|
|
a1 = DL_decompose_hi(params, rz)
|
|
if a0 != a1 {
|
|
if hptr >= omega {
|
|
return omega + 1
|
|
}
|
|
h[hptr] = byte(m) & 0xff
|
|
hptr++
|
|
}
|
|
}
|
|
return hptr
|
|
}
|
|
|
|
func DL_UsePartialHint(params []int, r []int8, h []byte, hptr int, i int, w []int32) int {
|
|
dv := int8(params[2])
|
|
omega := params[7]
|
|
md := int8(dv / 2)
|
|
var a0 int32
|
|
var a1 int8
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
a1 = DL_decompose_hi(params, w[m])
|
|
if m == int(h[hptr]) && hptr < int(h[omega+i]) {
|
|
hptr++
|
|
a0 = DL_decompose_lo(params, w[m])
|
|
if a0 <= DL_PRIME/2 {
|
|
a1++
|
|
if a1 >= md {
|
|
a1 -= md
|
|
}
|
|
} else {
|
|
a1--
|
|
if a1 < 0 {
|
|
a1 += md
|
|
}
|
|
}
|
|
}
|
|
r[m] = a1
|
|
}
|
|
return hptr
|
|
}
|
|
|
|
func DL_infinity_norm(w []int32) int32 {
|
|
var az int32
|
|
var n int32
|
|
n = 0
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
az = w[m]
|
|
if az > (DL_PRIME/2) {
|
|
az = DL_PRIME - az
|
|
}
|
|
if az > n {
|
|
n = az
|
|
}
|
|
}
|
|
return n
|
|
}
|
|
|
|
//Dilithium API
|
|
func DL_keypair(params []int, tau []byte, sk []byte, pk []byte) {
|
|
var buff [128]byte
|
|
var rho [32]byte
|
|
var rhod [64]byte
|
|
var bK [32]byte
|
|
var tr [32]byte // 320 bytes
|
|
var Aij [DL_DEGREE]int32 // 1024 bytes
|
|
var w [DL_DEGREE]int32 // work space 1024 bytes
|
|
var r [DL_DEGREE]int32 // work space 1024 bytes total = 12352
|
|
|
|
ck := params[3]
|
|
el := params[4]
|
|
|
|
s1 := make([][DL_DEGREE]int8, el) // 1280 bytes
|
|
s2 := make([][DL_DEGREE]int8, ck) // 1536 bytes
|
|
t0 := make([][DL_DEGREE]int16, ck) // 3072 bytes
|
|
t1 := make([][DL_DEGREE]int16, ck) // 3072 bytes
|
|
|
|
sh := NewSHA3(SHA3_SHAKE256)
|
|
|
|
for i := 0; i < 32; i++ {
|
|
sh.Process(tau[i])
|
|
}
|
|
sh.Shake(buff[:], 128)
|
|
|
|
for i := 0; i < 32; i++ {
|
|
rho[i] = buff[i]
|
|
bK[i] = buff[i+96]
|
|
}
|
|
|
|
for i := 0; i < 64; i++ {
|
|
rhod[i] = buff[32+i]
|
|
}
|
|
//fmt.Printf("rhod[0]= %d\n", rhod[0])
|
|
|
|
for i := 0; i < el; i++ {
|
|
DL_sample_Sn(params, rhod[:], s1[i][:], i)
|
|
}
|
|
//fmt.Printf("s1[0][0]= %d\n",s1[0][0])
|
|
|
|
for i := 0; i < ck; i++ {
|
|
DL_sample_Sn(params, rhod[:], s2[i][:], el+i)
|
|
//fmt.Printf("s2[0][0]= %d\n",s2[0][0])
|
|
DL_poly_zero(r[:])
|
|
for j := 0; j < el; j++ {
|
|
DL_poly_scopy(w[:], s1[j][:])
|
|
DL_ntt(w[:])
|
|
DL_ExpandAij(rho[:], Aij[:], i, j) //This is bottleneck
|
|
DL_poly_mul(w[:], w[:], Aij[:])
|
|
DL_poly_add(r[:], r[:], w[:])
|
|
//DL_poly_soft_reduce(r[:]) // be lazy
|
|
}
|
|
DL_poly_hard_reduce(r[:])
|
|
/*for k:=0; k<DL_DEGREE;k++{
|
|
fmt.Printf(" %d",r[k])
|
|
}*/
|
|
DL_intt(r[:])
|
|
//fmt.Printf("\n1. r[0]= %d\n",r[0])
|
|
//fmt.Printf("1. r[1]= %d\n",r[1])
|
|
//os.exit(0)
|
|
DL_poly_scopy(w[:], s2[i][:])
|
|
DL_poly_pos(w[:])
|
|
DL_poly_add(r[:], r[:], w[:])
|
|
DL_poly_soft_reduce(r[:])
|
|
//fmt.Printf("2. r[0]= %d\n",r[0])
|
|
//fmt.Printf("2. r[1]= %d\n",r[1])
|
|
DL_Power2Round(r[:], t0[i][:], t1[i][:])
|
|
//fmt.Printf("t0[0][0]= %d\n",t0[0][0])
|
|
//fmt.Printf("t0[0][1]= %d\n",t0[0][1])
|
|
//fmt.Printf("t1[0][0]= %d\n",t1[0][0])
|
|
//fmt.Printf("t1[0][1]= %d\n",t1[0][1])
|
|
}
|
|
DL_CRH1(params, tr[:], rho[:], t1)
|
|
//fmt.Printf("tr[0]= %d\n",tr[0])
|
|
//fmt.Printf("rho[0]= %d\n",rho[0])
|
|
DL_pack_pk(params, pk, rho[:], t1)
|
|
DL_pack_sk(params, sk, rho[:], bK[:], tr[:], s1, s2, t0)
|
|
}
|
|
|
|
func DL_signature(params []int, sk []byte, M []byte, sig []byte) int {
|
|
var fk, nh, k int
|
|
var badone bool
|
|
|
|
var rho [32]byte
|
|
var bK [32]byte
|
|
var ct [32]byte
|
|
var tr [32]byte
|
|
var mu [64]byte
|
|
var rhod [64]byte //288 bytes
|
|
var hint [100]byte //61 bytes
|
|
|
|
var c [DL_DEGREE]int32 // 1024 bytes
|
|
var w [DL_DEGREE]int32 // work space 1024 bytes
|
|
var r [DL_DEGREE]int32 // work space 1024 bytes total= 21673 bytes
|
|
//var Aij [DL_DEGREE]int32 //1024 bytes
|
|
|
|
ck := params[3]
|
|
el := params[4]
|
|
|
|
s1 := make([][DL_DEGREE]int8, el) // 1280 bytes
|
|
s2 := make([][DL_DEGREE]int8, ck) // 1536 bytes
|
|
t0 := make([][DL_DEGREE]int16, ck) // 3072 bytes
|
|
y := make([][DL_DEGREE]int32, el) // 5120 bytes
|
|
Ay := make([][DL_DEGREE]int32, ck) // 6144 bytes
|
|
w1 := make([][DL_DEGREE]int8, ck) // 1280 bytes
|
|
|
|
|
|
tau := params[0]
|
|
lg := params[1]
|
|
gamma1 := int32(1 << lg)
|
|
dv := int32(params[2])
|
|
gamma2 := (DL_PRIME - 1) / dv
|
|
eta := params[5]
|
|
beta := int32(tau * eta)
|
|
omega := params[7]
|
|
|
|
DL_unpack_sk(params, rho[:], bK[:], tr[:], s1, s2, t0, sk)
|
|
|
|
//signature
|
|
DL_CRH2(mu[:], tr[:], M, len(M))
|
|
DL_CRH3(rhod[:], bK[:], mu[:])
|
|
for k = 0; ; k++ {
|
|
fk = k * el
|
|
DL_sample_Y(params, fk, rhod[:], y)
|
|
|
|
//fmt.Printf("X y[0][0] = %d y[0][1] = %d\n",y[0][0],y[0][1])
|
|
//NTT y
|
|
for i := 0; i < el; i++ {
|
|
DL_ntt(y[i][:])
|
|
}
|
|
//fmt.Printf("Y y[0][0] = %d y[0][1] = %d\n",y[0][0],y[0][1])
|
|
// Calculate Ay
|
|
for i := 0; i < ck; i++ {
|
|
DL_poly_zero(r[:])
|
|
for j := 0; j < el; j++ {
|
|
//Note : no NTTs in here
|
|
DL_poly_copy(w[:], y[j][:])
|
|
DL_ExpandAij(rho[:], c[:], i, j) // This is bottleneck // re-use c for Aij
|
|
DL_poly_mul(w[:], w[:], c[:])
|
|
DL_poly_add(r[:], r[:], w[:])
|
|
//DL_poly_soft_reduce(r[:]) // be lazy
|
|
}
|
|
DL_poly_hard_reduce(r[:])
|
|
DL_intt(r[:])
|
|
DL_poly_copy(Ay[i][:], r[:])
|
|
// Calculate w1
|
|
DL_hibits(params, w1[i][:], Ay[i][:])
|
|
|
|
}
|
|
|
|
// Calculate c
|
|
DL_H4(params, ct[:], mu[:], w1)
|
|
DL_SampleInBall(params, ct[:], c[:])
|
|
|
|
badone = false
|
|
// Calculate z=y+c.s1
|
|
DL_ntt(c[:])
|
|
for i := 0; i<el; i++ {
|
|
DL_poly_scopy(w[:], s1[i][:])
|
|
DL_ntt(w[:])
|
|
DL_poly_mul(w[:], w[:], c[:])
|
|
DL_nres_it(w[:])
|
|
|
|
DL_poly_add(y[i][:], y[i][:], w[:]) // re-use y for z
|
|
DL_redc_it(y[i][:]) // unNTT y
|
|
DL_intt(y[i][:])
|
|
DL_poly_soft_reduce(y[i][:])
|
|
|
|
if DL_infinity_norm(y[i][:]) >= gamma1-beta { //seems to be always true
|
|
badone = true;
|
|
break;
|
|
}
|
|
}
|
|
if badone {
|
|
continue
|
|
}
|
|
// Calculate Ay=w-c.s2 and r0=DL_lobits(w-c.s2)
|
|
nh = 0
|
|
for i := 0; i < omega+ck; i++ {
|
|
hint[i] = 0
|
|
}
|
|
for i := 0; i < ck; i++ {
|
|
DL_poly_scopy(w[:], s2[i][:])
|
|
DL_ntt(w[:])
|
|
DL_poly_mul(w[:], w[:], c[:])
|
|
|
|
DL_intt(w[:])
|
|
DL_poly_sub(Ay[i][:], Ay[i][:], w[:])
|
|
DL_poly_soft_reduce(Ay[i][:]) // Ay=w-cs2
|
|
DL_lobits(params, w[:], Ay[i][:]) // r0
|
|
if DL_infinity_norm(w[:]) >= gamma2-beta {
|
|
badone = true
|
|
break
|
|
}
|
|
|
|
DL_poly_mcopy(w[:], t0[i][:])
|
|
DL_ntt(w[:])
|
|
DL_poly_mul(w[:], w[:], c[:])
|
|
|
|
DL_intt(w[:])
|
|
DL_poly_negate(r[:], w[:]) // -ct0
|
|
if DL_infinity_norm(r[:]) >= gamma2 {
|
|
badone = true
|
|
break
|
|
}
|
|
DL_poly_sub(Ay[i][:], Ay[i][:], r[:])
|
|
DL_poly_soft_reduce(Ay[i][:])
|
|
|
|
nh = DL_MakePartialHint(params, hint[:], nh, r[:], Ay[i][:])
|
|
if nh > omega {
|
|
badone = true
|
|
break
|
|
}
|
|
hint[omega+i] = byte(nh)
|
|
}
|
|
if badone {
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
//fmt.Printf("y[0][0] = %d y[0][1] = %d\n",y[0][0],y[0][1])
|
|
DL_pack_sig(params, sig, y[:], ct[:], hint[:])
|
|
return k + 1
|
|
}
|
|
|
|
func DL_verify(params []int, pk []byte, M []byte, sig []byte) bool {
|
|
var rho [32]byte
|
|
var mu [64]byte
|
|
var ct [32]byte
|
|
var cct [32]byte
|
|
var tr [32]byte // 192 bytes
|
|
var hint [100]byte
|
|
|
|
var Aij [DL_DEGREE]int32 // 1024 bytes
|
|
var c [DL_DEGREE]int32 // 1024 bytes
|
|
var w [DL_DEGREE]int32 // work space // 1024 bytes
|
|
var r [DL_DEGREE]int32 // work space // 1024 bytes total=14077 bytes
|
|
|
|
ck := params[3]
|
|
el := params[4]
|
|
|
|
z := make([][DL_DEGREE]int32, el)
|
|
t1 := make([][DL_DEGREE]int16, ck)
|
|
w1d := make([][DL_DEGREE]int8, ck)
|
|
|
|
tau := params[0]
|
|
lg := params[1]
|
|
gamma1 := int32(1<<lg)
|
|
eta := params[5]
|
|
beta := int32(tau*eta)
|
|
omega := params[7]
|
|
|
|
// unpack public key and signature
|
|
DL_unpack_pk(params, rho[:], t1, pk)
|
|
DL_unpack_sig(params, z, ct[:], hint[:], sig)
|
|
|
|
for i := 0; i < el; i++ {
|
|
if DL_infinity_norm(z[i][:]) >= gamma1-beta {
|
|
return false
|
|
}
|
|
DL_ntt(z[i][:]) // convert to ntt form
|
|
}
|
|
|
|
DL_CRH1(params, tr[:], rho[:], t1)
|
|
DL_CRH2(mu[:], tr[:], M, len(M))
|
|
DL_SampleInBall(params, ct[:], c[:])
|
|
DL_ntt(c[:])
|
|
|
|
// Calculate Az
|
|
hints := 0
|
|
for i := 0; i < ck; i++ {
|
|
DL_poly_zero(r[:])
|
|
for j := 0; j < el; j++ {
|
|
//Note : no NTTs in here
|
|
DL_poly_copy(w[:], z[j][:])
|
|
DL_ExpandAij(rho[:], Aij[:], i, j)
|
|
DL_poly_mul(w[:], w[:], Aij[:])
|
|
DL_poly_add(r[:], r[:], w[:])
|
|
//DL_poly_soft_reduce(r[:]) // be lazy
|
|
}
|
|
DL_poly_hard_reduce(r[:])
|
|
|
|
// Calculate Az-ct1.s^d
|
|
for m := 0; m < DL_DEGREE; m++ {
|
|
w[m] = int32(t1[i][m])<<DL_D
|
|
}
|
|
DL_ntt(w[:])
|
|
DL_poly_mul(w[:], w[:], c[:])
|
|
DL_poly_sub(r[:], r[:], w[:])
|
|
DL_intt(r[:])
|
|
|
|
hints = DL_UsePartialHint(params, w1d[i][:], hint[:], hints, i, r[:])
|
|
if hints > omega {
|
|
return false
|
|
}
|
|
}
|
|
|
|
DL_H4(params, cct[:], mu[:], w1d)
|
|
|
|
for i := 0; i < 32; i++ {
|
|
if ct[i] != cct[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func DL_keypair_2(tau []byte, sk []byte, pk []byte) {
|
|
DL_keypair(DL_PARAMS_2[:], tau, sk, pk)
|
|
}
|
|
|
|
func DL_signature_2(sk []byte, M []byte, sig []byte) int {
|
|
return DL_signature(DL_PARAMS_2[:], sk, M, sig)
|
|
}
|
|
|
|
func DL_verify_2(pk []byte, M []byte, sig []byte) bool {
|
|
return DL_verify(DL_PARAMS_2[:], pk, M, sig)
|
|
}
|
|
|
|
func DL_keypair_3(tau []byte, sk []byte, pk []byte) {
|
|
DL_keypair(DL_PARAMS_3[:], tau, sk, pk)
|
|
}
|
|
|
|
func DL_signature_3(sk []byte, M []byte, sig []byte) int {
|
|
return DL_signature(DL_PARAMS_3[:], sk, M, sig)
|
|
}
|
|
|
|
func DL_verify_3(pk []byte, M []byte, sig []byte) bool {
|
|
return DL_verify(DL_PARAMS_3[:], pk, M, sig)
|
|
}
|
|
|
|
func DL_keypair_5(tau []byte, sk []byte, pk []byte) {
|
|
DL_keypair(DL_PARAMS_5[:], tau, sk, pk)
|
|
}
|
|
|
|
func DL_signature_5(sk []byte, M []byte, sig []byte) int {
|
|
return DL_signature(DL_PARAMS_5[:], sk, M, sig)
|
|
}
|
|
|
|
func DL_verify_5(pk []byte, M []byte, sig []byte) bool {
|
|
return DL_verify(DL_PARAMS_5[:], pk, M, sig)
|
|
}
|