...

Source file src/github.com/lestrrat-go/jwx/jwk/okp.go

Documentation: github.com/lestrrat-go/jwx/jwk

     1  package jwk
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/ed25519"
     7  	"fmt"
     8  
     9  	"github.com/lestrrat-go/blackmagic"
    10  	"github.com/lestrrat-go/jwx/internal/base64"
    11  	"github.com/lestrrat-go/jwx/jwa"
    12  	"github.com/lestrrat-go/jwx/x25519"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  func (k *okpPublicKey) FromRaw(rawKeyIf interface{}) error {
    17  	k.mu.Lock()
    18  	defer k.mu.Unlock()
    19  
    20  	var crv jwa.EllipticCurveAlgorithm
    21  	switch rawKey := rawKeyIf.(type) {
    22  	case ed25519.PublicKey:
    23  		k.x = rawKey
    24  		crv = jwa.Ed25519
    25  		k.crv = &crv
    26  	case x25519.PublicKey:
    27  		k.x = rawKey
    28  		crv = jwa.X25519
    29  		k.crv = &crv
    30  	default:
    31  		return errors.Errorf(`unknown key type %T`, rawKeyIf)
    32  	}
    33  
    34  	return nil
    35  }
    36  
    37  func (k *okpPrivateKey) FromRaw(rawKeyIf interface{}) error {
    38  	k.mu.Lock()
    39  	defer k.mu.Unlock()
    40  
    41  	var crv jwa.EllipticCurveAlgorithm
    42  	switch rawKey := rawKeyIf.(type) {
    43  	case ed25519.PrivateKey:
    44  		k.d = rawKey.Seed()
    45  		k.x = rawKey.Public().(ed25519.PublicKey) //nolint:forcetypeassert
    46  		crv = jwa.Ed25519
    47  		k.crv = &crv
    48  	case x25519.PrivateKey:
    49  		k.d = rawKey.Seed()
    50  		k.x = rawKey.Public().(x25519.PublicKey) //nolint:forcetypeassert
    51  		crv = jwa.X25519
    52  		k.crv = &crv
    53  	default:
    54  		return errors.Errorf(`unknown key type %T`, rawKeyIf)
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  func buildOKPPublicKey(alg jwa.EllipticCurveAlgorithm, xbuf []byte) (interface{}, error) {
    61  	switch alg {
    62  	case jwa.Ed25519:
    63  		return ed25519.PublicKey(xbuf), nil
    64  	case jwa.X25519:
    65  		return x25519.PublicKey(xbuf), nil
    66  	default:
    67  		return nil, errors.Errorf(`invalid curve algorithm %s`, alg)
    68  	}
    69  }
    70  
    71  // Raw returns the EC-DSA public key represented by this JWK
    72  func (k *okpPublicKey) Raw(v interface{}) error {
    73  	k.mu.RLock()
    74  	defer k.mu.RUnlock()
    75  
    76  	pubk, err := buildOKPPublicKey(k.Crv(), k.x)
    77  	if err != nil {
    78  		return errors.Wrap(err, `failed to build public key`)
    79  	}
    80  
    81  	return blackmagic.AssignIfCompatible(v, pubk)
    82  }
    83  
    84  func buildOKPPrivateKey(alg jwa.EllipticCurveAlgorithm, xbuf []byte, dbuf []byte) (interface{}, error) {
    85  	switch alg {
    86  	case jwa.Ed25519:
    87  		ret := ed25519.NewKeyFromSeed(dbuf)
    88  		//nolint:forcetypeassert
    89  		if !bytes.Equal(xbuf, ret.Public().(ed25519.PublicKey)) {
    90  			return nil, errors.Errorf(`invalid x value given d value`)
    91  		}
    92  		return ret, nil
    93  	case jwa.X25519:
    94  		ret, err := x25519.NewKeyFromSeed(dbuf)
    95  		if err != nil {
    96  			return nil, errors.Wrap(err, `unable to construct x25519 private key from seed`)
    97  		}
    98  		//nolint:forcetypeassert
    99  		if !bytes.Equal(xbuf, ret.Public().(x25519.PublicKey)) {
   100  			return nil, errors.Errorf(`invalid x value given d value`)
   101  		}
   102  		return ret, nil
   103  	default:
   104  		return nil, errors.Errorf(`invalid curve algorithm %s`, alg)
   105  	}
   106  }
   107  
   108  func (k *okpPrivateKey) Raw(v interface{}) error {
   109  	k.mu.RLock()
   110  	defer k.mu.RUnlock()
   111  
   112  	privk, err := buildOKPPrivateKey(k.Crv(), k.x, k.d)
   113  	if err != nil {
   114  		return errors.Wrap(err, `failed to build public key`)
   115  	}
   116  
   117  	return blackmagic.AssignIfCompatible(v, privk)
   118  }
   119  
   120  func makeOKPPublicKey(v interface {
   121  	makePairs() []*HeaderPair
   122  }) (Key, error) {
   123  	newKey := NewOKPPublicKey()
   124  
   125  	// Iterate and copy everything except for the bits that should not be in the public key
   126  	for _, pair := range v.makePairs() {
   127  		switch pair.Key {
   128  		case OKPDKey:
   129  			continue
   130  		default:
   131  			//nolint:forcetypeassert
   132  			key := pair.Key.(string)
   133  			if err := newKey.Set(key, pair.Value); err != nil {
   134  				return nil, errors.Wrapf(err, `failed to set field %q`, key)
   135  			}
   136  		}
   137  	}
   138  
   139  	return newKey, nil
   140  }
   141  
   142  func (k *okpPrivateKey) PublicKey() (Key, error) {
   143  	return makeOKPPublicKey(k)
   144  }
   145  
   146  func (k *okpPublicKey) PublicKey() (Key, error) {
   147  	return makeOKPPublicKey(k)
   148  }
   149  
   150  func okpThumbprint(hash crypto.Hash, crv, x string) []byte {
   151  	h := hash.New()
   152  	fmt.Fprint(h, `{"crv":"`)
   153  	fmt.Fprint(h, crv)
   154  	fmt.Fprint(h, `","kty":"OKP","x":"`)
   155  	fmt.Fprint(h, x)
   156  	fmt.Fprint(h, `"}`)
   157  	return h.Sum(nil)
   158  }
   159  
   160  // Thumbprint returns the JWK thumbprint using the indicated
   161  // hashing algorithm, according to RFC 7638 / 8037
   162  func (k okpPublicKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
   163  	k.mu.RLock()
   164  	defer k.mu.RUnlock()
   165  
   166  	return okpThumbprint(
   167  		hash,
   168  		k.Crv().String(),
   169  		base64.EncodeToString(k.x),
   170  	), nil
   171  }
   172  
   173  // Thumbprint returns the JWK thumbprint using the indicated
   174  // hashing algorithm, according to RFC 7638 / 8037
   175  func (k okpPrivateKey) Thumbprint(hash crypto.Hash) ([]byte, error) {
   176  	k.mu.RLock()
   177  	defer k.mu.RUnlock()
   178  
   179  	return okpThumbprint(
   180  		hash,
   181  		k.Crv().String(),
   182  		base64.EncodeToString(k.x),
   183  	), nil
   184  }
   185  

View as plain text