Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Kyber #60

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/cloudflare/circl/dh/sidh"
"github.com/cloudflare/circl/dh/x448"
"github.com/cloudflare/circl/kem/kyber/kyber512"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/curve25519"
)
Expand Down Expand Up @@ -738,6 +739,124 @@ func (s sikeScheme) setEphemeralKeyPair(skE KEMPrivateKey) {
panic("SIKE cannot use a pre-set ephemeral key pair")
}

///////////
// Kyber512

type kyber512PublicKey struct {
pub *kyber512.PublicKey
}

type kyber512PrivateKey struct {
priv *kyber512.PrivateKey
pub *kyber512.PublicKey

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to store the public key along: kyberx.PrivateKey already contains a kyberx.PublicKey. Use the Public() function.

}

func (priv kyber512PrivateKey) PublicKey() KEMPublicKey {
return &kyber512PublicKey{priv.pub}
}

type kyber512Scheme struct{}

func (s kyber512Scheme) ID() KEMID {
return KEM_KYBER512
}

func (s kyber512Scheme) generateKeyPair(rand io.Reader) (KEMPrivateKey, KEMPublicKey, error) {
pub, priv, err := kyber512.GenerateKeyPair(rand)
if err != nil {
return nil, nil, err
}

return &kyber512PrivateKey{priv, pub}, &kyber512PublicKey{pub}, nil
}

func (s kyber512Scheme) DeriveKeyPair(ikm []byte) (KEMPrivateKey, KEMPublicKey, error) {
// DeriveKeyPair takes an input of length Nsk, which in the case of Kyber512
// is much larger than the required seed size. So we just take the first part
// of it.
ikm = ikm[:kyber512.KeySeedSize]
pub, priv := kyber512.NewKeyFromSeed(ikm)
return &kyber512PrivateKey{priv, pub}, &kyber512PublicKey{pub}, nil
}

func (s kyber512Scheme) SerializePublicKey(pk KEMPublicKey) []byte {
if pk == nil {
return nil
}

raw := pk.(*kyber512PublicKey)
out := make([]byte, kyber512.PublicKeySize)
raw.pub.Pack(out)
return out
}

func (s kyber512Scheme) SerializePrivateKey(sk KEMPrivateKey) []byte {
if sk == nil {
return nil
}

raw := sk.(*kyber512PrivateKey)
out := make([]byte, kyber512.PrivateKeySize)
raw.pub.Pack(out)
return out
}

func (s kyber512Scheme) DeserializePublicKey(enc []byte) (KEMPublicKey, error) {
if len(enc) != kyber512.PublicKeySize {
return nil, fmt.Errorf("Invalid public key size: got %d, expected %d", len(enc), kyber512.PublicKeySize)
}

pub := &kyber512.PublicKey{}
pub.Unpack(enc)
return &kyber512PublicKey{pub}, nil
}

func (s kyber512Scheme) DeserializePrivateKey(enc []byte) (KEMPrivateKey, error) {
if len(enc) != kyber512.PrivateKeySize {
return nil, fmt.Errorf("Invalid private key size: got %d, expected %d", len(enc), kyber512.PrivateKeySize)
}

priv := &kyber512.PrivateKey{}
priv.Unpack(enc)
pub := priv.Public().(*kyber512.PublicKey)

return &kyber512PrivateKey{priv, pub}, nil
}

func (s kyber512Scheme) Encap(rand io.Reader, pkR KEMPublicKey) ([]byte, []byte, error) {
raw := pkR.(*kyber512PublicKey)

sharedSecret := make([]byte, kyber512.SharedKeySize)
enc := make([]byte, kyber512.CiphertextSize)
raw.pub.EncapsulateTo(enc, sharedSecret, nil)

return sharedSecret, enc, nil
}

func (s kyber512Scheme) Decap(enc []byte, skR KEMPrivateKey) ([]byte, error) {
raw := skR.(*kyber512PrivateKey)

if len(enc) != kyber512.CiphertextSize {
return nil, fmt.Errorf("Invalid encapsulated key size: got %d, expected %d", len(enc), kyber512.SharedKeySize)
}

sharedSecret := make([]byte, kyber512.SharedKeySize)
raw.priv.DecapsulateTo(sharedSecret, enc)
return sharedSecret, nil
}

func (s kyber512Scheme) PublicKeySize() int {
return kyber512.PublicKeySize
}

func (s kyber512Scheme) PrivateKeySize() int {
return kyber512.PrivateKeySize
}

func (s kyber512Scheme) setEphemeralKeyPair(skE KEMPrivateKey) {
panic("Kyber512 cannot use a pre-set ephemeral key pair")
}

//////////
// AES-GCM

Expand Down Expand Up @@ -913,6 +1032,7 @@ const (
DHKEM_P521 KEMID = 0x0012
DHKEM_X25519 KEMID = 0x0020
DHKEM_X448 KEMID = 0x0021
KEM_KYBER512 KEMID = 0xFFFD
KEM_SIKE503 KEMID = 0xFFFE
KEM_SIKE751 KEMID = 0xFFFF
)
Expand All @@ -922,6 +1042,7 @@ var kems = map[KEMID]KEMScheme{
DHKEM_X448: &dhkemScheme{group: x448Scheme{}},
DHKEM_P256: &dhkemScheme{group: ecdhScheme{curve: elliptic.P256(), KDF: hkdfScheme{hash: crypto.SHA256}}},
DHKEM_P521: &dhkemScheme{group: ecdhScheme{curve: elliptic.P521(), KDF: hkdfScheme{hash: crypto.SHA512}}},
KEM_KYBER512: &kyber512Scheme{},
KEM_SIKE503: &sikeScheme{field: sidh.Fp503, KDF: hkdfScheme{hash: crypto.SHA512}},
KEM_SIKE751: &sikeScheme{field: sidh.Fp751, KDF: hkdfScheme{hash: crypto.SHA512}},
}
Expand All @@ -936,6 +1057,8 @@ func newKEMScheme(kemID KEMID) (KEMScheme, bool) {
return &dhkemScheme{group: ecdhScheme{curve: elliptic.P256(), KDF: hkdfScheme{hash: crypto.SHA256}}}, true
case DHKEM_P521:
return &dhkemScheme{group: ecdhScheme{curve: elliptic.P521(), KDF: hkdfScheme{hash: crypto.SHA512}}}, true
case KEM_KYBER512:
return &kyber512Scheme{}, true
case KEM_SIKE503:
return &sikeScheme{field: sidh.Fp503, KDF: hkdfScheme{hash: crypto.SHA512}}, true
case KEM_SIKE751:
Expand Down
1 change: 1 addition & 0 deletions crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func TestKEMSchemes(t *testing.T) {
&dhkemScheme{group: x448Scheme{}},
&dhkemScheme{group: ecdhScheme{curve: elliptic.P256(), KDF: hkdfScheme{hash: crypto.SHA256}}},
&dhkemScheme{group: ecdhScheme{curve: elliptic.P521(), KDF: hkdfScheme{hash: crypto.SHA256}}},
&kyber512Scheme{},
&sikeScheme{field: sidh.Fp503, KDF: hkdfScheme{hash: crypto.SHA512}},
&sikeScheme{field: sidh.Fp751, KDF: hkdfScheme{hash: crypto.SHA512}},
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.14

require (
github.com/cisco/go-tls-syntax v0.0.0-20200617162716-46b0cfb76b9b
github.com/cloudflare/circl v1.0.0
github.com/cloudflare/circl v1.2.0
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
)
15 changes: 15 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
github.com/bwesterb/go-ristretto v1.2.1 h1:Xd9ZXmjKE2aY8Ub7+4bX7tXsIPsV1pIZaUlJUjI1toE=
github.com/bwesterb/go-ristretto v1.2.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cisco/go-tls-syntax v0.0.0-20200617162716-46b0cfb76b9b h1:Ves2turKTX7zruivAcUOQg155xggcbv3suVdbKCBQNM=
github.com/cisco/go-tls-syntax v0.0.0-20200617162716-46b0cfb76b9b/go.mod h1:0AZAV7lYvynZQ5ErHlGMKH+4QYMyNCFd+AiL9MlrCYA=
github.com/cloudflare/circl v1.0.0 h1:64b6pyfCFbYm623ncIkYGNZaOcmIbyd+CjyMi2L9vdI=
github.com/cloudflare/circl v1.0.0/go.mod h1:MhjB3NEEhJbTOdLLq964NIUisXDxaE1WkQPUxtgZXiY=
github.com/cloudflare/circl v1.2.0 h1:NheeISPSUcYftKlfrLuOo4T62FkmD4t4jviLfFFYaec=
github.com/cloudflare/circl v1.2.0/go.mod h1:Ch2UgYr6ti2KTtlejELlROl0YIYj7SLjAC8M+INXlMk=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -12,12 +16,23 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed h1:uPxWBzB3+mlnjy9W58qY1j/cjyFjutgw/Vhan2zLy/A=
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc=
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
Expand Down