Skip to content

Commit

Permalink
Dilithium: update to v3.1
Browse files Browse the repository at this point in the history
This updates Dilithium to v3.1 as described in

  https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf

Some AVX2 optimisations have not yet been upgraded.

Change the hybrid schemes "eddilithium" accordingly.
  • Loading branch information
bwesterb authored and armfazh committed Sep 21, 2021
1 parent 3543c1a commit 5d1f07e
Show file tree
Hide file tree
Showing 144 changed files with 5,196 additions and 11,487 deletions.
21 changes: 7 additions & 14 deletions sign/dilithium/dilithium.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//go:generate go run gen.go

// dilithium implements the CRYSTALS-Dilithium signature schemes
// as submitted to round2 of the NIST PQC competition and described in
// as submitted to round3 of the NIST PQC competition and described in
//
// https://pq-crystals.org/dilithium/data/dilithium-specification-round2.pdf
// https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf
//
// Each of the eight different modes of Dilithium is implemented by a
// subpackage. For instance, Dilithium III (the recommended mode)
// subpackage. For instance, Dilithium2 (the recommended mode)
// can be found in
//
// github.com/cloudflare/circl/sign/dilithium/mode3
// github.com/cloudflare/circl/sign/dilithium/mode2
//
// If your choice for mode is fixed compile-time, use the subpackages.
// This package provides a convenient wrapper around all of the subpackages
Expand All @@ -18,11 +18,11 @@
// The authors of Dilithium recommend to combine it with a "pre-quantum"
// signature scheme. The packages
//
// github.com/cloudflare/circl/sign/eddilithium2
// github.com/cloudflare/circl/sign/eddilithium3
// github.com/cloudflare/circl/sign/eddilithium4
//
// implement such hybrids of Dilithium3 with Ed25519 respectively and
// Dilithium4 with Ed448. These packages are a drop in replacements for the
// implement such hybrids of Dilithium2 with Ed25519 respectively and
// Dilithium3 with Ed448. These packages are a drop in replacements for the
// mode subpackages of this package.
package dilithium

Expand Down Expand Up @@ -61,13 +61,6 @@ type Mode interface {
// Panics if len(seed) != SeedSize()
NewKeyFromSeed(seed []byte) (PublicKey, PrivateKey)

// NewKeyFromExpandedSeed derives a public/private key pair using the
// given expanded seed.
//
// Use NewKeyFromSeed instead of this function. This function is only exposed
// to generate the NIST KAT test vectors.
NewKeyFromExpandedSeed(seed *[96]byte) (PublicKey, PrivateKey)

// Sign signs the given message and returns the signature.
// It will panic if sk has not been generated for this mode.
Sign(sk PrivateKey, msg []byte) []byte
Expand Down
72 changes: 36 additions & 36 deletions sign/dilithium/dilithium_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,42 +15,42 @@ func hexHash(in []byte) string {
return hex.EncodeToString(ret[:])
}

func testNewKeyFromSeed(t *testing.T, name, esk, epk string) {
mode := ModeByName(name)
if mode == nil {
t.Fatal()
}
var seed [96]byte
h := sha3.NewShake128()
_, _ = h.Write(make([]byte, mode.SeedSize()))
_, _ = h.Read(seed[:])
pk, sk := mode.NewKeyFromExpandedSeed(&seed)
pkh := hexHash(pk.Bytes())
skh := hexHash(sk.Bytes())
if pkh != epk {
t.Fatalf("%s expected pk %s, got %s", name, epk, pkh)
}
if skh != esk {
t.Fatalf("%s expected pk %s, got %s", name, esk, skh)
}
}

func TestNewKeyFromSeed(t *testing.T) {
// Test vectors generated from reference implementation
testNewKeyFromSeed(t, "Dilithium1",
"af470e12a57d00c04c4a2b5998f41c71", "83616951b98312a97ea10e12b7b69675")
testNewKeyFromSeed(t, "Dilithium2",
"48dec3d688330dfc68f9bf4277fb92e1", "38e7339d00e64348cb2f965ecf9ee38b")
testNewKeyFromSeed(t, "Dilithium3",
"a44fcf1f43d124865c63cbf381a3b7eb", "b725d31fb709664f8587e2fb6a60fe80")
testNewKeyFromSeed(t, "Dilithium4",
"e054319bbabd2e156c56e8ee923c2a8e", "e7997fc71a6796056d4633a40769c495")
testNewKeyFromSeed(t, "Dilithium1-AES",
"be55853ce1d2c1113fc96f1295928789", "7782ac146d9e636221329cfe64647112")
testNewKeyFromSeed(t, "Dilithium2-AES",
"2abfd0d294ce1b2bab5b860482c4bbc1", "23c4e9516662394e88e559cf2874d7a4")
testNewKeyFromSeed(t, "Dilithium3-AES",
"ba72ed309182aa509e595013b3ad9089", "887baaf3a98d0aa6b95c8c1a6867e609")
testNewKeyFromSeed(t, "Dilithium4-AES",
"7c1c8b5df63fd096901da43c00fa71e8", "f7f850c1d8ff82c868ab2f188ac624b3")
for _, tc := range []struct {
name string
esk string
epk string
}{
{"Dilithium2", "afe2e91f5f5899354230744c18410498",
"7522162619f3329b5312322d3ee45b87"},
{"Dilithium3", "8ad3142e08b718b33f7c2668cd9d053c",
"3562fc184dce1a10aad099051705b5d3"},
{"Dilithium5", "3956d812a7961af6e5dad16af15c736c",
"665388291aa01e12e7f94bdc7769db18"},
{"Dilithium2-AES", "8466a752b0a09e63e42f66d3174a6471",
"c3f8e705a0d8dfd489b98b205670f393"},
{"Dilithium3-AES", "2bb713ba7cb15f3ebf05c4c1fbb1b03c",
"eb2bd8d98630835a3b18594ac436368b"},
{"Dilithium5-AES", "a613a08b564ee8717ba4f5ccfddc2693",
"2f541bf6fedd12854d06a6b80090932a"},
} {
t.Run(tc.name, func(t *testing.T) {
mode := ModeByName(tc.name)
if mode == nil {
t.Fatal()
}
var seed [32]byte
pk, sk := mode.NewKeyFromSeed(seed[:])

pkh := hexHash(pk.Bytes())
skh := hexHash(sk.Bytes())
if pkh != tc.epk {
t.Fatalf("%s expected pk %s, got %s", tc.name, tc.epk, pkh)
}
if skh != tc.esk {
t.Fatalf("%s expected pk %s, got %s", tc.name, tc.esk, skh)
}
})
}
}
2 changes: 1 addition & 1 deletion sign/dilithium/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ func Example() {
fmt.Printf("O.K.")

// Output:
// Supported modes: [Dilithium1 Dilithium1-AES Dilithium2 Dilithium2-AES Dilithium3 Dilithium3-AES Dilithium4 Dilithium4-AES]
// Supported modes: [Dilithium2 Dilithium2-AES Dilithium3 Dilithium3-AES Dilithium5 Dilithium5-AES]
// O.K.
}
180 changes: 75 additions & 105 deletions sign/dilithium/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@ import (
"path"
"strings"
"text/template"

"github.com/cloudflare/circl/sign/dilithium/internal/common/params"
)

type Mode struct {
Name string
UseAES bool
PublicKeySize int
PrivateKeySize int
SignatureSize int
K int
L int
Eta int
DoubleEtaBits int
Beta int
Omega int
Name string
UseAES bool
K int
L int
Eta int
DoubleEtaBits int
Omega int
Tau int
Gamma1Bits int
Gamma2 int
}

func (m Mode) Pkg() string {
Expand All @@ -43,106 +44,74 @@ func (m Mode) Mode() string {
var (
Modes = []Mode{
{
Name: "Dilithium1",
UseAES: false,
PublicKeySize: 896,
PrivateKeySize: 2096,
SignatureSize: 1387,
K: 3,
L: 2,
Eta: 7,
DoubleEtaBits: 4,
Beta: 375,
Omega: 64,
},
{
Name: "Dilithium1-AES",
UseAES: true,
PublicKeySize: 896,
PrivateKeySize: 2096,
SignatureSize: 1387,
K: 3,
L: 2,
Eta: 7,
DoubleEtaBits: 4,
Beta: 375,
Omega: 64,
},
{
Name: "Dilithium2",
UseAES: false,
PublicKeySize: 1184,
PrivateKeySize: 2800,
SignatureSize: 2044,
K: 4,
L: 3,
Eta: 6,
DoubleEtaBits: 4,
Beta: 325,
Omega: 80,
Name: "Dilithium2",
UseAES: false,
K: 4,
L: 4,
Eta: 2,
DoubleEtaBits: 3,
Omega: 80,
Tau: 39,
Gamma1Bits: 17,
Gamma2: (params.Q - 1) / 88,
},
{
Name: "Dilithium2-AES",
UseAES: true,
PublicKeySize: 1184,
PrivateKeySize: 2800,
SignatureSize: 2044,
K: 4,
L: 3,
Eta: 6,
DoubleEtaBits: 4,
Beta: 325,
Omega: 80,
Name: "Dilithium2-AES",
UseAES: true,
K: 4,
L: 4,
Eta: 2,
DoubleEtaBits: 3,
Omega: 80,
Tau: 39,
Gamma1Bits: 17,
Gamma2: (params.Q - 1) / 88,
},
{
Name: "Dilithium3",
UseAES: false,
PublicKeySize: 1472,
PrivateKeySize: 3504,
SignatureSize: 2701,
K: 5,
L: 4,
Eta: 5,
DoubleEtaBits: 4,
Beta: 275,
Omega: 96,
Name: "Dilithium3",
UseAES: false,
K: 6,
L: 5,
Eta: 4,
DoubleEtaBits: 4,
Omega: 55,
Tau: 49,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
},
{
Name: "Dilithium3-AES",
UseAES: true,
PublicKeySize: 1472,
PrivateKeySize: 3504,
SignatureSize: 2701,
K: 5,
L: 4,
Eta: 5,
DoubleEtaBits: 4,
Beta: 275,
Omega: 96,
Name: "Dilithium3-AES",
UseAES: true,
K: 6,
L: 5,
Eta: 4,
DoubleEtaBits: 4,
Omega: 55,
Tau: 49,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
}, {
Name: "Dilithium4",
UseAES: false,
PublicKeySize: 1760,
PrivateKeySize: 3856,
SignatureSize: 3366,
K: 6,
L: 5,
Eta: 3,
DoubleEtaBits: 3,
Beta: 175,
Omega: 120,
Name: "Dilithium5",
UseAES: false,
K: 8,
L: 7,
Eta: 2,
DoubleEtaBits: 3,
Omega: 75,
Tau: 60,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
}, {
Name: "Dilithium4-AES",
UseAES: true,
PublicKeySize: 1760,
PrivateKeySize: 3856,
SignatureSize: 3366,
K: 6,
L: 5,
Eta: 3,
DoubleEtaBits: 3,
Beta: 175,
Omega: 120,
Name: "Dilithium5-AES",
UseAES: true,
K: 8,
L: 7,
Eta: 2,
DoubleEtaBits: 3,
Omega: 75,
Tau: 60,
Gamma1Bits: 19,
Gamma2: (params.Q - 1) / 32,
},
}
TemplateWarning = "// Code generated from"
Expand Down Expand Up @@ -240,7 +209,8 @@ func generateSourceFiles() {

// Ignore mode specific files.
ignored := func(x string) bool {
return x == "params.go" || x == "params_test.go"
return x == "params.go" || x == "params_test.go" ||
strings.HasSuffix(x, ".swp")
}

fs, err := ioutil.ReadDir("mode3/internal")
Expand Down Expand Up @@ -275,7 +245,7 @@ func generateSourceFiles() {
}
_, ok := files[name]
if !ok {
fmt.Printf("Removing superfluous file: %s", fn)
fmt.Printf("Removing superfluous file: %s\n", fn)
err = os.Remove(fn)
if err != nil {
panic(err)
Expand Down
4 changes: 2 additions & 2 deletions sign/dilithium/internal/common/aes.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ func NewAesStream128(key *[32]byte, nonce uint16) AesStream {
// Create a new AesStream as a replacement of SHAKE256. (Note that
// not all occurrences of SHAKE are replaced by AES in the AES-variants.)
//
// Yes, in an AES mode, Dilithium throws away the last 16 bytes of a seed ...
// Yes, in an AES mode, Dilithium throws away the last 32 bytes of a seed ...
// See the remark at the end of the caption of Figure 4 in the Round 2 spec.
func NewAesStream256(key *[48]byte, nonce uint16) AesStream {
func NewAesStream256(key *[64]byte, nonce uint16) AesStream {
c, _ := aes.NewCipher(key[:32])
return AesStream{c: c, nonce: nonce}
}
Expand Down
Loading

0 comments on commit 5d1f07e

Please sign in to comment.