rsa_utils.go

  1package jwt
  2
  3import (
  4	"crypto/rsa"
  5	"crypto/x509"
  6	"encoding/pem"
  7	"errors"
  8)
  9
 10var (
 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
 17func 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 interface{}
 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.
 47func 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 interface{}
 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
 79func 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 interface{}
 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}