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 112 113 114 115 116 117 118 119 120 121
|
// Copyright 2025 Google LLC
//
// 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.
package mldsa
import (
"fmt"
"testing"
)
func fmtPoly(p *poly) string {
res := ""
for i := range p {
res += fmt.Sprintf("%v, ", p[i])
}
return res
}
func TestSampleInBall(t *testing.T) {
pars := []struct {
name string
par *params
rho []byte
exp [degree]uint32
}{
{"MLDSA44", MLDSA44, []byte("test44"), [degree]uint32{0, 0, 0, 8380416, 0, 8380416, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 8380416, 0, 8380416, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 8380416, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 8380416, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 1, 1, 0, 0, 0, 0, 8380416, 0, 0, 0, 8380416, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1}},
{"MLDSA65", MLDSA65, []byte("test65"), [degree]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8380416, 1, 0, 0, 0, 0, 0, 0, 1, 0, 8380416, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 8380416, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 8380416, 1, 0, 0, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 8380416, 0, 0, 1, 8380416, 0, 0, 1, 0, 0, 0, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 1, 0, 0, 0, 1, 0, 0, 1, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 8380416, 0, 8380416, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 8380416, 0, 8380416, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 8380416, 0, 0, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 1, 0, 8380416, 8380416, 0, 0, 0, 0, 0, 0, 0}},
{"MLDSA87", MLDSA87, []byte("test87"), [degree]uint32{0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 8380416, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 1, 0, 0, 0, 8380416, 0, 0, 8380416, 0, 1, 8380416, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 8380416, 8380416, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 8380416, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 8380416, 0, 0, 1, 8380416, 8380416, 0, 1, 0, 0, 0, 0, 0, 8380416, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 8380416, 0, 0, 0, 8380416, 0, 1, 8380416, 0, 0, 0, 8380416, 0, 0, 8380416, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 0, 0, 8380416, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 8380416, 0, 8380416, 8380416, 8380416, 0, 0, 8380416, 0, 0, 0, 8380416, 0, 0, 0, 8380416, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 8380416, 0, 8380416, 0, 0, 0}},
}
for _, par := range pars {
got := par.par.sampleInBall(par.rho)
exp := &poly{}
for i := range par.exp {
exp[i] = rZq(par.exp[i])
}
if !comparePoly(exp, got) {
t.Errorf("sampleInBall(%v) = %v, want %v", par.name, got, exp)
}
}
}
func TestRejectNTTPoly(t *testing.T) {
var rho [32 + 2]byte
copy(rho[:], []byte("test"))
got := rejectNTTPoly(rho)
expCoeff := [degree]uint32{3578166, 972121, 1648259, 7677015, 7376256, 5757783, 3101446, 451067, 6059670, 5905884, 4247480, 6679920, 5555081, 5144979, 7075978, 7103507, 7757395, 6415702, 7912360, 1786375, 5021428, 4285621, 2300099, 517782, 3159847, 6432777, 7874432, 4637670, 5116597, 4416746, 131575, 1295247, 2024915, 3530654, 4685938, 6426766, 3252315, 5534711, 501983, 2745133, 4631370, 1720508, 4803276, 2665408, 2601674, 2050001, 881099, 7065587, 7667596, 5564556, 4908268, 4430756, 7113411, 1448161, 4673027, 3025369, 7260498, 3754333, 6189687, 4788810, 7027191, 1291127, 1943917, 6811679, 7569460, 8295707, 3360283, 4419822, 7033727, 3984496, 7161488, 5493370, 7503985, 2532912, 4383716, 6164164, 2937280, 7772634, 2929950, 1152540, 5435522, 785917, 6584256, 1003532, 1955532, 4540370, 762206, 2240473, 5906072, 7440006, 2273961, 5730641, 6727709, 6284746, 7262289, 1880606, 3980372, 951759, 2597630, 949515, 4907846, 6279803, 4881171, 4453505, 302758, 7778031, 2113839, 2770685, 3888225, 548843, 2304201, 7015316, 7198775, 7207486, 7976493, 563117, 6072801, 6116272, 5051986, 7371985, 6943341, 6891047, 1550530, 1278600, 580067, 3252388, 6847311, 3212057, 7750900, 5939169, 726280, 3417354, 4769397, 610311, 7666886, 4395572, 7715999, 317514, 5090616, 4857095, 6960708, 4305385, 3228894, 5313136, 1892104, 6569383, 1352019, 2927514, 7064092, 6823878, 5890322, 1130244, 1908695, 6759827, 783842, 1112633, 4043807, 3011861, 938725, 3174967, 4748831, 4114401, 6702457, 6276820, 6256526, 2706103, 8000821, 8329692, 480724, 3945356, 5727318, 2441670, 6402483, 6010899, 8241871, 5253031, 7365886, 6630122, 3797332, 1014035, 1374475, 8013694, 1524131, 2406576, 7355560, 1429746, 1271739, 3225058, 307267, 5313838, 5142749, 4169359, 4966778, 4050707, 2500257, 2977209, 1812783, 405033, 5144724, 3699340, 870062, 7673186, 1464149, 422268, 5846554, 4425801, 3137547, 6860986, 7455071, 5659639, 5100439, 2902352, 2695051, 8137526, 6208043, 1693021, 3413236, 4176881, 4449190, 3916118, 1989094, 1135723, 2183769, 6641817, 3015521, 7356074, 2798296, 2439037, 1906625, 6986208, 1916547, 6652074, 5483432, 6816451, 7740644, 4436736, 181633, 8352909, 7657371, 1675250, 837485, 2604507, 5158513, 2613871, 5316527, 7655366, 5551366, 5105921, 6399947, 8281582, 5189356, 59379, 828119, 6331152, 3695617, 4629496}
eq := true
for i := range expCoeff {
if got[i] != rZq(expCoeff[i]) {
eq = false
}
}
if !eq {
t.Errorf("rejectNTTPoly(...) = %v, want %v", got, expCoeff)
}
}
func TestCoeffFromHalfByte(t *testing.T) {
pars := []struct {
name string
par *params
}{
{"MLDSA44", MLDSA44},
{"MLDSA65", MLDSA65},
{"MLDSA87", MLDSA87},
}
for _, par := range pars {
for i := 0; i <= 0xF; i++ {
b := byte(i)
exp := rZq(0)
ok := false
if par.par.eta == 2 && b < 15 {
exp = rZq(2).sub(rZq(b % 5))
ok = true
} else if par.par.eta == 4 && b < 9 {
exp = rZq(4).sub(rZq(b))
ok = true
}
got, gotOK := par.par.coeffFromHalfByte(b)
if got != exp || gotOK != ok {
t.Errorf("coeffFromHalfByte(%v) = %v, %v, want %v, %v", b, got, gotOK, exp, ok)
}
}
}
}
func TestRejectBoundedPoly(t *testing.T) {
pars := []struct {
name string
par *params
rho []byte
exp [degree]uint32
}{
{"MLDSA44", MLDSA44, []byte("test44"), [degree]uint32{8380416, 0, 2, 1, 8380416, 1, 8380416, 1, 2, 1, 2, 0, 0, 8380415, 1, 8380416, 0, 2, 8380415, 8380416, 1, 8380415, 2, 8380416, 0, 8380415, 8380416, 2, 2, 8380415, 2, 0, 8380415, 8380416, 0, 8380416, 2, 1, 8380416, 1, 0, 8380415, 2, 2, 0, 1, 8380415, 8380415, 8380416, 0, 0, 8380415, 2, 1, 1, 8380416, 0, 8380415, 1, 1, 8380415, 0, 2, 1, 2, 1, 1, 2, 2, 2, 1, 0, 2, 1, 0, 8380416, 8380415, 8380416, 8380416, 1, 1, 8380415, 1, 2, 8380416, 2, 2, 2, 2, 0, 8380415, 1, 8380416, 1, 2, 2, 1, 8380416, 8380416, 8380415, 8380415, 8380415, 8380415, 0, 8380415, 8380416, 0, 1, 8380416, 1, 0, 1, 8380415, 2, 0, 1, 0, 8380416, 2, 2, 8380415, 0, 2, 0, 2, 8380415, 8380416, 8380415, 8380415, 2, 8380416, 8380416, 1, 1, 8380416, 2, 2, 8380416, 8380415, 1, 8380415, 8380415, 8380415, 2, 1, 0, 8380415, 8380416, 0, 8380415, 8380416, 2, 8380415, 1, 2, 8380415, 2, 8380415, 2, 1, 2, 8380416, 8380416, 8380416, 1, 8380416, 0, 8380415, 8380415, 2, 1, 8380415, 2, 0, 0, 2, 2, 8380415, 1, 0, 1, 8380415, 8380416, 1, 8380416, 8380415, 2, 1, 1, 0, 0, 0, 2, 2, 0, 8380416, 1, 2, 2, 8380416, 0, 8380415, 0, 2, 8380416, 1, 2, 8380415, 8380415, 8380416, 8380415, 2, 0, 8380415, 0, 1, 8380416, 8380416, 8380415, 8380416, 1, 8380415, 0, 8380416, 2, 8380416, 8380415, 2, 2, 1, 8380416, 2, 2, 8380416, 0, 0, 2, 2, 8380416, 1, 8380416, 0, 8380416, 1, 2, 8380416, 0, 8380416, 2, 2, 1, 1, 8380415, 8380416, 8380416, 8380415}},
{"MLDSA65", MLDSA65, []byte("test65"), [degree]uint32{8380415, 4, 8380416, 8380414, 3, 8380416, 8380416, 8380416, 8380414, 1, 8380413, 2, 8380414, 8380414, 8380413, 8380416, 8380415, 8380415, 4, 2, 1, 2, 8380414, 8380415, 8380414, 8380413, 4, 0, 4, 3, 1, 8380414, 8380415, 8380415, 8380415, 0, 8380414, 4, 1, 2, 3, 1, 8380414, 3, 8380415, 2, 4, 8380413, 8380415, 8380416, 8380415, 8380414, 8380413, 4, 8380416, 8380413, 8380414, 2, 8380414, 1, 8380415, 3, 4, 2, 8380416, 4, 8380416, 2, 3, 8380414, 0, 8380414, 4, 8380416, 8380414, 8380415, 0, 1, 0, 0, 8380414, 4, 8380413, 1, 0, 4, 4, 2, 4, 8380415, 0, 1, 0, 8380414, 2, 0, 2, 4, 0, 1, 3, 1, 8380413, 1, 3, 4, 0, 4, 8380413, 8380416, 2, 4, 2, 8380414, 8380414, 3, 0, 2, 8380415, 2, 8380416, 3, 2, 8380414, 0, 0, 8380416, 2, 4, 8380413, 4, 8380415, 3, 4, 3, 8380413, 8380414, 8380414, 0, 8380414, 8380413, 2, 1, 1, 4, 1, 0, 8380416, 0, 0, 4, 1, 1, 4, 8380413, 1, 8380414, 8380414, 2, 1, 4, 4, 4, 0, 8380414, 1, 1, 8380414, 2, 0, 2, 8380415, 8380415, 2, 3, 0, 8380416, 3, 8380415, 8380414, 8380414, 8380413, 8380414, 8380415, 1, 8380415, 8380413, 8380414, 2, 8380416, 3, 8380416, 8380415, 4, 1, 3, 0, 8380413, 8380415, 0, 2, 0, 4, 2, 8380415, 0, 2, 8380415, 8380416, 2, 8380413, 8380416, 4, 1, 8380415, 8380413, 2, 4, 8380416, 8380415, 8380415, 1, 8380414, 1, 8380413, 3, 8380415, 8380415, 4, 0, 4, 0, 0, 0, 3, 0, 0, 0, 4, 8380413, 1, 8380415, 0, 3, 1, 1, 1, 8380416, 3, 8380413, 1, 4, 1, 4, 8380415, 4}},
{"MLDSA87", MLDSA87, []byte("test87"), [degree]uint32{8380416, 1, 0, 0, 8380416, 8380416, 0, 8380416, 8380416, 8380415, 8380416, 1, 0, 0, 2, 8380415, 0, 8380416, 2, 8380415, 2, 1, 8380415, 8380416, 2, 1, 8380415, 8380416, 8380416, 8380416, 0, 8380415, 8380416, 2, 0, 1, 8380415, 1, 0, 2, 0, 1, 2, 8380415, 2, 8380415, 8380415, 2, 0, 8380415, 8380416, 8380415, 1, 8380416, 1, 8380416, 8380416, 2, 0, 1, 8380416, 1, 0, 1, 8380416, 1, 0, 8380415, 8380416, 8380416, 1, 8380416, 0, 8380416, 8380415, 2, 1, 2, 2, 8380416, 2, 8380415, 2, 2, 2, 2, 0, 1, 2, 0, 0, 1, 1, 8380415, 8380416, 2, 0, 8380416, 0, 2, 0, 8380416, 8380415, 1, 0, 8380415, 1, 1, 0, 2, 0, 0, 1, 0, 8380416, 0, 8380416, 8380416, 2, 1, 1, 8380415, 8380416, 2, 2, 2, 1, 8380415, 8380415, 2, 8380415, 8380416, 2, 8380416, 1, 8380415, 2, 8380415, 2, 0, 8380415, 1, 8380415, 8380415, 8380416, 2, 1, 1, 8380415, 8380416, 8380415, 2, 0, 2, 8380416, 1, 0, 8380415, 2, 8380416, 8380415, 1, 1, 1, 2, 1, 0, 2, 1, 0, 8380416, 8380415, 2, 0, 2, 2, 8380415, 1, 2, 0, 8380416, 8380415, 2, 2, 8380416, 1, 0, 1, 2, 2, 2, 0, 1, 1, 1, 8380416, 8380415, 0, 8380415, 1, 2, 0, 0, 8380415, 8380415, 2, 2, 2, 8380415, 0, 0, 2, 8380415, 2, 2, 2, 2, 0, 1, 1, 8380415, 1, 1, 0, 2, 8380415, 8380416, 0, 8380416, 1, 0, 2, 1, 1, 0, 8380416, 0, 0, 0, 0, 0, 8380416, 8380415, 1, 0, 1, 0, 2, 8380416, 8380415, 0, 8380416, 0, 8380415, 1, 8380415}},
}
for _, par := range pars {
var rho [64 + 2]byte
copy(rho[:], par.rho[:])
got := par.par.rejectBoundedPoly(rho)
exp := &poly{}
for i := range par.exp {
exp[i] = rZq(par.exp[i])
}
if !comparePoly(exp, got) {
t.Errorf("rejectBoundedPoly(%v) = %v, want %v", par.name, got, exp)
}
}
}
|