cert_test.go 46 KB

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