github.com/slackhq/nebula@v1.9.0/cert/cert_test.go (about)

     1  package cert
     2  
     3  import (
     4  	"crypto/ecdh"
     5  	"crypto/ecdsa"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"fmt"
     9  	"io"
    10  	"net"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/slackhq/nebula/test"
    15  	"github.com/stretchr/testify/assert"
    16  	"golang.org/x/crypto/curve25519"
    17  	"golang.org/x/crypto/ed25519"
    18  	"google.golang.org/protobuf/proto"
    19  )
    20  
    21  func TestMarshalingNebulaCertificate(t *testing.T) {
    22  	before := time.Now().Add(time.Second * -60).Round(time.Second)
    23  	after := time.Now().Add(time.Second * 60).Round(time.Second)
    24  	pubKey := []byte("1234567890abcedfghij1234567890ab")
    25  
    26  	nc := NebulaCertificate{
    27  		Details: NebulaCertificateDetails{
    28  			Name: "testing",
    29  			Ips: []*net.IPNet{
    30  				{IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
    31  				{IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
    32  				{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
    33  			},
    34  			Subnets: []*net.IPNet{
    35  				{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
    36  				{IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
    37  				{IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
    38  			},
    39  			Groups:    []string{"test-group1", "test-group2", "test-group3"},
    40  			NotBefore: before,
    41  			NotAfter:  after,
    42  			PublicKey: pubKey,
    43  			IsCA:      false,
    44  			Issuer:    "1234567890abcedfghij1234567890ab",
    45  		},
    46  		Signature: []byte("1234567890abcedfghij1234567890ab"),
    47  	}
    48  
    49  	b, err := nc.Marshal()
    50  	assert.Nil(t, err)
    51  	//t.Log("Cert size:", len(b))
    52  
    53  	nc2, err := UnmarshalNebulaCertificate(b)
    54  	assert.Nil(t, err)
    55  
    56  	assert.Equal(t, nc.Signature, nc2.Signature)
    57  	assert.Equal(t, nc.Details.Name, nc2.Details.Name)
    58  	assert.Equal(t, nc.Details.NotBefore, nc2.Details.NotBefore)
    59  	assert.Equal(t, nc.Details.NotAfter, nc2.Details.NotAfter)
    60  	assert.Equal(t, nc.Details.PublicKey, nc2.Details.PublicKey)
    61  	assert.Equal(t, nc.Details.IsCA, nc2.Details.IsCA)
    62  
    63  	// IP byte arrays can be 4 or 16 in length so we have to go this route
    64  	assert.Equal(t, len(nc.Details.Ips), len(nc2.Details.Ips))
    65  	for i, wIp := range nc.Details.Ips {
    66  		assert.Equal(t, wIp.String(), nc2.Details.Ips[i].String())
    67  	}
    68  
    69  	assert.Equal(t, len(nc.Details.Subnets), len(nc2.Details.Subnets))
    70  	for i, wIp := range nc.Details.Subnets {
    71  		assert.Equal(t, wIp.String(), nc2.Details.Subnets[i].String())
    72  	}
    73  
    74  	assert.EqualValues(t, nc.Details.Groups, nc2.Details.Groups)
    75  }
    76  
    77  func TestNebulaCertificate_Sign(t *testing.T) {
    78  	before := time.Now().Add(time.Second * -60).Round(time.Second)
    79  	after := time.Now().Add(time.Second * 60).Round(time.Second)
    80  	pubKey := []byte("1234567890abcedfghij1234567890ab")
    81  
    82  	nc := NebulaCertificate{
    83  		Details: NebulaCertificateDetails{
    84  			Name: "testing",
    85  			Ips: []*net.IPNet{
    86  				{IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
    87  				{IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
    88  				{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
    89  			},
    90  			Subnets: []*net.IPNet{
    91  				{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
    92  				{IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
    93  				{IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
    94  			},
    95  			Groups:    []string{"test-group1", "test-group2", "test-group3"},
    96  			NotBefore: before,
    97  			NotAfter:  after,
    98  			PublicKey: pubKey,
    99  			IsCA:      false,
   100  			Issuer:    "1234567890abcedfghij1234567890ab",
   101  		},
   102  	}
   103  
   104  	pub, priv, err := ed25519.GenerateKey(rand.Reader)
   105  	assert.Nil(t, err)
   106  	assert.False(t, nc.CheckSignature(pub))
   107  	assert.Nil(t, nc.Sign(Curve_CURVE25519, priv))
   108  	assert.True(t, nc.CheckSignature(pub))
   109  
   110  	_, err = nc.Marshal()
   111  	assert.Nil(t, err)
   112  	//t.Log("Cert size:", len(b))
   113  }
   114  
   115  func TestNebulaCertificate_SignP256(t *testing.T) {
   116  	before := time.Now().Add(time.Second * -60).Round(time.Second)
   117  	after := time.Now().Add(time.Second * 60).Round(time.Second)
   118  	pubKey := []byte("01234567890abcedfghij1234567890ab1234567890abcedfghij1234567890ab")
   119  
   120  	nc := NebulaCertificate{
   121  		Details: NebulaCertificateDetails{
   122  			Name: "testing",
   123  			Ips: []*net.IPNet{
   124  				{IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
   125  				{IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
   126  				{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
   127  			},
   128  			Subnets: []*net.IPNet{
   129  				{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
   130  				{IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
   131  				{IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
   132  			},
   133  			Groups:    []string{"test-group1", "test-group2", "test-group3"},
   134  			NotBefore: before,
   135  			NotAfter:  after,
   136  			PublicKey: pubKey,
   137  			IsCA:      false,
   138  			Curve:     Curve_P256,
   139  			Issuer:    "1234567890abcedfghij1234567890ab",
   140  		},
   141  	}
   142  
   143  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   144  	pub := elliptic.Marshal(elliptic.P256(), priv.PublicKey.X, priv.PublicKey.Y)
   145  	rawPriv := priv.D.FillBytes(make([]byte, 32))
   146  
   147  	assert.Nil(t, err)
   148  	assert.False(t, nc.CheckSignature(pub))
   149  	assert.Nil(t, nc.Sign(Curve_P256, rawPriv))
   150  	assert.True(t, nc.CheckSignature(pub))
   151  
   152  	_, err = nc.Marshal()
   153  	assert.Nil(t, err)
   154  	//t.Log("Cert size:", len(b))
   155  }
   156  
   157  func TestNebulaCertificate_Expired(t *testing.T) {
   158  	nc := NebulaCertificate{
   159  		Details: NebulaCertificateDetails{
   160  			NotBefore: time.Now().Add(time.Second * -60).Round(time.Second),
   161  			NotAfter:  time.Now().Add(time.Second * 60).Round(time.Second),
   162  		},
   163  	}
   164  
   165  	assert.True(t, nc.Expired(time.Now().Add(time.Hour)))
   166  	assert.True(t, nc.Expired(time.Now().Add(-time.Hour)))
   167  	assert.False(t, nc.Expired(time.Now()))
   168  }
   169  
   170  func TestNebulaCertificate_MarshalJSON(t *testing.T) {
   171  	time.Local = time.UTC
   172  	pubKey := []byte("1234567890abcedfghij1234567890ab")
   173  
   174  	nc := NebulaCertificate{
   175  		Details: NebulaCertificateDetails{
   176  			Name: "testing",
   177  			Ips: []*net.IPNet{
   178  				{IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
   179  				{IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
   180  				{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
   181  			},
   182  			Subnets: []*net.IPNet{
   183  				{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
   184  				{IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
   185  				{IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
   186  			},
   187  			Groups:    []string{"test-group1", "test-group2", "test-group3"},
   188  			NotBefore: time.Date(1, 0, 0, 1, 0, 0, 0, time.UTC),
   189  			NotAfter:  time.Date(1, 0, 0, 2, 0, 0, 0, time.UTC),
   190  			PublicKey: pubKey,
   191  			IsCA:      false,
   192  			Issuer:    "1234567890abcedfghij1234567890ab",
   193  		},
   194  		Signature: []byte("1234567890abcedfghij1234567890ab"),
   195  	}
   196  
   197  	b, err := nc.MarshalJSON()
   198  	assert.Nil(t, err)
   199  	assert.Equal(
   200  		t,
   201  		"{\"details\":{\"curve\":\"CURVE25519\",\"groups\":[\"test-group1\",\"test-group2\",\"test-group3\"],\"ips\":[\"10.1.1.1/24\",\"10.1.1.2/16\",\"10.1.1.3/ff00ff00\"],\"isCa\":false,\"issuer\":\"1234567890abcedfghij1234567890ab\",\"name\":\"testing\",\"notAfter\":\"0000-11-30T02:00:00Z\",\"notBefore\":\"0000-11-30T01:00:00Z\",\"publicKey\":\"313233343536373839306162636564666768696a313233343536373839306162\",\"subnets\":[\"9.1.1.1/ff00ff00\",\"9.1.1.2/24\",\"9.1.1.3/16\"]},\"fingerprint\":\"26cb1c30ad7872c804c166b5150fa372f437aa3856b04edb4334b4470ec728e4\",\"signature\":\"313233343536373839306162636564666768696a313233343536373839306162\"}",
   202  		string(b),
   203  	)
   204  }
   205  
   206  func TestNebulaCertificate_Verify(t *testing.T) {
   207  	ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
   208  	assert.Nil(t, err)
   209  
   210  	c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
   211  	assert.Nil(t, err)
   212  
   213  	h, err := ca.Sha256Sum()
   214  	assert.Nil(t, err)
   215  
   216  	caPool := NewCAPool()
   217  	caPool.CAs[h] = ca
   218  
   219  	f, err := c.Sha256Sum()
   220  	assert.Nil(t, err)
   221  	caPool.BlocklistFingerprint(f)
   222  
   223  	v, err := c.Verify(time.Now(), caPool)
   224  	assert.False(t, v)
   225  	assert.EqualError(t, err, "certificate is in the block list")
   226  
   227  	caPool.ResetCertBlocklist()
   228  	v, err = c.Verify(time.Now(), caPool)
   229  	assert.True(t, v)
   230  	assert.Nil(t, err)
   231  
   232  	v, err = c.Verify(time.Now().Add(time.Hour*1000), caPool)
   233  	assert.False(t, v)
   234  	assert.EqualError(t, err, "root certificate is expired")
   235  
   236  	c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   237  	assert.Nil(t, err)
   238  	v, err = c.Verify(time.Now().Add(time.Minute*6), caPool)
   239  	assert.False(t, v)
   240  	assert.EqualError(t, err, "certificate is expired")
   241  
   242  	// Test group assertion
   243  	ca, _, caKey, err = newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "test2"})
   244  	assert.Nil(t, err)
   245  
   246  	caPem, err := ca.MarshalToPEM()
   247  	assert.Nil(t, err)
   248  
   249  	caPool = NewCAPool()
   250  	caPool.AddCACertificate(caPem)
   251  
   252  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "bad"})
   253  	assert.Nil(t, err)
   254  	v, err = c.Verify(time.Now(), caPool)
   255  	assert.False(t, v)
   256  	assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
   257  
   258  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1"})
   259  	assert.Nil(t, err)
   260  	v, err = c.Verify(time.Now(), caPool)
   261  	assert.True(t, v)
   262  	assert.Nil(t, err)
   263  }
   264  
   265  func TestNebulaCertificate_VerifyP256(t *testing.T) {
   266  	ca, _, caKey, err := newTestCaCertP256(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
   267  	assert.Nil(t, err)
   268  
   269  	c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
   270  	assert.Nil(t, err)
   271  
   272  	h, err := ca.Sha256Sum()
   273  	assert.Nil(t, err)
   274  
   275  	caPool := NewCAPool()
   276  	caPool.CAs[h] = ca
   277  
   278  	f, err := c.Sha256Sum()
   279  	assert.Nil(t, err)
   280  	caPool.BlocklistFingerprint(f)
   281  
   282  	v, err := c.Verify(time.Now(), caPool)
   283  	assert.False(t, v)
   284  	assert.EqualError(t, err, "certificate is in the block list")
   285  
   286  	caPool.ResetCertBlocklist()
   287  	v, err = c.Verify(time.Now(), caPool)
   288  	assert.True(t, v)
   289  	assert.Nil(t, err)
   290  
   291  	v, err = c.Verify(time.Now().Add(time.Hour*1000), caPool)
   292  	assert.False(t, v)
   293  	assert.EqualError(t, err, "root certificate is expired")
   294  
   295  	c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   296  	assert.Nil(t, err)
   297  	v, err = c.Verify(time.Now().Add(time.Minute*6), caPool)
   298  	assert.False(t, v)
   299  	assert.EqualError(t, err, "certificate is expired")
   300  
   301  	// Test group assertion
   302  	ca, _, caKey, err = newTestCaCertP256(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "test2"})
   303  	assert.Nil(t, err)
   304  
   305  	caPem, err := ca.MarshalToPEM()
   306  	assert.Nil(t, err)
   307  
   308  	caPool = NewCAPool()
   309  	caPool.AddCACertificate(caPem)
   310  
   311  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "bad"})
   312  	assert.Nil(t, err)
   313  	v, err = c.Verify(time.Now(), caPool)
   314  	assert.False(t, v)
   315  	assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
   316  
   317  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1"})
   318  	assert.Nil(t, err)
   319  	v, err = c.Verify(time.Now(), caPool)
   320  	assert.True(t, v)
   321  	assert.Nil(t, err)
   322  }
   323  
   324  func TestNebulaCertificate_Verify_IPs(t *testing.T) {
   325  	_, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
   326  	_, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
   327  	ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
   328  	assert.Nil(t, err)
   329  
   330  	caPem, err := ca.MarshalToPEM()
   331  	assert.Nil(t, err)
   332  
   333  	caPool := NewCAPool()
   334  	caPool.AddCACertificate(caPem)
   335  
   336  	// ip is outside the network
   337  	cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
   338  	cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
   339  	c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
   340  	assert.Nil(t, err)
   341  	v, err := c.Verify(time.Now(), caPool)
   342  	assert.False(t, v)
   343  	assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
   344  
   345  	// ip is outside the network reversed order of above
   346  	cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
   347  	cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
   348  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
   349  	assert.Nil(t, err)
   350  	v, err = c.Verify(time.Now(), caPool)
   351  	assert.False(t, v)
   352  	assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
   353  
   354  	// ip is within the network but mask is outside
   355  	cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
   356  	cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
   357  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
   358  	assert.Nil(t, err)
   359  	v, err = c.Verify(time.Now(), caPool)
   360  	assert.False(t, v)
   361  	assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
   362  
   363  	// ip is within the network but mask is outside reversed order of above
   364  	cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
   365  	cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
   366  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
   367  	assert.Nil(t, err)
   368  	v, err = c.Verify(time.Now(), caPool)
   369  	assert.False(t, v)
   370  	assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
   371  
   372  	// ip and mask are within the network
   373  	cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
   374  	cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
   375  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
   376  	assert.Nil(t, err)
   377  	v, err = c.Verify(time.Now(), caPool)
   378  	assert.True(t, v)
   379  	assert.Nil(t, err)
   380  
   381  	// Exact matches
   382  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
   383  	assert.Nil(t, err)
   384  	v, err = c.Verify(time.Now(), caPool)
   385  	assert.True(t, v)
   386  	assert.Nil(t, err)
   387  
   388  	// Exact matches reversed
   389  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp2, caIp1}, []*net.IPNet{}, []string{"test"})
   390  	assert.Nil(t, err)
   391  	v, err = c.Verify(time.Now(), caPool)
   392  	assert.True(t, v)
   393  	assert.Nil(t, err)
   394  
   395  	// Exact matches reversed with just 1
   396  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1}, []*net.IPNet{}, []string{"test"})
   397  	assert.Nil(t, err)
   398  	v, err = c.Verify(time.Now(), caPool)
   399  	assert.True(t, v)
   400  	assert.Nil(t, err)
   401  }
   402  
   403  func TestNebulaCertificate_Verify_Subnets(t *testing.T) {
   404  	_, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
   405  	_, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
   406  	ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
   407  	assert.Nil(t, err)
   408  
   409  	caPem, err := ca.MarshalToPEM()
   410  	assert.Nil(t, err)
   411  
   412  	caPool := NewCAPool()
   413  	caPool.AddCACertificate(caPem)
   414  
   415  	// ip is outside the network
   416  	cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
   417  	cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
   418  	c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
   419  	assert.Nil(t, err)
   420  	v, err := c.Verify(time.Now(), caPool)
   421  	assert.False(t, v)
   422  	assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
   423  
   424  	// ip is outside the network reversed order of above
   425  	cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
   426  	cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
   427  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
   428  	assert.Nil(t, err)
   429  	v, err = c.Verify(time.Now(), caPool)
   430  	assert.False(t, v)
   431  	assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
   432  
   433  	// ip is within the network but mask is outside
   434  	cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
   435  	cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
   436  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
   437  	assert.Nil(t, err)
   438  	v, err = c.Verify(time.Now(), caPool)
   439  	assert.False(t, v)
   440  	assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
   441  
   442  	// ip is within the network but mask is outside reversed order of above
   443  	cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
   444  	cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
   445  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
   446  	assert.Nil(t, err)
   447  	v, err = c.Verify(time.Now(), caPool)
   448  	assert.False(t, v)
   449  	assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
   450  
   451  	// ip and mask are within the network
   452  	cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
   453  	cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
   454  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
   455  	assert.Nil(t, err)
   456  	v, err = c.Verify(time.Now(), caPool)
   457  	assert.True(t, v)
   458  	assert.Nil(t, err)
   459  
   460  	// Exact matches
   461  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
   462  	assert.Nil(t, err)
   463  	v, err = c.Verify(time.Now(), caPool)
   464  	assert.True(t, v)
   465  	assert.Nil(t, err)
   466  
   467  	// Exact matches reversed
   468  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp2, caIp1}, []string{"test"})
   469  	assert.Nil(t, err)
   470  	v, err = c.Verify(time.Now(), caPool)
   471  	assert.True(t, v)
   472  	assert.Nil(t, err)
   473  
   474  	// Exact matches reversed with just 1
   475  	c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1}, []string{"test"})
   476  	assert.Nil(t, err)
   477  	v, err = c.Verify(time.Now(), caPool)
   478  	assert.True(t, v)
   479  	assert.Nil(t, err)
   480  }
   481  
   482  func TestNebulaCertificate_VerifyPrivateKey(t *testing.T) {
   483  	ca, _, caKey, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   484  	assert.Nil(t, err)
   485  	err = ca.VerifyPrivateKey(Curve_CURVE25519, caKey)
   486  	assert.Nil(t, err)
   487  
   488  	_, _, caKey2, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   489  	assert.Nil(t, err)
   490  	err = ca.VerifyPrivateKey(Curve_CURVE25519, caKey2)
   491  	assert.NotNil(t, err)
   492  
   493  	c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   494  	err = c.VerifyPrivateKey(Curve_CURVE25519, priv)
   495  	assert.Nil(t, err)
   496  
   497  	_, priv2 := x25519Keypair()
   498  	err = c.VerifyPrivateKey(Curve_CURVE25519, priv2)
   499  	assert.NotNil(t, err)
   500  }
   501  
   502  func TestNebulaCertificate_VerifyPrivateKeyP256(t *testing.T) {
   503  	ca, _, caKey, err := newTestCaCertP256(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   504  	assert.Nil(t, err)
   505  	err = ca.VerifyPrivateKey(Curve_P256, caKey)
   506  	assert.Nil(t, err)
   507  
   508  	_, _, caKey2, err := newTestCaCertP256(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   509  	assert.Nil(t, err)
   510  	err = ca.VerifyPrivateKey(Curve_P256, caKey2)
   511  	assert.NotNil(t, err)
   512  
   513  	c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
   514  	err = c.VerifyPrivateKey(Curve_P256, priv)
   515  	assert.Nil(t, err)
   516  
   517  	_, priv2 := p256Keypair()
   518  	err = c.VerifyPrivateKey(Curve_P256, priv2)
   519  	assert.NotNil(t, err)
   520  }
   521  
   522  func TestNewCAPoolFromBytes(t *testing.T) {
   523  	noNewLines := `
   524  # Current provisional, Remove once everything moves over to the real root.
   525  -----BEGIN NEBULA CERTIFICATE-----
   526  CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
   527  vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
   528  bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
   529  -----END NEBULA CERTIFICATE-----
   530  # root-ca01
   531  -----BEGIN NEBULA CERTIFICATE-----
   532  CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
   533  BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
   534  8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
   535  -----END NEBULA CERTIFICATE-----
   536  `
   537  
   538  	withNewLines := `
   539  # Current provisional, Remove once everything moves over to the real root.
   540  
   541  -----BEGIN NEBULA CERTIFICATE-----
   542  CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
   543  vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
   544  bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
   545  -----END NEBULA CERTIFICATE-----
   546  
   547  # root-ca01
   548  
   549  
   550  -----BEGIN NEBULA CERTIFICATE-----
   551  CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
   552  BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
   553  8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
   554  -----END NEBULA CERTIFICATE-----
   555  
   556  `
   557  
   558  	expired := `
   559  # expired certificate
   560  -----BEGIN NEBULA CERTIFICATE-----
   561  CjkKB2V4cGlyZWQouPmWjQYwufmWjQY6ILCRaoCkJlqHgv5jfDN4lzLHBvDzaQm4
   562  vZxfu144hmgjQAESQG4qlnZi8DncvD/LDZnLgJHOaX1DWCHHEh59epVsC+BNgTie
   563  WH1M9n4O7cFtGlM6sJJOS+rCVVEJ3ABS7+MPdQs=
   564  -----END NEBULA CERTIFICATE-----
   565  `
   566  
   567  	p256 := `
   568  # p256 certificate
   569  -----BEGIN NEBULA CERTIFICATE-----
   570  CmYKEG5lYnVsYSBQMjU2IHRlc3Qo4s+7mgYw4tXrsAc6QQRkaW2jFmllYvN4+/k2
   571  6tctO9sPT3jOx8ES6M1nIqOhpTmZeabF/4rELDqPV4aH5jfJut798DUXql0FlF8H
   572  76gvQAGgBgESRzBFAiEAib0/te6eMiZOKD8gdDeloMTS0wGuX2t0C7TFdUhAQzgC
   573  IBNWYMep3ysx9zCgknfG5dKtwGTaqF++BWKDYdyl34KX
   574  -----END NEBULA CERTIFICATE-----
   575  `
   576  
   577  	rootCA := NebulaCertificate{
   578  		Details: NebulaCertificateDetails{
   579  			Name: "nebula root ca",
   580  		},
   581  	}
   582  
   583  	rootCA01 := NebulaCertificate{
   584  		Details: NebulaCertificateDetails{
   585  			Name: "nebula root ca 01",
   586  		},
   587  	}
   588  
   589  	rootCAP256 := NebulaCertificate{
   590  		Details: NebulaCertificateDetails{
   591  			Name: "nebula P256 test",
   592  		},
   593  	}
   594  
   595  	p, err := NewCAPoolFromBytes([]byte(noNewLines))
   596  	assert.Nil(t, err)
   597  	assert.Equal(t, p.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
   598  	assert.Equal(t, p.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
   599  
   600  	pp, err := NewCAPoolFromBytes([]byte(withNewLines))
   601  	assert.Nil(t, err)
   602  	assert.Equal(t, pp.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
   603  	assert.Equal(t, pp.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
   604  
   605  	// expired cert, no valid certs
   606  	ppp, err := NewCAPoolFromBytes([]byte(expired))
   607  	assert.Equal(t, ErrExpired, err)
   608  	assert.Equal(t, ppp.CAs[string("152070be6bb19bc9e3bde4c2f0e7d8f4ff5448b4c9856b8eccb314fade0229b0")].Details.Name, "expired")
   609  
   610  	// expired cert, with valid certs
   611  	pppp, err := NewCAPoolFromBytes(append([]byte(expired), noNewLines...))
   612  	assert.Equal(t, ErrExpired, err)
   613  	assert.Equal(t, pppp.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
   614  	assert.Equal(t, pppp.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
   615  	assert.Equal(t, pppp.CAs[string("152070be6bb19bc9e3bde4c2f0e7d8f4ff5448b4c9856b8eccb314fade0229b0")].Details.Name, "expired")
   616  	assert.Equal(t, len(pppp.CAs), 3)
   617  
   618  	ppppp, err := NewCAPoolFromBytes([]byte(p256))
   619  	assert.Nil(t, err)
   620  	assert.Equal(t, ppppp.CAs[string("a7938893ec8c4ef769b06d7f425e5e46f7a7f5ffa49c3bcf4a86b608caba9159")].Details.Name, rootCAP256.Details.Name)
   621  	assert.Equal(t, len(ppppp.CAs), 1)
   622  }
   623  
   624  func appendByteSlices(b ...[]byte) []byte {
   625  	retSlice := []byte{}
   626  	for _, v := range b {
   627  		retSlice = append(retSlice, v...)
   628  	}
   629  	return retSlice
   630  }
   631  
   632  func TestUnmrshalCertPEM(t *testing.T) {
   633  	goodCert := []byte(`
   634  # A good cert
   635  -----BEGIN NEBULA CERTIFICATE-----
   636  CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
   637  vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
   638  bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
   639  -----END NEBULA CERTIFICATE-----
   640  `)
   641  	badBanner := []byte(`# A bad banner
   642  -----BEGIN NOT A NEBULA CERTIFICATE-----
   643  CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
   644  vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
   645  bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
   646  -----END NOT A NEBULA CERTIFICATE-----
   647  `)
   648  	invalidPem := []byte(`# Not a valid PEM format
   649  -BEGIN NEBULA CERTIFICATE-----
   650  CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
   651  vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
   652  bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
   653  -END NEBULA CERTIFICATE----`)
   654  
   655  	certBundle := appendByteSlices(goodCert, badBanner, invalidPem)
   656  
   657  	// Success test case
   658  	cert, rest, err := UnmarshalNebulaCertificateFromPEM(certBundle)
   659  	assert.NotNil(t, cert)
   660  	assert.Equal(t, rest, append(badBanner, invalidPem...))
   661  	assert.Nil(t, err)
   662  
   663  	// Fail due to invalid banner.
   664  	cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
   665  	assert.Nil(t, cert)
   666  	assert.Equal(t, rest, invalidPem)
   667  	assert.EqualError(t, err, "bytes did not contain a proper nebula certificate banner")
   668  
   669  	// Fail due to ivalid PEM format, because
   670  	// it's missing the requisite pre-encapsulation boundary.
   671  	cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
   672  	assert.Nil(t, cert)
   673  	assert.Equal(t, rest, invalidPem)
   674  	assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
   675  }
   676  
   677  func TestUnmarshalSigningPrivateKey(t *testing.T) {
   678  	privKey := []byte(`# A good key
   679  -----BEGIN NEBULA ED25519 PRIVATE KEY-----
   680  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
   681  -----END NEBULA ED25519 PRIVATE KEY-----
   682  `)
   683  	privP256Key := []byte(`# A good key
   684  -----BEGIN NEBULA ECDSA P256 PRIVATE KEY-----
   685  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   686  -----END NEBULA ECDSA P256 PRIVATE KEY-----
   687  `)
   688  	shortKey := []byte(`# A short key
   689  -----BEGIN NEBULA ED25519 PRIVATE KEY-----
   690  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
   691  -----END NEBULA ED25519 PRIVATE KEY-----
   692  `)
   693  	invalidBanner := []byte(`# Invalid banner
   694  -----BEGIN NOT A NEBULA PRIVATE KEY-----
   695  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
   696  -----END NOT A NEBULA PRIVATE KEY-----
   697  `)
   698  	invalidPem := []byte(`# Not a valid PEM format
   699  -BEGIN NEBULA ED25519 PRIVATE KEY-----
   700  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
   701  -END NEBULA ED25519 PRIVATE KEY-----`)
   702  
   703  	keyBundle := appendByteSlices(privKey, privP256Key, shortKey, invalidBanner, invalidPem)
   704  
   705  	// Success test case
   706  	k, rest, curve, err := UnmarshalSigningPrivateKey(keyBundle)
   707  	assert.Len(t, k, 64)
   708  	assert.Equal(t, rest, appendByteSlices(privP256Key, shortKey, invalidBanner, invalidPem))
   709  	assert.Equal(t, Curve_CURVE25519, curve)
   710  	assert.Nil(t, err)
   711  
   712  	// Success test case
   713  	k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
   714  	assert.Len(t, k, 32)
   715  	assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
   716  	assert.Equal(t, Curve_P256, curve)
   717  	assert.Nil(t, err)
   718  
   719  	// Fail due to short key
   720  	k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
   721  	assert.Nil(t, k)
   722  	assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
   723  	assert.EqualError(t, err, "key was not 64 bytes, is invalid Ed25519 private key")
   724  
   725  	// Fail due to invalid banner
   726  	k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
   727  	assert.Nil(t, k)
   728  	assert.Equal(t, rest, invalidPem)
   729  	assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519/ECDSA private key banner")
   730  
   731  	// Fail due to ivalid PEM format, because
   732  	// it's missing the requisite pre-encapsulation boundary.
   733  	k, rest, curve, err = UnmarshalSigningPrivateKey(rest)
   734  	assert.Nil(t, k)
   735  	assert.Equal(t, rest, invalidPem)
   736  	assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
   737  }
   738  
   739  func TestDecryptAndUnmarshalSigningPrivateKey(t *testing.T) {
   740  	passphrase := []byte("DO NOT USE THIS KEY")
   741  	privKey := []byte(`# A good key
   742  -----BEGIN NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
   743  CjwKC0FFUy0yNTYtR0NNEi0IExCAgIABGAEgBCognnjujd67Vsv99p22wfAjQaDT
   744  oCMW1mdjkU3gACKNW4MSXOWR9Sts4C81yk1RUku2gvGKs3TB9LYoklLsIizSYOLl
   745  +Vs//O1T0I1Xbml2XBAROsb/VSoDln/6LMqR4B6fn6B3GOsLBBqRI8daDl9lRMPB
   746  qrlJ69wer3ZUHFXA
   747  -----END NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
   748  `)
   749  	shortKey := []byte(`# A key which, once decrypted, is too short
   750  -----BEGIN NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
   751  CjwKC0FFUy0yNTYtR0NNEi0IExCAgIABGAEgBCoga5h8owMEBWRSMMJKzuUvWce7
   752  k0qlBkQmCxiuLh80MuASW70YcKt8jeEIS2axo2V6zAKA9TSMcCsJW1kDDXEtL/xe
   753  GLF5T7sDl5COp4LU3pGxpV+KoeQ/S3gQCAAcnaOtnJQX+aSDnbO3jCHyP7U9CHbs
   754  rQr3bdH3Oy/WiYU=
   755  -----END NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
   756  `)
   757  	invalidBanner := []byte(`# Invalid banner (not encrypted)
   758  -----BEGIN NEBULA ED25519 PRIVATE KEY-----
   759  bWRp2CTVFhW9HD/qCd28ltDgK3w8VXSeaEYczDWos8sMUBqDb9jP3+NYwcS4lURG
   760  XgLvodMXZJuaFPssp+WwtA==
   761  -----END NEBULA ED25519 PRIVATE KEY-----
   762  `)
   763  	invalidPem := []byte(`# Not a valid PEM format
   764  -BEGIN NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
   765  CjwKC0FFUy0yNTYtR0NNEi0IExCAgIABGAEgBCognnjujd67Vsv99p22wfAjQaDT
   766  oCMW1mdjkU3gACKNW4MSXOWR9Sts4C81yk1RUku2gvGKs3TB9LYoklLsIizSYOLl
   767  +Vs//O1T0I1Xbml2XBAROsb/VSoDln/6LMqR4B6fn6B3GOsLBBqRI8daDl9lRMPB
   768  qrlJ69wer3ZUHFXA
   769  -END NEBULA ED25519 ENCRYPTED PRIVATE KEY-----
   770  `)
   771  
   772  	keyBundle := appendByteSlices(privKey, shortKey, invalidBanner, invalidPem)
   773  
   774  	// Success test case
   775  	curve, k, rest, err := DecryptAndUnmarshalSigningPrivateKey(passphrase, keyBundle)
   776  	assert.Nil(t, err)
   777  	assert.Equal(t, Curve_CURVE25519, curve)
   778  	assert.Len(t, k, 64)
   779  	assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
   780  
   781  	// Fail due to short key
   782  	curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
   783  	assert.EqualError(t, err, "key was not 64 bytes, is invalid ed25519 private key")
   784  	assert.Nil(t, k)
   785  	assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
   786  
   787  	// Fail due to invalid banner
   788  	curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
   789  	assert.EqualError(t, err, "bytes did not contain a proper nebula encrypted Ed25519/ECDSA private key banner")
   790  	assert.Nil(t, k)
   791  	assert.Equal(t, rest, invalidPem)
   792  
   793  	// Fail due to ivalid PEM format, because
   794  	// it's missing the requisite pre-encapsulation boundary.
   795  	curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
   796  	assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
   797  	assert.Nil(t, k)
   798  	assert.Equal(t, rest, invalidPem)
   799  
   800  	// Fail due to invalid passphrase
   801  	curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey([]byte("invalid passphrase"), privKey)
   802  	assert.EqualError(t, err, "invalid passphrase or corrupt private key")
   803  	assert.Nil(t, k)
   804  	assert.Equal(t, rest, []byte{})
   805  }
   806  
   807  func TestEncryptAndMarshalSigningPrivateKey(t *testing.T) {
   808  	// Having proved that decryption works correctly above, we can test the
   809  	// encryption function produces a value which can be decrypted
   810  	passphrase := []byte("passphrase")
   811  	bytes := []byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
   812  	kdfParams := NewArgon2Parameters(64*1024, 4, 3)
   813  	key, err := EncryptAndMarshalSigningPrivateKey(Curve_CURVE25519, bytes, passphrase, kdfParams)
   814  	assert.Nil(t, err)
   815  
   816  	// Verify the "key" can be decrypted successfully
   817  	curve, k, rest, err := DecryptAndUnmarshalSigningPrivateKey(passphrase, key)
   818  	assert.Len(t, k, 64)
   819  	assert.Equal(t, Curve_CURVE25519, curve)
   820  	assert.Equal(t, rest, []byte{})
   821  	assert.Nil(t, err)
   822  
   823  	// EncryptAndMarshalEd25519PrivateKey does not create any errors itself
   824  }
   825  
   826  func TestUnmarshalPrivateKey(t *testing.T) {
   827  	privKey := []byte(`# A good key
   828  -----BEGIN NEBULA X25519 PRIVATE KEY-----
   829  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   830  -----END NEBULA X25519 PRIVATE KEY-----
   831  `)
   832  	privP256Key := []byte(`# A good key
   833  -----BEGIN NEBULA P256 PRIVATE KEY-----
   834  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   835  -----END NEBULA P256 PRIVATE KEY-----
   836  `)
   837  	shortKey := []byte(`# A short key
   838  -----BEGIN NEBULA X25519 PRIVATE KEY-----
   839  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
   840  -----END NEBULA X25519 PRIVATE KEY-----
   841  `)
   842  	invalidBanner := []byte(`# Invalid banner
   843  -----BEGIN NOT A NEBULA PRIVATE KEY-----
   844  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   845  -----END NOT A NEBULA PRIVATE KEY-----
   846  `)
   847  	invalidPem := []byte(`# Not a valid PEM format
   848  -BEGIN NEBULA X25519 PRIVATE KEY-----
   849  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   850  -END NEBULA X25519 PRIVATE KEY-----`)
   851  
   852  	keyBundle := appendByteSlices(privKey, privP256Key, shortKey, invalidBanner, invalidPem)
   853  
   854  	// Success test case
   855  	k, rest, curve, err := UnmarshalPrivateKey(keyBundle)
   856  	assert.Len(t, k, 32)
   857  	assert.Equal(t, rest, appendByteSlices(privP256Key, shortKey, invalidBanner, invalidPem))
   858  	assert.Equal(t, Curve_CURVE25519, curve)
   859  	assert.Nil(t, err)
   860  
   861  	// Success test case
   862  	k, rest, curve, err = UnmarshalPrivateKey(rest)
   863  	assert.Len(t, k, 32)
   864  	assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
   865  	assert.Equal(t, Curve_P256, curve)
   866  	assert.Nil(t, err)
   867  
   868  	// Fail due to short key
   869  	k, rest, curve, err = UnmarshalPrivateKey(rest)
   870  	assert.Nil(t, k)
   871  	assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
   872  	assert.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 private key")
   873  
   874  	// Fail due to invalid banner
   875  	k, rest, curve, err = UnmarshalPrivateKey(rest)
   876  	assert.Nil(t, k)
   877  	assert.Equal(t, rest, invalidPem)
   878  	assert.EqualError(t, err, "bytes did not contain a proper nebula private key banner")
   879  
   880  	// Fail due to ivalid PEM format, because
   881  	// it's missing the requisite pre-encapsulation boundary.
   882  	k, rest, curve, err = UnmarshalPrivateKey(rest)
   883  	assert.Nil(t, k)
   884  	assert.Equal(t, rest, invalidPem)
   885  	assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
   886  }
   887  
   888  func TestUnmarshalEd25519PublicKey(t *testing.T) {
   889  	pubKey := []byte(`# A good key
   890  -----BEGIN NEBULA ED25519 PUBLIC KEY-----
   891  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   892  -----END NEBULA ED25519 PUBLIC KEY-----
   893  `)
   894  	shortKey := []byte(`# A short key
   895  -----BEGIN NEBULA ED25519 PUBLIC KEY-----
   896  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
   897  -----END NEBULA ED25519 PUBLIC KEY-----
   898  `)
   899  	invalidBanner := []byte(`# Invalid banner
   900  -----BEGIN NOT A NEBULA PUBLIC KEY-----
   901  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   902  -----END NOT A NEBULA PUBLIC KEY-----
   903  `)
   904  	invalidPem := []byte(`# Not a valid PEM format
   905  -BEGIN NEBULA ED25519 PUBLIC KEY-----
   906  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   907  -END NEBULA ED25519 PUBLIC KEY-----`)
   908  
   909  	keyBundle := appendByteSlices(pubKey, shortKey, invalidBanner, invalidPem)
   910  
   911  	// Success test case
   912  	k, rest, err := UnmarshalEd25519PublicKey(keyBundle)
   913  	assert.Equal(t, len(k), 32)
   914  	assert.Nil(t, err)
   915  	assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
   916  
   917  	// Fail due to short key
   918  	k, rest, err = UnmarshalEd25519PublicKey(rest)
   919  	assert.Nil(t, k)
   920  	assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
   921  	assert.EqualError(t, err, "key was not 32 bytes, is invalid ed25519 public key")
   922  
   923  	// Fail due to invalid banner
   924  	k, rest, err = UnmarshalEd25519PublicKey(rest)
   925  	assert.Nil(t, k)
   926  	assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519 public key banner")
   927  	assert.Equal(t, rest, invalidPem)
   928  
   929  	// Fail due to ivalid PEM format, because
   930  	// it's missing the requisite pre-encapsulation boundary.
   931  	k, rest, err = UnmarshalEd25519PublicKey(rest)
   932  	assert.Nil(t, k)
   933  	assert.Equal(t, rest, invalidPem)
   934  	assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
   935  }
   936  
   937  func TestUnmarshalX25519PublicKey(t *testing.T) {
   938  	pubKey := []byte(`# A good key
   939  -----BEGIN NEBULA X25519 PUBLIC KEY-----
   940  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   941  -----END NEBULA X25519 PUBLIC KEY-----
   942  `)
   943  	pubP256Key := []byte(`# A good key
   944  -----BEGIN NEBULA P256 PUBLIC KEY-----
   945  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
   946  AAAAAAAAAAAAAAAAAAAAAAA=
   947  -----END NEBULA P256 PUBLIC KEY-----
   948  `)
   949  	shortKey := []byte(`# A short key
   950  -----BEGIN NEBULA X25519 PUBLIC KEY-----
   951  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
   952  -----END NEBULA X25519 PUBLIC KEY-----
   953  `)
   954  	invalidBanner := []byte(`# Invalid banner
   955  -----BEGIN NOT A NEBULA PUBLIC KEY-----
   956  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   957  -----END NOT A NEBULA PUBLIC KEY-----
   958  `)
   959  	invalidPem := []byte(`# Not a valid PEM format
   960  -BEGIN NEBULA X25519 PUBLIC KEY-----
   961  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   962  -END NEBULA X25519 PUBLIC KEY-----`)
   963  
   964  	keyBundle := appendByteSlices(pubKey, pubP256Key, shortKey, invalidBanner, invalidPem)
   965  
   966  	// Success test case
   967  	k, rest, curve, err := UnmarshalPublicKey(keyBundle)
   968  	assert.Equal(t, len(k), 32)
   969  	assert.Nil(t, err)
   970  	assert.Equal(t, rest, appendByteSlices(pubP256Key, shortKey, invalidBanner, invalidPem))
   971  	assert.Equal(t, Curve_CURVE25519, curve)
   972  
   973  	// Success test case
   974  	k, rest, curve, err = UnmarshalPublicKey(rest)
   975  	assert.Equal(t, len(k), 65)
   976  	assert.Nil(t, err)
   977  	assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
   978  	assert.Equal(t, Curve_P256, curve)
   979  
   980  	// Fail due to short key
   981  	k, rest, curve, err = UnmarshalPublicKey(rest)
   982  	assert.Nil(t, k)
   983  	assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
   984  	assert.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 public key")
   985  
   986  	// Fail due to invalid banner
   987  	k, rest, curve, err = UnmarshalPublicKey(rest)
   988  	assert.Nil(t, k)
   989  	assert.EqualError(t, err, "bytes did not contain a proper nebula public key banner")
   990  	assert.Equal(t, rest, invalidPem)
   991  
   992  	// Fail due to ivalid PEM format, because
   993  	// it's missing the requisite pre-encapsulation boundary.
   994  	k, rest, curve, err = UnmarshalPublicKey(rest)
   995  	assert.Nil(t, k)
   996  	assert.Equal(t, rest, invalidPem)
   997  	assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
   998  }
   999  
  1000  // Ensure that upgrading the protobuf library does not change how certificates
  1001  // are marshalled, since this would break signature verification
  1002  func TestMarshalingNebulaCertificateConsistency(t *testing.T) {
  1003  	before := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
  1004  	after := time.Date(2017, time.January, 18, 28, 40, 0, 0, time.UTC)
  1005  	pubKey := []byte("1234567890abcedfghij1234567890ab")
  1006  
  1007  	nc := NebulaCertificate{
  1008  		Details: NebulaCertificateDetails{
  1009  			Name: "testing",
  1010  			Ips: []*net.IPNet{
  1011  				{IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  1012  				{IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  1013  				{IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  1014  			},
  1015  			Subnets: []*net.IPNet{
  1016  				{IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  1017  				{IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  1018  				{IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  1019  			},
  1020  			Groups:    []string{"test-group1", "test-group2", "test-group3"},
  1021  			NotBefore: before,
  1022  			NotAfter:  after,
  1023  			PublicKey: pubKey,
  1024  			IsCA:      false,
  1025  			Issuer:    "1234567890abcedfghij1234567890ab",
  1026  		},
  1027  		Signature: []byte("1234567890abcedfghij1234567890ab"),
  1028  	}
  1029  
  1030  	b, err := nc.Marshal()
  1031  	assert.Nil(t, err)
  1032  	//t.Log("Cert size:", len(b))
  1033  	assert.Equal(t, "0aa2010a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf1220313233343536373839306162636564666768696a313233343536373839306162", fmt.Sprintf("%x", b))
  1034  
  1035  	b, err = proto.Marshal(nc.getRawDetails())
  1036  	assert.Nil(t, err)
  1037  	//t.Log("Raw cert size:", len(b))
  1038  	assert.Equal(t, "0a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf", fmt.Sprintf("%x", b))
  1039  }
  1040  
  1041  func TestNebulaCertificate_Copy(t *testing.T) {
  1042  	ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  1043  	assert.Nil(t, err)
  1044  
  1045  	c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  1046  	assert.Nil(t, err)
  1047  	cc := c.Copy()
  1048  
  1049  	test.AssertDeepCopyEqual(t, c, cc)
  1050  }
  1051  
  1052  func TestUnmarshalNebulaCertificate(t *testing.T) {
  1053  	// Test that we don't panic with an invalid certificate (#332)
  1054  	data := []byte("\x98\x00\x00")
  1055  	_, err := UnmarshalNebulaCertificate(data)
  1056  	assert.EqualError(t, err, "encoded Details was nil")
  1057  }
  1058  
  1059  func newTestCaCert(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  1060  	pub, priv, err := ed25519.GenerateKey(rand.Reader)
  1061  	if before.IsZero() {
  1062  		before = time.Now().Add(time.Second * -60).Round(time.Second)
  1063  	}
  1064  	if after.IsZero() {
  1065  		after = time.Now().Add(time.Second * 60).Round(time.Second)
  1066  	}
  1067  
  1068  	nc := &NebulaCertificate{
  1069  		Details: NebulaCertificateDetails{
  1070  			Name:           "test ca",
  1071  			NotBefore:      time.Unix(before.Unix(), 0),
  1072  			NotAfter:       time.Unix(after.Unix(), 0),
  1073  			PublicKey:      pub,
  1074  			IsCA:           true,
  1075  			InvertedGroups: make(map[string]struct{}),
  1076  		},
  1077  	}
  1078  
  1079  	if len(ips) > 0 {
  1080  		nc.Details.Ips = ips
  1081  	}
  1082  
  1083  	if len(subnets) > 0 {
  1084  		nc.Details.Subnets = subnets
  1085  	}
  1086  
  1087  	if len(groups) > 0 {
  1088  		nc.Details.Groups = groups
  1089  	}
  1090  
  1091  	err = nc.Sign(Curve_CURVE25519, priv)
  1092  	if err != nil {
  1093  		return nil, nil, nil, err
  1094  	}
  1095  	return nc, pub, priv, nil
  1096  }
  1097  
  1098  func newTestCaCertP256(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  1099  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1100  	pub := elliptic.Marshal(elliptic.P256(), priv.PublicKey.X, priv.PublicKey.Y)
  1101  	rawPriv := priv.D.FillBytes(make([]byte, 32))
  1102  
  1103  	if before.IsZero() {
  1104  		before = time.Now().Add(time.Second * -60).Round(time.Second)
  1105  	}
  1106  	if after.IsZero() {
  1107  		after = time.Now().Add(time.Second * 60).Round(time.Second)
  1108  	}
  1109  
  1110  	nc := &NebulaCertificate{
  1111  		Details: NebulaCertificateDetails{
  1112  			Name:           "test ca",
  1113  			NotBefore:      time.Unix(before.Unix(), 0),
  1114  			NotAfter:       time.Unix(after.Unix(), 0),
  1115  			PublicKey:      pub,
  1116  			IsCA:           true,
  1117  			Curve:          Curve_P256,
  1118  			InvertedGroups: make(map[string]struct{}),
  1119  		},
  1120  	}
  1121  
  1122  	if len(ips) > 0 {
  1123  		nc.Details.Ips = ips
  1124  	}
  1125  
  1126  	if len(subnets) > 0 {
  1127  		nc.Details.Subnets = subnets
  1128  	}
  1129  
  1130  	if len(groups) > 0 {
  1131  		nc.Details.Groups = groups
  1132  	}
  1133  
  1134  	err = nc.Sign(Curve_P256, rawPriv)
  1135  	if err != nil {
  1136  		return nil, nil, nil, err
  1137  	}
  1138  	return nc, pub, rawPriv, nil
  1139  }
  1140  
  1141  func newTestCert(ca *NebulaCertificate, key []byte, before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  1142  	issuer, err := ca.Sha256Sum()
  1143  	if err != nil {
  1144  		return nil, nil, nil, err
  1145  	}
  1146  
  1147  	if before.IsZero() {
  1148  		before = time.Now().Add(time.Second * -60).Round(time.Second)
  1149  	}
  1150  	if after.IsZero() {
  1151  		after = time.Now().Add(time.Second * 60).Round(time.Second)
  1152  	}
  1153  
  1154  	if len(groups) == 0 {
  1155  		groups = []string{"test-group1", "test-group2", "test-group3"}
  1156  	}
  1157  
  1158  	if len(ips) == 0 {
  1159  		ips = []*net.IPNet{
  1160  			{IP: net.ParseIP("10.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  1161  			{IP: net.ParseIP("10.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  1162  			{IP: net.ParseIP("10.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  1163  		}
  1164  	}
  1165  
  1166  	if len(subnets) == 0 {
  1167  		subnets = []*net.IPNet{
  1168  			{IP: net.ParseIP("9.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  1169  			{IP: net.ParseIP("9.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  1170  			{IP: net.ParseIP("9.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  1171  		}
  1172  	}
  1173  
  1174  	var pub, rawPriv []byte
  1175  
  1176  	switch ca.Details.Curve {
  1177  	case Curve_CURVE25519:
  1178  		pub, rawPriv = x25519Keypair()
  1179  	case Curve_P256:
  1180  		pub, rawPriv = p256Keypair()
  1181  	default:
  1182  		return nil, nil, nil, fmt.Errorf("unknown curve: %v", ca.Details.Curve)
  1183  	}
  1184  
  1185  	nc := &NebulaCertificate{
  1186  		Details: NebulaCertificateDetails{
  1187  			Name:           "testing",
  1188  			Ips:            ips,
  1189  			Subnets:        subnets,
  1190  			Groups:         groups,
  1191  			NotBefore:      time.Unix(before.Unix(), 0),
  1192  			NotAfter:       time.Unix(after.Unix(), 0),
  1193  			PublicKey:      pub,
  1194  			IsCA:           false,
  1195  			Curve:          ca.Details.Curve,
  1196  			Issuer:         issuer,
  1197  			InvertedGroups: make(map[string]struct{}),
  1198  		},
  1199  	}
  1200  
  1201  	err = nc.Sign(ca.Details.Curve, key)
  1202  	if err != nil {
  1203  		return nil, nil, nil, err
  1204  	}
  1205  
  1206  	return nc, pub, rawPriv, nil
  1207  }
  1208  
  1209  func x25519Keypair() ([]byte, []byte) {
  1210  	privkey := make([]byte, 32)
  1211  	if _, err := io.ReadFull(rand.Reader, privkey); err != nil {
  1212  		panic(err)
  1213  	}
  1214  
  1215  	pubkey, err := curve25519.X25519(privkey, curve25519.Basepoint)
  1216  	if err != nil {
  1217  		panic(err)
  1218  	}
  1219  
  1220  	return pubkey, privkey
  1221  }
  1222  
  1223  func p256Keypair() ([]byte, []byte) {
  1224  	privkey, err := ecdh.P256().GenerateKey(rand.Reader)
  1225  	if err != nil {
  1226  		panic(err)
  1227  	}
  1228  	pubkey := privkey.PublicKey()
  1229  	return pubkey.Bytes(), privkey.Bytes()
  1230  }