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 PEM encoded PKCS1 or PKCS8 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 return nil, err 95 } 96 } 97 98 var pkey *rsa.PublicKey 99 var ok bool 100 if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { 101 return nil, ErrNotRSAPublicKey 102 } 103 104 return pkey, nil 105} 106