rsa_utils.go raw

   1  package jwt
   2  
   3  import (
   4  	"crypto/rsa"
   5  	"crypto/x509"
   6  	"encoding/pem"
   7  	"errors"
   8  )
   9  
  10  var (
  11  	ErrKeyMustBePEMEncoded = errors.New("invalid key: Key must be a PEM encoded PKCS1 or PKCS8 key")
  12  	ErrNotRSAPrivateKey    = errors.New("key is not a valid RSA private key")
  13  	ErrNotRSAPublicKey     = errors.New("key is not a valid RSA public key")
  14  )
  15  
  16  // ParseRSAPrivateKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 private key
  17  func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) {
  18  	var err error
  19  
  20  	// Parse PEM block
  21  	var block *pem.Block
  22  	if block, _ = pem.Decode(key); block == nil {
  23  		return nil, ErrKeyMustBePEMEncoded
  24  	}
  25  
  26  	var parsedKey any
  27  	if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
  28  		if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
  29  			return nil, err
  30  		}
  31  	}
  32  
  33  	var pkey *rsa.PrivateKey
  34  	var ok bool
  35  	if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok {
  36  		return nil, ErrNotRSAPrivateKey
  37  	}
  38  
  39  	return pkey, nil
  40  }
  41  
  42  // ParseRSAPrivateKeyFromPEMWithPassword parses a PEM encoded PKCS1 or PKCS8 private key protected with password
  43  //
  44  // Deprecated: This function is deprecated and should not be used anymore. It uses the deprecated x509.DecryptPEMBlock
  45  // function, which was deprecated since RFC 1423 is regarded insecure by design. Unfortunately, there is no alternative
  46  // in the Go standard library for now. See https://github.com/golang/go/issues/8860.
  47  func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) {
  48  	var err error
  49  
  50  	// Parse PEM block
  51  	var block *pem.Block
  52  	if block, _ = pem.Decode(key); block == nil {
  53  		return nil, ErrKeyMustBePEMEncoded
  54  	}
  55  
  56  	var parsedKey any
  57  
  58  	var blockDecrypted []byte
  59  	if blockDecrypted, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil {
  60  		return nil, err
  61  	}
  62  
  63  	if parsedKey, err = x509.ParsePKCS1PrivateKey(blockDecrypted); err != nil {
  64  		if parsedKey, err = x509.ParsePKCS8PrivateKey(blockDecrypted); err != nil {
  65  			return nil, err
  66  		}
  67  	}
  68  
  69  	var pkey *rsa.PrivateKey
  70  	var ok bool
  71  	if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok {
  72  		return nil, ErrNotRSAPrivateKey
  73  	}
  74  
  75  	return pkey, nil
  76  }
  77  
  78  // ParseRSAPublicKeyFromPEM parses a certificate or a PEM encoded PKCS1 or PKIX public key
  79  func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) {
  80  	var err error
  81  
  82  	// Parse PEM block
  83  	var block *pem.Block
  84  	if block, _ = pem.Decode(key); block == nil {
  85  		return nil, ErrKeyMustBePEMEncoded
  86  	}
  87  
  88  	// Parse the key
  89  	var parsedKey any
  90  	if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
  91  		if cert, err := x509.ParseCertificate(block.Bytes); err == nil {
  92  			parsedKey = cert.PublicKey
  93  		} else {
  94  			if parsedKey, err = x509.ParsePKCS1PublicKey(block.Bytes); err != nil {
  95  				return nil, err
  96  			}
  97  		}
  98  	}
  99  
 100  	var pkey *rsa.PublicKey
 101  	var ok bool
 102  	if pkey, ok = parsedKey.(*rsa.PublicKey); !ok {
 103  		return nil, ErrNotRSAPublicKey
 104  	}
 105  
 106  	return pkey, nil
 107  }
 108