From 067a9a3e2ffcf3e76579d65ccd11a1fa6cebbc0c Mon Sep 17 00:00:00 2001 From: JackDoan Date: Thu, 11 Sep 2025 16:05:17 -0500 Subject: [PATCH 1/6] bump nebula to current master for cert-v2 support --- client_test.go | 36 +++++++++++++------------- dnapitest/dnapitest.go | 59 +++++++++++++++++++++--------------------- go.mod | 15 +++++------ go.sum | 41 +++++++++++------------------ keys/crypto.go | 10 +++---- keys/pem.go | 8 +++--- 6 files changed, 79 insertions(+), 90 deletions(-) diff --git a/client_test.go b/client_test.go index 6624a31..8fc64cb 100644 --- a/client_test.go +++ b/client_test.go @@ -54,7 +54,7 @@ func TestEnroll(t *testing.T) { oidcExpiresAt := time.Now() counter := uint(5) ca, _ := dnapitest.NebulaCACert() - caPEM, err := ca.MarshalToPEM() + caPEM, err := ca.MarshalPEM() require.NoError(t, err) ts.ExpectEnrollment(code, message.NetworkCurve25519, func(req message.EnrollRequest) []byte { @@ -78,7 +78,7 @@ func TestEnroll(t *testing.T) { HostID: hostID, Counter: counter, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: orgID, Name: orgName, @@ -109,7 +109,7 @@ func TestEnroll(t *testing.T) { assert.Empty(t, ts.Errors()) assert.Equal(t, 0, ts.RequestsRemaining()) - tk, err := keys.NewTrustedKey(ed25519.PublicKey(ca.Details.PublicKey)) + tk, err := keys.NewTrustedKey(ed25519.PublicKey(ca.PublicKey())) require.NoError(t, err) assert.Equal(t, hostID, creds.HostID) @@ -129,7 +129,7 @@ func TestEnroll(t *testing.T) { } err = yaml.Unmarshal(cfg, &y) require.NoError(t, err) - _, rest, err := cert.UnmarshalX25519PublicKey(y.Test.DHPubkey) + _, rest, _, err := cert.UnmarshalPublicKeyFromPEM(y.Test.DHPubkey) assert.NoError(t, err) assert.Len(t, rest, 0) assert.Equal(t, code, y.Test.Code) @@ -182,7 +182,7 @@ func TestDoUpdate(t *testing.T) { t.Cleanup(func() { ts.Close() }) ca, caPrivkey := dnapitest.NebulaCACert() - caPEM, err := ca.MarshalToPEM() + caPEM, err := ca.MarshalPEM() require.NoError(t, err) c := NewClient(useragent, ts.URL) @@ -209,7 +209,7 @@ func TestDoUpdate(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -278,7 +278,7 @@ func TestDoUpdate(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 2, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -333,7 +333,7 @@ func TestDoUpdate(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 0, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -393,7 +393,7 @@ func TestDoUpdate(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 3, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: orgID, Name: orgName, @@ -453,7 +453,7 @@ func TestDoUpdate_P256(t *testing.T) { t.Cleanup(func() { ts.Close() }) ca, caPrivkey := dnapitest.NebulaCACertP256() - caPEM, err := ca.MarshalToPEM() + caPEM, err := ca.MarshalPEM() require.NoError(t, err) c := NewClient(useragent, ts.URL) @@ -480,7 +480,7 @@ func TestDoUpdate_P256(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -638,7 +638,7 @@ func TestDoUpdate_P256(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 3, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -693,7 +693,7 @@ func TestCommandResponse(t *testing.T) { t.Cleanup(func() { ts.Close() }) ca, _ := dnapitest.NebulaCACert() - caPEM, err := ca.MarshalToPEM() + caPEM, err := ca.MarshalPEM() require.NoError(t, err) c := NewClient(useragent, ts.URL) @@ -720,7 +720,7 @@ func TestCommandResponse(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -798,7 +798,7 @@ func TestStreamCommandResponse(t *testing.T) { t.Cleanup(func() { ts.Close() }) ca, _ := dnapitest.NebulaCACert() - caPEM, err := ca.MarshalToPEM() + caPEM, err := ca.MarshalPEM() require.NoError(t, err) c := NewClient(useragent, ts.URL) @@ -825,7 +825,7 @@ func TestStreamCommandResponse(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -924,7 +924,7 @@ func TestReauthenticate(t *testing.T) { t.Cleanup(func() { ts.Close() }) ca, caPrivkey := dnapitest.NebulaCACert() - caPEM, err := ca.MarshalToPEM() + caPEM, err := ca.MarshalPEM() require.NoError(t, err) c := NewClient(useragent, ts.URL) @@ -951,7 +951,7 @@ func TestReauthenticate(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Details.Curve, ca.Details.PublicKey), + TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", diff --git a/dnapitest/dnapitest.go b/dnapitest/dnapitest.go index 4cb4677..a912a15 100644 --- a/dnapitest/dnapitest.go +++ b/dnapitest/dnapitest.go @@ -14,9 +14,9 @@ import ( "fmt" "io" "math/big" - "net" "net/http" "net/http/httptest" + "net/netip" "time" "github.com/DefinedNet/dnapi/keys" @@ -484,33 +484,33 @@ func NebulaCfg(caCert []byte) []byte { return nebulaCfg } -func NebulaCACert() (*cert.NebulaCertificate, ed25519.PrivateKey) { +func NebulaCACert() (cert.Certificate, ed25519.PrivateKey) { pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { panic(err) } - nc := &cert.NebulaCertificate{ - Details: cert.NebulaCertificateDetails{ - Name: "UnitTesting", - Groups: []string{"testa", "testb"}, - Ips: []*net.IPNet{}, - Subnets: []*net.IPNet{}, - NotBefore: time.Now(), - NotAfter: time.Now().Add(24 * time.Hour), - PublicKey: pub, - IsCA: true, - }, + nc := cert.TBSCertificate{ + Version: cert.Version1, + Curve: cert.Curve_CURVE25519, + Name: "UnitTesting", + Groups: []string{"testa", "testb"}, + Networks: []netip.Prefix{}, + UnsafeNetworks: []netip.Prefix{}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + PublicKey: pub, + IsCA: true, } - err = nc.Sign(nc.Details.Curve, priv) + out, err := nc.Sign(nil, nc.Curve, priv) if err != nil { panic(err) } - return nc, priv + return out, priv } -func NebulaCACertP256() (*cert.NebulaCertificate, *ecdsa.PrivateKey) { +func NebulaCACertP256() (cert.Certificate, *ecdsa.PrivateKey) { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(err) @@ -526,23 +526,22 @@ func NebulaCACertP256() (*cert.NebulaCertificate, *ecdsa.PrivateKey) { rawPriv := eKey.Bytes() pub := eKey.PublicKey().Bytes() - nc := &cert.NebulaCertificate{ - Details: cert.NebulaCertificateDetails{ - Curve: cert.Curve_P256, - Name: "UnitTesting", - Groups: []string{"testa", "testb"}, - Ips: []*net.IPNet{}, - Subnets: []*net.IPNet{}, - NotBefore: time.Now(), - NotAfter: time.Now().Add(24 * time.Hour), - PublicKey: pub, - IsCA: true, - }, + nc := cert.TBSCertificate{ + Version: cert.Version1, + Curve: cert.Curve_P256, + Name: "UnitTesting", + Groups: []string{"testa", "testb"}, + Networks: []netip.Prefix{}, + UnsafeNetworks: []netip.Prefix{}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + PublicKey: pub, + IsCA: true, } - err = nc.Sign(nc.Details.Curve, rawPriv) + out, err := nc.Sign(nil, nc.Curve, rawPriv) if err != nil { panic(err) } - return nc, key + return out, key } diff --git a/go.mod b/go.mod index 7774303..22faf2d 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,21 @@ module github.com/DefinedNet/dnapi -go 1.24.0 +go 1.25 require ( - github.com/sirupsen/logrus v1.9.2 - github.com/slackhq/nebula v1.7.1 - github.com/stretchr/testify v1.8.2 - golang.org/x/crypto v0.42.0 + github.com/sirupsen/logrus v1.9.3 + github.com/slackhq/nebula v1.10.0 + github.com/stretchr/testify v1.11.1 + golang.org/x/crypto v0.46.0 gopkg.in/yaml.v2 v2.4.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.9 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.36.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + golang.org/x/sys v0.39.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b83b7e6..8e076aa 100644 --- a/go.sum +++ b/go.sum @@ -2,10 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -16,32 +14,23 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= -github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/slackhq/nebula v1.7.1 h1:+kzPkx9rMXJKj43N7Zcdb+ZsHAX+/u2beS7qPHbWhdw= -github.com/slackhq/nebula v1.7.1/go.mod h1:cnaoahkUipDs1vrNoIszyp0QPRIQN9Pm68ppQEW1Fhg= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/slackhq/nebula v1.10.0 h1:uhu4Cpzw3pXyDJ8G1fMSppsvG7aE9XCt4UaauggHax0= +github.com/slackhq/nebula v1.10.0/go.mod h1:PmYcyoGhAX4X8lCzJjGv7aLTBbFbPy7QeWbpwWvJf+Y= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= -golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/keys/crypto.go b/keys/crypto.go index ee256da..af8cc2e 100644 --- a/keys/crypto.go +++ b/keys/crypto.go @@ -150,18 +150,18 @@ func newP256Keypair() (*ecdsa.PublicKey, *ecdsa.PrivateKey, error) { return privkey.Public().(*ecdsa.PublicKey), privkey, nil } -// newNebulaX25519KeypairPEM returns a new Nebula keypair (X25519) in PEM format. +// newNebulaX25519KeypairPEM returns a new Nebula key-agreement keypair (ED25519) in PEM format. func newNebulaX25519KeypairPEM() ([]byte, []byte, error) { pubkey, privkey, err := newX25519Keypair() if err != nil { return nil, nil, err } - pubkey, privkey = cert.MarshalX25519PublicKey(pubkey), cert.MarshalX25519PrivateKey(privkey) + pubkey, privkey = cert.MarshalPublicKeyToPEM(cert.Curve_CURVE25519, pubkey), cert.MarshalPrivateKeyToPEM(cert.Curve_P256, privkey) return pubkey, privkey, nil } -// newNebulaP256KeypairPEM returns a new Nebula keypair (P256) in PEM format. +// newNebulaP256KeypairPEM returns a new Nebula key-agreement keypair (P256) in PEM format. func newNebulaP256KeypairPEM() ([]byte, []byte, error) { rawPrivkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { @@ -173,8 +173,8 @@ func newNebulaP256KeypairPEM() ([]byte, []byte, error) { return nil, nil, err } - pubkey := cert.MarshalPublicKey(cert.Curve_P256, ecdhPrivkey.PublicKey().Bytes()) - privkey := cert.MarshalPrivateKey(cert.Curve_P256, ecdhPrivkey.Bytes()) + pubkey := cert.MarshalPublicKeyToPEM(cert.Curve_P256, ecdhPrivkey.PublicKey().Bytes()) + privkey := cert.MarshalPrivateKeyToPEM(cert.Curve_P256, ecdhPrivkey.Bytes()) return pubkey, privkey, nil } diff --git a/keys/pem.go b/keys/pem.go index 09bb79f..d51ea6e 100644 --- a/keys/pem.go +++ b/keys/pem.go @@ -168,9 +168,11 @@ func UnmarshalTrustedKey(b []byte) (TrustedKey, []byte, error) { if len(k.Bytes) != 65 { return nil, r, fmt.Errorf("key was not 65 bytes, is invalid P256 public key") } - - x, y := elliptic.Unmarshal(elliptic.P256(), k.Bytes) - return P256TrustedKey{&ecdsa.PublicKey{X: x, Y: y, Curve: elliptic.P256()}}, r, nil + pk, err := ecdsa.ParseUncompressedPublicKey(elliptic.P256(), k.Bytes) + if err != nil { + return nil, r, fmt.Errorf("failed to parse public key: %s", err) + } + return P256TrustedKey{pk}, r, nil case NebulaEd25519PublicKeyBanner: if len(k.Bytes) != ed25519.PublicKeySize { return nil, r, fmt.Errorf("key was not 32 bytes, is invalid ed25519 public key") From ec15620677b15d12140770df1d91bcda51736fca Mon Sep 17 00:00:00 2001 From: JackDoan Date: Tue, 9 Dec 2025 13:53:27 -0600 Subject: [PATCH 2/6] bonus broken test --- client_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/client_test.go b/client_test.go index 8fc64cb..005cb97 100644 --- a/client_test.go +++ b/client_test.go @@ -1217,3 +1217,16 @@ func TestDownloads(t *testing.T) { assert.Equal(t, "0.8.4", resp.VersionInfo.Latest.DNClient) assert.Equal(t, "0.5.1", resp.VersionInfo.Latest.Mobile) } + +func TestNebulaPemBanners(t *testing.T) { + t.SkipNow() //todo this is correct for 25519 but not p256. Once this test passes, we can lean on Nebula's implementations. + const NebulaECDSAP256PublicKeyBanner = "NEBULA ECDSA P256 PUBLIC KEY" + const NebulaEd25519PublicKeyBanner = "NEBULA ED25519 PUBLIC KEY" + ca, _ := dnapitest.NebulaCACert() + pub := ca.MarshalPublicKeyPEM() + assert.Contains(t, string(pub), NebulaEd25519PublicKeyBanner) + + ca, _ = dnapitest.NebulaCACertP256() + pub = ca.MarshalPublicKeyPEM() + assert.Contains(t, string(pub), NebulaECDSAP256PublicKeyBanner) +} From 53686c93520512c820efbaa14f5b320d0a9344c0 Mon Sep 17 00:00:00 2001 From: JackDoan Date: Wed, 10 Dec 2025 10:57:34 -0600 Subject: [PATCH 3/6] prefer Nebula's public key handling functions where possible --- client_test.go | 33 ++++++++++----------------------- go.mod | 2 +- go.sum | 4 ++-- keys/pem.go | 10 +++++----- keys/trusted_keys.go | 6 ++++-- 5 files changed, 22 insertions(+), 33 deletions(-) diff --git a/client_test.go b/client_test.go index 005cb97..2c99067 100644 --- a/client_test.go +++ b/client_test.go @@ -8,7 +8,6 @@ import ( "crypto/rand" "crypto/sha256" "encoding/json" - "encoding/pem" "errors" "fmt" "io" @@ -78,7 +77,7 @@ func TestEnroll(t *testing.T) { HostID: hostID, Counter: counter, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: orgID, Name: orgName, @@ -209,7 +208,7 @@ func TestDoUpdate(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -278,7 +277,7 @@ func TestDoUpdate(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 2, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -333,7 +332,7 @@ func TestDoUpdate(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 0, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -393,7 +392,7 @@ func TestDoUpdate(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 3, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: orgID, Name: orgName, @@ -480,7 +479,7 @@ func TestDoUpdate_P256(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -638,7 +637,7 @@ func TestDoUpdate_P256(t *testing.T) { Config: dnapitest.NebulaCfg(caPEM), Counter: 3, Nonce: dnapitest.GetNonce(r), - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -720,7 +719,7 @@ func TestCommandResponse(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -825,7 +824,7 @@ func TestStreamCommandResponse(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -951,7 +950,7 @@ func TestReauthenticate(t *testing.T) { HostID: "foobar", Counter: 1, Config: cfg, - TrustedKeys: marshalCAPublicKey(ca.Curve(), ca.PublicKey()), + TrustedKeys: ca.MarshalPublicKeyPEM(), Organization: message.HostOrgMetadata{ ID: "foobaz", Name: "foobar's foo org", @@ -1062,17 +1061,6 @@ func TestOverrideTimeout(t *testing.T) { require.ErrorIs(t, err, context.DeadlineExceeded) } -func marshalCAPublicKey(curve cert.Curve, pubkey []byte) []byte { - switch curve { - case cert.Curve_CURVE25519: - return pem.EncodeToMemory(&pem.Block{Type: keys.NebulaEd25519PublicKeyBanner, Bytes: pubkey}) - case cert.Curve_P256: - return pem.EncodeToMemory(&pem.Block{Type: keys.NebulaECDSAP256PublicKeyBanner, Bytes: pubkey}) - default: - panic("unsupported curve") - } -} - func TestGetOidcPollCode(t *testing.T) { t.Parallel() @@ -1219,7 +1207,6 @@ func TestDownloads(t *testing.T) { } func TestNebulaPemBanners(t *testing.T) { - t.SkipNow() //todo this is correct for 25519 but not p256. Once this test passes, we can lean on Nebula's implementations. const NebulaECDSAP256PublicKeyBanner = "NEBULA ECDSA P256 PUBLIC KEY" const NebulaEd25519PublicKeyBanner = "NEBULA ED25519 PUBLIC KEY" ca, _ := dnapitest.NebulaCACert() diff --git a/go.mod b/go.mod index 22faf2d..93406ee 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.25 require ( github.com/sirupsen/logrus v1.9.3 - github.com/slackhq/nebula v1.10.0 + github.com/slackhq/nebula v1.10.1-0.20251210163936-3ec527e42cec github.com/stretchr/testify v1.11.1 golang.org/x/crypto v0.46.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 8e076aa..072e53b 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/slackhq/nebula v1.10.0 h1:uhu4Cpzw3pXyDJ8G1fMSppsvG7aE9XCt4UaauggHax0= -github.com/slackhq/nebula v1.10.0/go.mod h1:PmYcyoGhAX4X8lCzJjGv7aLTBbFbPy7QeWbpwWvJf+Y= +github.com/slackhq/nebula v1.10.1-0.20251210163936-3ec527e42cec h1:F251X4hgG3Fen49ouS7yUVcwYkvvCjb5bmRFAbMnm+c= +github.com/slackhq/nebula v1.10.1-0.20251210163936-3ec527e42cec/go.mod h1:mqXWEQjg+I1r5KeCqji83gA0rZPCY9yvP25USUBFGxc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= diff --git a/keys/pem.go b/keys/pem.go index d51ea6e..ee40dc0 100644 --- a/keys/pem.go +++ b/keys/pem.go @@ -7,6 +7,8 @@ import ( "crypto/x509" "encoding/pem" "fmt" + + "github.com/slackhq/nebula/cert" ) const HostEd25519PublicKeyBanner = "DEFINED HOST ED25519 PUBLIC KEY" @@ -14,9 +16,6 @@ const HostEd25519PrivateKeyBanner = "DEFINED HOST ED25519 PRIVATE KEY" const HostP256PublicKeyBanner = "DEFINED HOST P256 PUBLIC KEY" const HostP256PrivateKeyBanner = "DEFINED HOST P256 PRIVATE KEY" -const NebulaECDSAP256PublicKeyBanner = "NEBULA ECDSA P256 PUBLIC KEY" -const NebulaEd25519PublicKeyBanner = "NEBULA ED25519 PUBLIC KEY" - func MarshalHostEd25519PublicKey(k ed25519.PublicKey) ([]byte, error) { b, err := x509.MarshalPKIXPublicKey(k) if err != nil { @@ -163,8 +162,9 @@ func UnmarshalTrustedKey(b []byte) (TrustedKey, []byte, error) { return nil, r, fmt.Errorf("input did not contain a valid PEM encoded block") } + // we could use Nebula's implementation here, but we want to make sure we only see these specific banners. switch k.Type { - case NebulaECDSAP256PublicKeyBanner: + case cert.ECDSAP256PublicKeyBanner: if len(k.Bytes) != 65 { return nil, r, fmt.Errorf("key was not 65 bytes, is invalid P256 public key") } @@ -173,7 +173,7 @@ func UnmarshalTrustedKey(b []byte) (TrustedKey, []byte, error) { return nil, r, fmt.Errorf("failed to parse public key: %s", err) } return P256TrustedKey{pk}, r, nil - case NebulaEd25519PublicKeyBanner: + case cert.Ed25519PublicKeyBanner: if len(k.Bytes) != ed25519.PublicKeySize { return nil, r, fmt.Errorf("key was not 32 bytes, is invalid ed25519 public key") } diff --git a/keys/trusted_keys.go b/keys/trusted_keys.go index 6d5fa28..270c9d1 100644 --- a/keys/trusted_keys.go +++ b/keys/trusted_keys.go @@ -7,6 +7,8 @@ import ( "crypto/sha256" "encoding/pem" "fmt" + + "github.com/slackhq/nebula/cert" ) // TrustedKey is an interface used to generically verify signatures returned @@ -42,7 +44,7 @@ func (key Ed25519TrustedKey) Unwrap() any { } func (key Ed25519TrustedKey) MarshalPEM() ([]byte, error) { - return pem.EncodeToMemory(&pem.Block{Type: NebulaEd25519PublicKeyBanner, Bytes: key.PublicKey}), nil + return pem.EncodeToMemory(&pem.Block{Type: cert.Ed25519PublicKeyBanner, Bytes: key.PublicKey}), nil } // P256TrustedKey is the P256 implementation of TrustedKey. @@ -61,7 +63,7 @@ func (key P256TrustedKey) Unwrap() any { func (key P256TrustedKey) MarshalPEM() ([]byte, error) { b := elliptic.Marshal(elliptic.P256(), key.X, key.Y) - return pem.EncodeToMemory(&pem.Block{Type: NebulaECDSAP256PublicKeyBanner, Bytes: b}), nil + return pem.EncodeToMemory(&pem.Block{Type: cert.ECDSAP256PublicKeyBanner, Bytes: b}), nil } // TrustedKeysToPEM converts a slice of TrustedKey to a PEM-encoded byte slice. From b18672a19b464789a56cd751d901e3ce21f69e39 Mon Sep 17 00:00:00 2001 From: JackDoan Date: Wed, 10 Dec 2025 15:11:56 -0600 Subject: [PATCH 4/6] fix typo --- keys/crypto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keys/crypto.go b/keys/crypto.go index af8cc2e..f34603c 100644 --- a/keys/crypto.go +++ b/keys/crypto.go @@ -156,7 +156,7 @@ func newNebulaX25519KeypairPEM() ([]byte, []byte, error) { if err != nil { return nil, nil, err } - pubkey, privkey = cert.MarshalPublicKeyToPEM(cert.Curve_CURVE25519, pubkey), cert.MarshalPrivateKeyToPEM(cert.Curve_P256, privkey) + pubkey, privkey = cert.MarshalPublicKeyToPEM(cert.Curve_CURVE25519, pubkey), cert.MarshalPrivateKeyToPEM(cert.Curve_CURVE25519, privkey) return pubkey, privkey, nil } From f43810ceab90bf05297fb244815c6282e414c312 Mon Sep 17 00:00:00 2001 From: JackDoan Date: Wed, 10 Dec 2025 15:12:15 -0600 Subject: [PATCH 5/6] fix typo --- keys/crypto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keys/crypto.go b/keys/crypto.go index f34603c..b906571 100644 --- a/keys/crypto.go +++ b/keys/crypto.go @@ -150,7 +150,7 @@ func newP256Keypair() (*ecdsa.PublicKey, *ecdsa.PrivateKey, error) { return privkey.Public().(*ecdsa.PublicKey), privkey, nil } -// newNebulaX25519KeypairPEM returns a new Nebula key-agreement keypair (ED25519) in PEM format. +// newNebulaX25519KeypairPEM returns a new Nebula key-agreement keypair (Ed25519) in PEM format. func newNebulaX25519KeypairPEM() ([]byte, []byte, error) { pubkey, privkey, err := newX25519Keypair() if err != nil { From dbbe95a971e1c958b21d4a0275e007498b0c5261 Mon Sep 17 00:00:00 2001 From: JackDoan Date: Wed, 10 Dec 2025 15:15:08 -0600 Subject: [PATCH 6/6] fix typo 2 --- keys/crypto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keys/crypto.go b/keys/crypto.go index b906571..58a1910 100644 --- a/keys/crypto.go +++ b/keys/crypto.go @@ -150,7 +150,7 @@ func newP256Keypair() (*ecdsa.PublicKey, *ecdsa.PrivateKey, error) { return privkey.Public().(*ecdsa.PublicKey), privkey, nil } -// newNebulaX25519KeypairPEM returns a new Nebula key-agreement keypair (Ed25519) in PEM format. +// newNebulaX25519KeypairPEM returns a new Nebula key-agreement keypair (X25519) in PEM format. func newNebulaX25519KeypairPEM() ([]byte, []byte, error) { pubkey, privkey, err := newX25519Keypair() if err != nil {