github.com/pion/dtls/v2@v2.2.12/pkg/crypto/elliptic/elliptic.go (about)

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