Skip to content

Commit

Permalink
Update to match api changes
Browse files Browse the repository at this point in the history
  • Loading branch information
johnmaguire committed Nov 22, 2024
1 parent d8e1da4 commit 6f272f9
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 40 deletions.
13 changes: 11 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,18 @@ func (c *Client) Enroll(ctx context.Context, logger logrus.FieldLogger, code str
return nil, nil, nil, nil, err
}

hostPubkeyP256, err := MarshalECDSAP256PublicKey(keys.ecdsaP256PublicKey)
if err != nil {
return nil, nil, nil, nil, err
}

// Make a request to the API with the enrollment code
jv, err := json.Marshal(message.EnrollRequest{
Code: code,
DHPubkey: keys.x25519PublicKeyPEM,
EdPubkey: cert.MarshalEd25519PublicKey(ed25519.PublicKey(keys.ed25519PublicKey)),
P256ECDHPubkey: keys.ecdhP256PublicKeyPEM,
P256ECDSAPubkey: MarshalECDSAP256PublicKey(keys.ecdsaP256PublicKey),
P256ECDSAPubkey: hostPubkeyP256,
Timestamp: time.Now(),
})
if err != nil {
Expand Down Expand Up @@ -246,7 +251,11 @@ func (c *Client) DoUpdate(ctx context.Context, creds Credentials) ([]byte, []byt
privkeyPEM = newKeys.x25519PrivateKeyPEM
privkey = Ed25519PrivateKey{newKeys.ed25519PrivateKey}
case P256:
updateKeys.P256ECDSAPubkey = MarshalECDSAP256PublicKey(newKeys.ecdsaP256PublicKey)
b, err := MarshalECDSAP256PublicKey(newKeys.ecdsaP256PublicKey)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to marshal ECDSA P256 public key: %s", err)
}
updateKeys.P256ECDSAPubkey = b
updateKeys.P256ECDHPubkey = newKeys.ecdhP256PublicKeyPEM
privkeyPEM = newKeys.ecdhP256PrivateKeyPEM
privkey = P256PrivateKey{newKeys.ecdsaP256PrivateKey}
Expand Down
3 changes: 2 additions & 1 deletion client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ func TestDoUpdate(t *testing.T) {
config, pkey, creds, _, err := c.Enroll(ctx, testutil.NewTestLogger(), "foobar")
require.NoError(t, err)

pubkey := cert.MarshalEd25519PublicKey(ed25519.PublicKey(creds.PrivateKey.PublicKey()))
// convert privkey to private key
pubkey := cert.MarshalEd25519PublicKey(creds.PrivateKey.Unwrap().(ed25519.PrivateKey).Public().(ed25519.PublicKey))

// make sure all credential values were set
assert.NotEmpty(t, creds.HostID)
Expand Down
59 changes: 26 additions & 33 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
Expand All @@ -17,15 +18,22 @@ import (
const ECDSAP256PublicKeyBanner = "NEBULA ECDSA P256 PUBLIC KEY"

// MarshalECDSAP256PublicKey is a simple helper to PEM encode an ECDSA P256 public key
func MarshalECDSAP256PublicKey(key []byte) []byte {
return pem.EncodeToMemory(&pem.Block{Type: ECDSAP256PublicKeyBanner, Bytes: key})
func MarshalECDSAP256PublicKey(k *ecdsa.PublicKey) ([]byte, error) {
b, err := x509.MarshalPKIXPublicKey(k)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{
Type: ECDSAP256PublicKeyBanner,
Bytes: b,
}), nil
}

// PrivateKey is used to sign messages.
type PrivateKey interface {
Type() PrivateKeyType
PublicKey() PublicKey
Sign(msg []byte) ([]byte, error)
Unwrap() interface{}
}

type PrivateKeyType int
Expand All @@ -43,14 +51,14 @@ func (k Ed25519PrivateKey) Type() PrivateKeyType {
return Ed25519
}

func (k Ed25519PrivateKey) PublicKey() PublicKey {
return PublicKey(k.Public().(ed25519.PublicKey))
}

func (k Ed25519PrivateKey) Sign(msg []byte) ([]byte, error) {
return ed25519.Sign(k.PrivateKey, msg), nil
}

func (k Ed25519PrivateKey) Unwrap() interface{} {
return k.PrivateKey
}

type P256PrivateKey struct {
*ecdsa.PrivateKey
}
Expand All @@ -59,34 +67,26 @@ func (k P256PrivateKey) Type() PrivateKeyType {
return P256
}

func (k P256PrivateKey) PublicKey() PublicKey {
pkey, err := k.ECDH()
if err != nil {
panic(err)
}

return pkey.PublicKey().Bytes()
}

func (k P256PrivateKey) Sign(msg []byte) ([]byte, error) {
hashed := sha256.Sum256(msg)
return ecdsa.SignASN1(rand.Reader, k.PrivateKey, hashed[:])
}

// PublicKey is used to carry the public key of a PrivateKey.
type PublicKey []byte
func (k P256PrivateKey) Unwrap() interface{} {
return k.PrivateKey
}

type initialKeys struct {
// 25519 Curve
x25519PublicKeyPEM []byte // ECDH
x25519PrivateKeyPEM []byte // ECDH
ed25519PublicKey PublicKey // EdDSA
ed25519PublicKey []byte // EdDSA
ed25519PrivateKey ed25519.PrivateKey // EdDSA

// P256 Curve
ecdhP256PublicKeyPEM []byte // ECDH
ecdhP256PrivateKeyPEM []byte // ECDH
ecdsaP256PublicKey PublicKey // ECDSA
ecdsaP256PublicKey *ecdsa.PublicKey // ECDSA
ecdsaP256PrivateKey *ecdsa.PrivateKey // ECDSA, in spite of its type
}

Expand All @@ -104,7 +104,7 @@ func newKeys() (*initialKeys, error) {
return &initialKeys{
x25519PublicKeyPEM: x25519PublicKeyPEM,
x25519PrivateKeyPEM: x25519PrivateKeyPEM,
ed25519PublicKey: PublicKey(ed25519PublicKey),
ed25519PublicKey: ed25519PublicKey,
ed25519PrivateKey: ed25519PrivateKey,
ecdhP256PublicKeyPEM: ecdhP256PublicKeyPEM,
ecdhP256PrivateKeyPEM: ecdhP256PrivateKeyPEM,
Expand All @@ -129,7 +129,7 @@ func new25519Keys() ([]byte, []byte, ed25519.PublicKey, ed25519.PrivateKey, erro
}

// newP256Keys returns a new set of Nebula (Diffie-Hellman) ECDH P256 keys and a new set of ECDSA (request signing) keys.
func newP256Keys() ([]byte, []byte, []byte, *ecdsa.PrivateKey, error) {
func newP256Keys() ([]byte, []byte, *ecdsa.PublicKey, *ecdsa.PrivateKey, error) {
ecdhPubkeyPEM, ecdhPrivkeyPEM, err := newNebulaP256Keypair()
if err != nil {
return nil, nil, nil, nil, fmt.Errorf("failed to generate Nebula keypair: %s", err)
Expand Down Expand Up @@ -180,9 +180,9 @@ func newEd25519Keypair() (ed25519.PublicKey, ed25519.PrivateKey, error) {

// newNebulaP256Keypair returns a new Nebula keypair (P256) in PEM format.
func newNebulaP256Keypair() ([]byte, []byte, error) {
_, rawPrivkey, err := newP256Keypair()
rawPrivkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, nil, err
return nil, nil, fmt.Errorf("error while generating ecdsa keys: %s", err)
}

ecdhPrivkey, err := rawPrivkey.ECDH()
Expand All @@ -197,20 +197,13 @@ func newNebulaP256Keypair() ([]byte, []byte, error) {
}

// newP256Keypair create a pair of P256 public key and private key and returns them, in that order.
func newP256Keypair() ([]byte, *ecdsa.PrivateKey, error) {
func newP256Keypair() (*ecdsa.PublicKey, *ecdsa.PrivateKey, error) {
privkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, nil, fmt.Errorf("error while generating ecdsa keys: %s", err)
}

// ecdh.PrivateKey lets us get at the encoded bytes, even though
// we aren't using ECDH here.
pubkey, err := privkey.ECDH()
if err != nil {
return nil, nil, err
}

return pubkey.PublicKey().Bytes(), privkey, nil
return privkey.Public().(*ecdsa.PublicKey), privkey, nil
}

func nonce() []byte {
Expand Down
20 changes: 20 additions & 0 deletions crypto_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dnapi

import (
"crypto/ed25519"
"testing"

"github.com/slackhq/nebula/cert"
"github.com/stretchr/testify/require"
)

func TestNewKeys(t *testing.T) {
// TestNewKeys tests the creation of new keys
t.Parallel()
ik, err := newKeys()
require.NoError(t, err)
b, err := MarshalECDSAP256PublicKey(ik.ecdsaP256PublicKey)
require.NoError(t, err)

t.Logf("ecdhP256PublicKeyPEM: %s, ecdsaP256PublicKey: %s, ed25519PublicKey: %s", ik.ecdhP256PublicKeyPEM, b, cert.MarshalEd25519PublicKey(ed25519.PublicKey(ik.ed25519PublicKey)))
}
8 changes: 4 additions & 4 deletions message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ type CheckForUpdateResponse struct {
type DoUpdateRequest struct {
EdPubkeyPEM []byte `json:"edPubkeyPEM"` // X25519 (used for key exchange)
DHPubkeyPEM []byte `json:"dhPubkeyPEM"` // Ed25519 (used for signing)
P256ECDHPubkey []byte `json:"p256ECDHPubkeyPEM"` // P256 (used for key exchange)
P256ECDSAPubkey []byte `json:"p256ECDSAPubkeyPEM"` // P256 (used for signing)
P256ECDHPubkey []byte `json:"ecdhP256PubkeyPEM"` // P256 (used for key exchange)
P256ECDSAPubkey []byte `json:"ecdsaP256PubkeyPEM"` // P256 (used for signing)
Nonce []byte `json:"nonce"`
}

Expand Down Expand Up @@ -123,8 +123,8 @@ type EnrollRequest struct {
Code string `json:"code"`
DHPubkey []byte `json:"dhPubkey"` // X25519 (used for key exchange)
EdPubkey []byte `json:"edPubkey"` // Ed25519 (used for signing)
P256ECDHPubkey []byte `json:"p256ECDHPubkey"` // P256 (used for key exchange)
P256ECDSAPubkey []byte `json:"p256ECDSAPubkey"` // P256 (used for signing)
P256ECDHPubkey []byte `json:"ecdhP256Pubkey"` // P256 (used for key exchange)
P256ECDSAPubkey []byte `json:"ecdsaP256Pubkey"` // P256 (used for signing)
Timestamp time.Time `json:"timestamp"`
}

Expand Down

0 comments on commit 6f272f9

Please sign in to comment.