Skip to content

Commit

Permalink
WIP Support for CRYSTALS-Dilithium (NIST PQC Round2)
Browse files Browse the repository at this point in the history
https://pq-crystals.org/dilithium/data/dilithium-specification-round2.pdf

Notes

- At the moment, instead of using templates like other parts of circl,
  the dilithium code uses duplicated source files using symlinks.  This
  makes development a bit easier, but the layout a bit awkward.
- This implementation is based on the spec with the reference
  implementaiton used as, what is in a name, reference.  It turns out to
  be pretty close to the reference implementation.  I did not simply
  mimic their choices, but checked them (for instance, whether
  coefficients stay bounded.)  I did not find an issue except for some
  errors in comments.

To do

- [ ] Add public API
- [ ] Compare performance against C implementation
- [ ] Support AES-based CRH
- [ ] Check some implementation details
- [ ] Document Make/UseHint
- [ ] Check whether the optimized checks on the signature (as also used
      in the reference implementation) correspond to those prescribed in
      the specification.

Nice to have

- [ ] Add AVX2 optimized NTT

Investigate

- [ ] Check how stupid the current Go compiler is --- it might be worthwhile
      to do one of the following.
    - [ ] Add explicit constants for literals like 1<<(D-1)
    - [ ] Manually unroll loops in Poly, VecK and VecL
    - [ ] Eliminate branches
- [ ] Check if it's an issue that a single public key has multiple valid
      packed representations, (see PackT1/UnpackT1.)
  • Loading branch information
bwesterb committed Feb 12, 2020
1 parent 3855119 commit 62a2da3
Show file tree
Hide file tree
Showing 66 changed files with 2,657 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Version numbers are [Semvers](https://semver.org/). We release a minor version f
| Key Exchange | FourQ | One of the fastest elliptic curves at 128-bit security level. | Experimental for key agreement and digital signatures. |
| Key Exchange / Digital signatures | P-384 | Our optimizations reduce the burden when moving from P-256 to P-384. | ECDSA and ECDH using Suite B at top secret level. |
| Digital Signatures | Ed25519 | RFC-8032 provides new signature schemes based on Edwards curves. | Digital certificates and authentication. |
| Digital Signatures | Dilithium | Lattice (Module LWE) based signature scheme | Post-Quantum PKI |

### Work in Progress

Expand Down
6 changes: 6 additions & 0 deletions sign/dilithium/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dilithium
=========

Implementation of CRYSTALS-Dilithium
[as proposed](https://pq-crystals.org/dilithium/data/dilithium-specification-round2.pdf)
for the second round of the NIST PQC project.
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/dilithium.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/dilithium_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/field.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/field_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/kat_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/mat.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/ntt.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/ntt_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/pack.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/pack_test.go
14 changes: 14 additions & 0 deletions sign/dilithium/mode1/internal/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package internal

const (
Name = "Dilithium1"
PublicKeySize = 896
PrivateKeySize = 2096
SignatureSize = 1387
K = 3
L = 2
Eta = 7
DoubleEtaBits = 4
Beta = 375
Omega = 64
)
85 changes: 85 additions & 0 deletions sign/dilithium/mode1/internal/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package internal

import (
"testing"

"github.com/cloudflare/circl/internal/shake"
)

// Tests specific to the current mode

func hash(in []byte) [16]byte {
var ret [16]byte
h := shake.NewShake256()
h.Write(in)
h.Read(ret[:])
return ret
}

func TestNewKeyFromSeed(t *testing.T) {
var seed [SeedSize]byte
var pkp [PublicKeySize]byte
var skp [PrivateKeySize]byte
pk, sk := NewKeyFromSeed(&seed)
pk.Pack(&pkp)
sk.Pack(&skp)

// Generated with reference implementation.
ehpk := [16]byte{
131, 97, 105, 81, 185, 131, 18, 169,
126, 161, 14, 18, 183, 182, 150, 117,
}
ehsk := [16]byte{
175, 71, 14, 18, 165, 125, 0, 192, 76,
74, 43, 89, 152, 244, 28, 113,
}

if hash(pkp[:]) != ehpk {
t.Fatalf("pk not ok")
}
if hash(skp[:]) != ehsk {
t.Fatalf("sk not ok")
}
}

func TestVectorDeriveUniformLeqEta(t *testing.T) {
var p Poly
var seed [32]byte
p2 := Poly{
3, 0, 2, 3, 8380412, 8380414, 2, 2, 8380415, 8380416,
8380416, 1, 7, 8380411, 4, 7, 2, 8380414, 8380412, 0, 3,
8380413, 4, 8380410, 8380414, 8380410, 8380413, 8380412,
8380410, 8380410, 7, 3, 8380412, 3, 8380411, 8380414, 7,
8380415, 1, 8380416, 7, 8380414, 2, 4, 7, 8380416, 4, 5,
5, 2, 1, 8380411, 7, 3, 4, 8380416, 8380415, 2, 2, 8380410,
7, 5, 0, 8380411, 8380416, 7, 8380412, 5, 8380411, 5, 4,
1, 4, 2, 8380414, 8380416, 3, 4, 8380414, 8380410, 8380414,
7, 8380415, 8380412, 8380411, 6, 8380415, 8380410, 8380413,
0, 8380416, 8380412, 8380411, 6, 8380415, 8380410, 8380410,
8380413, 7, 8380415, 3, 1, 0, 8380414, 4, 8380410, 8380412,
5, 6, 0, 1, 8380410, 8380413, 8380410, 6, 8380411, 0,
8380415, 3, 8380411, 2, 3, 6, 8380410, 8380410, 0, 0, 6,
8380414, 0, 6, 8380411, 8380412, 8380412, 5, 7, 2, 8380413,
8380410, 0, 0, 4, 0, 5, 8380416, 1, 5, 7, 7, 8380410, 2,
0, 8380412, 6, 5, 4, 8380411, 0, 0, 7, 8380414, 8380416,
8380410, 4, 0, 8380411, 8380410, 8380413, 8380414, 3,
8380413, 8380414, 8380415, 7, 8380411, 8380414, 8380410,
5, 6, 8380410, 6, 8380415, 4, 0, 0, 8380416, 8380415,
8380415, 8380415, 4, 8380410, 8380411, 8380415, 8380412,
6, 1, 4, 1, 2, 8380411, 0, 8380416, 4, 8380414, 8380416,
6, 5, 1, 3, 8380414, 4, 8380414, 8380414, 3, 2, 2, 8380413,
2, 8380412, 0, 8380416, 8380415, 8380414, 0, 3, 8380413,
3, 8380410, 7, 8380410, 8380414, 8380412, 1, 4, 2, 8380415,
2, 8380410, 8380410, 8380410, 4, 8380413, 4, 4, 0, 3,
8380410, 5, 8380413, 8380414, 8380415, 4, 1, 8380410, 7,
8380413,
}
for i := 0; i < 32; i++ {
seed[i] = byte(i)
}
p.DeriveUniformLeqEta(&seed, 30000)
p.Normalize()
if p != p2 {
t.Fatalf("%v != %v", p, p2)
}
}
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/poly.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/sample.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/sample_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode1/internal/vec.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/dilithium.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/dilithium_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/field.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/field_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/kat_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/mat.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/ntt.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/ntt_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/pack.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/pack_test.go
14 changes: 14 additions & 0 deletions sign/dilithium/mode2/internal/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package internal

const (
Name = "Dilithium2"
PublicKeySize = 1184
PrivateKeySize = 2800
SignatureSize = 2044
K = 4
L = 3
Eta = 6
DoubleEtaBits = 4
Beta = 325
Omega = 80
)
85 changes: 85 additions & 0 deletions sign/dilithium/mode2/internal/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package internal

import (
"testing"

"github.com/cloudflare/circl/internal/shake"
)

// Tests specific to the current mode

func hash(in []byte) [16]byte {
var ret [16]byte
h := shake.NewShake256()
h.Write(in)
h.Read(ret[:])
return ret
}

func TestNewKeyFromSeed(t *testing.T) {
var seed [SeedSize]byte
var pkp [PublicKeySize]byte
var skp [PrivateKeySize]byte
pk, sk := NewKeyFromSeed(&seed)
pk.Pack(&pkp)
sk.Pack(&skp)

// Generated with reference implementation.
ehpk := [16]byte{
56, 231, 51, 157, 0, 230, 67, 72, 203,
47, 150, 94, 207, 158, 227, 139,
}
ehsk := [16]byte{
72, 222, 195, 214, 136, 51, 13, 252,
104, 249, 191, 66, 119, 251, 146, 225,
}

if hash(pkp[:]) != ehpk {
t.Fatalf("pk not ok")
}
if hash(skp[:]) != ehsk {
t.Fatalf("sk not ok")
}
}

func TestVectorDeriveUniformLeqEta(t *testing.T) {
var p Poly
var seed [32]byte
p2 := Poly{
2, 8380416, 1, 2, 8380411, 8380413, 1, 1, 8380414, 8380415,
8380415, 0, 6, 3, 6, 1, 8380413, 8380411, 8380416, 2,
8380412, 3, 8380413, 8380412, 8380411, 6, 2, 8380411, 2,
8380413, 6, 8380414, 0, 8380415, 6, 8380413, 1, 3, 6,
8380415, 3, 4, 4, 1, 0, 6, 2, 3, 8380415, 8380414, 1, 1,
6, 4, 8380416, 8380415, 6, 8380411, 4, 4, 3, 0, 3, 1,
8380413, 8380415, 2, 3, 8380413, 8380413, 6, 8380414,
8380411, 5, 8380414, 8380412, 8380416, 8380415, 8380411,
5, 8380414, 8380412, 6, 8380414, 2, 0, 8380416, 8380413,
3, 8380411, 4, 5, 8380416, 0, 8380412, 5, 8380416, 8380414,
2, 1, 2, 5, 8380416, 8380416, 5, 8380413, 8380416, 5,
8380411, 8380411, 4, 6, 1, 8380412, 8380416, 8380416, 3,
8380416, 4, 8380415, 0, 4, 6, 6, 1, 8380416, 8380411, 5,
4, 3, 8380416, 8380416, 6, 8380413, 8380415, 3, 8380416,
8380412, 8380413, 2, 8380412, 8380413, 8380414, 6, 8380413,
4, 5, 5, 8380414, 3, 8380416, 8380416, 8380415, 8380414,
8380414, 8380414, 3, 8380414, 8380411, 5, 0, 3, 0, 1,
8380416, 8380415, 3, 8380413, 8380415, 5, 4, 0, 2, 8380413,
3, 8380413, 8380413, 2, 1, 1, 8380412, 1, 8380411, 8380416,
8380415, 8380414, 8380413, 8380416, 2, 8380412, 2, 6,
8380413, 8380411, 0, 3, 1, 8380414, 1, 3, 8380412, 3, 3,
8380416, 2, 4, 8380412, 8380413, 8380414, 3, 0, 6, 8380412,
8380415, 8380416, 5, 5, 0, 6, 8380415, 8380413, 8380414,
5, 6, 3, 6, 3, 5, 5, 8380415, 6, 4, 8380416, 3, 2, 6,
8380414, 2, 8380415, 6, 8380412, 8380413, 8380415, 1, 2,
0, 8380411, 6, 8380413, 6, 8380414, 8380416, 8380415,
8380414, 1, 8380412,
}
for i := 0; i < 32; i++ {
seed[i] = byte(i)
}
p.DeriveUniformLeqEta(&seed, 30000)
p.Normalize()
if p != p2 {
t.Fatalf("%v != %v", p, p2)
}
}
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/poly.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/sample.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/sample_test.go
1 change: 1 addition & 0 deletions sign/dilithium/mode2/internal/vec.go
Loading

0 comments on commit 62a2da3

Please sign in to comment.