github.com/cloudflare/circl@v1.5.0/sign/dilithium/kat_test.go (about)

     1  package dilithium
     2  
     3  // Code to generate the NIST "PQCsignKAT" test vectors.
     4  // See PQCsignKAT_sign.c and randombytes.c in the reference implementation.
     5  
     6  import (
     7  	"crypto/sha256"
     8  	"fmt"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/cloudflare/circl/internal/nist"
    13  	"github.com/cloudflare/circl/sign/schemes"
    14  )
    15  
    16  func TestPQCgenKATSign(t *testing.T) {
    17  	for _, tc := range []struct {
    18  		name string
    19  		want string
    20  	}{
    21  		// Generated from reference implementation commit 61b51a71701b8ae9f546a1e5,
    22  		// which can be found at https://github.com/pq-crystals/dilithium
    23  		{"Dilithium2", "38ed991c5ca11e39ab23945ca37af89e059d16c5474bf8ba96b15cb4e948af2a"},
    24  		{"Dilithium3", "8196b32212753f525346201ffec1c7a0a852596fa0b57bd4e2746231dab44d55"},
    25  		{"Dilithium5", "7ded97a6e6c809b43b54c248171d7504fa6a0cab651bf288bb00034782667481"},
    26  
    27  		// Generated from reference implementation commit cbcd8753a43402885c90343c
    28  		// which can be found at https://github.com/pq-crystals/dilithium
    29  		// with the DILITHIUM_RANDOMIZED_SIGNING macro unset in ref/config.h
    30  		// to disable randomized signing.
    31  		{"ML-DSA-44", "14f92c48abc0d63ea263cce3c83183c8360c6ede7cbd5b65bd7c6f31e38f0ea5"},
    32  		{"ML-DSA-65", "595a8eff6988159c94eb5398294458c5d27d21c994fb64cadbee339173abcf63"},
    33  		{"ML-DSA-87", "35e2ce3d88b3311517bf8d41aa2cd24aa0fbda2bb8052ca8af4ad8d7c7344074"},
    34  	} {
    35  		t.Run(tc.name, func(t *testing.T) {
    36  			mode := schemes.ByName(tc.name)
    37  			if mode == nil {
    38  				t.Fatal()
    39  			}
    40  
    41  			var seed [48]byte
    42  			var eseed [32]byte
    43  			for i := 0; i < 48; i++ {
    44  				seed[i] = byte(i)
    45  			}
    46  			f := sha256.New()
    47  			g := nist.NewDRBG(&seed)
    48  			nameInKat := tc.name
    49  			if !strings.HasPrefix(tc.name, "Dilithium") {
    50  				switch tc.name {
    51  				case "ML-DSA-44":
    52  					nameInKat = "Dilithium2"
    53  				case "ML-DSA-65":
    54  					nameInKat = "Dilithium3"
    55  				case "ML-DSA-87":
    56  					nameInKat = "Dilithium5"
    57  				}
    58  			}
    59  			fmt.Fprintf(f, "# %s\n\n", nameInKat)
    60  			for i := 0; i < 100; i++ {
    61  				mlen := 33 * (i + 1)
    62  				g.Fill(seed[:])
    63  				msg := make([]byte, mlen)
    64  				g.Fill(msg[:])
    65  
    66  				fmt.Fprintf(f, "count = %d\n", i)
    67  				fmt.Fprintf(f, "seed = %X\n", seed)
    68  				fmt.Fprintf(f, "mlen = %d\n", mlen)
    69  				fmt.Fprintf(f, "msg = %X\n", msg)
    70  
    71  				g2 := nist.NewDRBG(&seed)
    72  				g2.Fill(eseed[:])
    73  				pk, sk := mode.DeriveKey(eseed[:])
    74  
    75  				ppk, err := pk.MarshalBinary()
    76  				if err != nil {
    77  					t.Fatal(err)
    78  				}
    79  				psk, err := sk.MarshalBinary()
    80  				if err != nil {
    81  					t.Fatal(err)
    82  				}
    83  
    84  				fmt.Fprintf(f, "pk = %X\n", ppk)
    85  				fmt.Fprintf(f, "sk = %X\n", psk)
    86  				fmt.Fprintf(f, "smlen = %d\n", mlen+mode.SignatureSize())
    87  
    88  				sig := mode.Sign(sk, msg[:], nil)
    89  
    90  				fmt.Fprintf(f, "sm = %X%X\n\n", sig, msg)
    91  
    92  				if !mode.Verify(pk, msg[:], sig, nil) {
    93  					t.Fatal()
    94  				}
    95  			}
    96  			if fmt.Sprintf("%x", f.Sum(nil)) != tc.want {
    97  				t.Fatal()
    98  			}
    99  		})
   100  	}
   101  }