elliptic.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. // Package elliptic provides elliptic curve cryptography for DTLS
  4. package elliptic
  5. import (
  6. "crypto/elliptic"
  7. "crypto/rand"
  8. "errors"
  9. "fmt"
  10. "golang.org/x/crypto/curve25519"
  11. )
  12. var errInvalidNamedCurve = errors.New("invalid named curve")
  13. // CurvePointFormat is used to represent the IANA registered curve points
  14. //
  15. // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
  16. type CurvePointFormat byte
  17. // CurvePointFormat enums
  18. const (
  19. CurvePointFormatUncompressed CurvePointFormat = 0
  20. )
  21. // Keypair is a Curve with a Private/Public Keypair
  22. type Keypair struct {
  23. Curve Curve
  24. PublicKey []byte
  25. PrivateKey []byte
  26. }
  27. // CurveType is used to represent the IANA registered curve types for TLS
  28. //
  29. // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-10
  30. type CurveType byte
  31. // CurveType enums
  32. const (
  33. CurveTypeNamedCurve CurveType = 0x03
  34. )
  35. // CurveTypes returns all known curves
  36. func CurveTypes() map[CurveType]struct{} {
  37. return map[CurveType]struct{}{
  38. CurveTypeNamedCurve: {},
  39. }
  40. }
  41. // Curve is used to represent the IANA registered curves for TLS
  42. //
  43. // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
  44. type Curve uint16
  45. // Curve enums
  46. const (
  47. P256 Curve = 0x0017
  48. P384 Curve = 0x0018
  49. X25519 Curve = 0x001d
  50. )
  51. func (c Curve) String() string {
  52. switch c {
  53. case P256:
  54. return "P-256"
  55. case P384:
  56. return "P-384"
  57. case X25519:
  58. return "X25519"
  59. }
  60. return fmt.Sprintf("%#x", uint16(c))
  61. }
  62. // Curves returns all curves we implement
  63. func Curves() map[Curve]bool {
  64. return map[Curve]bool{
  65. X25519: true,
  66. P256: true,
  67. P384: true,
  68. }
  69. }
  70. // GenerateKeypair generates a keypair for the given Curve
  71. func GenerateKeypair(c Curve) (*Keypair, error) {
  72. switch c { //nolint:revive
  73. case X25519:
  74. tmp := make([]byte, 32)
  75. if _, err := rand.Read(tmp); err != nil {
  76. return nil, err
  77. }
  78. var public, private [32]byte
  79. copy(private[:], tmp)
  80. curve25519.ScalarBaseMult(&public, &private)
  81. return &Keypair{X25519, public[:], private[:]}, nil
  82. case P256:
  83. return ellipticCurveKeypair(P256, elliptic.P256(), elliptic.P256())
  84. case P384:
  85. return ellipticCurveKeypair(P384, elliptic.P384(), elliptic.P384())
  86. default:
  87. return nil, errInvalidNamedCurve
  88. }
  89. }
  90. func ellipticCurveKeypair(nc Curve, c1, c2 elliptic.Curve) (*Keypair, error) {
  91. privateKey, x, y, err := elliptic.GenerateKey(c1, rand.Reader)
  92. if err != nil {
  93. return nil, err
  94. }
  95. return &Keypair{nc, elliptic.Marshal(c2, x, y), privateKey}, nil
  96. }