ntru_test.go raw
1 package composite
2
3 import (
4 "crypto/rand"
5 "testing"
6
7 "git.smesh.lol/gnarl-hamadryad/crypto/ring"
8 )
9
10 func TestCompositeRingInversion(t *testing.T) {
11 p := DefaultParam(); rp := p.Ring
12 gs := ring.NewGaussianSamplerFrom(p.Sigma, rand.Reader)
13 for trial := 0; trial < 5; trial++ {
14 f := gs.SamplePoly(rp)
15 fInv := polyInverseModQ(f, rp)
16 if fInv == nil { continue }
17 prod := ring.Mul(f, fInv)
18 if prod.Coeffs[0] != 1 { t.Fatalf("f*f^{-1}[0]=%d, want 1", prod.Coeffs[0]) }
19 t.Logf("ring inversion at n=%d q=%d: OK", rp.N, rp.Q)
20 return
21 }
22 t.Skip("all f non-invertible")
23 }
24
25 func TestCompositeH(t *testing.T) {
26 p := DefaultParam(); rp := p.Ring
27 gs := ring.NewGaussianSamplerFrom(p.Sigma, rand.Reader)
28 for trial := 0; trial < 5; trial++ {
29 f := gs.SamplePoly(rp); g := gs.SamplePoly(rp)
30 fInv := polyInverseModQ(f, rp)
31 if fInv == nil { continue }
32 h := ring.Mul(g, fInv)
33 hf := ring.Mul(h, f)
34 if !ring.Equal(hf, g) { t.Fatalf("h*f != g") }
35 t.Logf("h = g*f^{-1} at n=%d: OK", rp.N)
36 return
37 }
38 t.Skip("all f non-invertible")
39 }
40
41 func TestCompositeKeyGenH(t *testing.T) {
42 p := DefaultParam()
43 pk, sk := NTRUKeyGen(p)
44 if ring.Norm(pk.H) == 0 { t.Fatal("h is zero") }
45 _ = sk
46 t.Logf("public key generated: n=%d q=%d, h norm=%d, (F,G) blocked", p.Ring.N, p.Ring.Q, ring.Norm(pk.H))
47 }
48
49 func TestCompositeParams(t *testing.T) {
50 p := DefaultParam()
51 t.Logf("Composite: n=%d q=%d", p.Ring.N, p.Ring.Q)
52 t.Logf(" ring inversion via matrix solve: verified")
53 t.Logf(" h = g*f^{-1}: verified")
54 t.Logf(" NTRU equation (F,G): blocked")
55 t.Logf(" -> requires integer INTT (16x16 matrix with exact rational entries)")
56 t.Logf(" -> or ring extended GCD (Euclidean in Z[x]/(x^n+1))")
57 t.Logf("")
58 t.Logf("Gnarlring: n=27 q=271 — working via LLL at dim 54 (coefficient space)")
59 t.Logf("Falcon: n=512 q=12289 — production target (~128-bit SIS)")
60 }
61