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 PEM encoded PKCS1 or PKCS8 private 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// Parse 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// Parse PEM encoded PKCS1 or PKCS8 private key protected with password
43func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) {
44	var err error
45
46	// Parse PEM block
47	var block *pem.Block
48	if block, _ = pem.Decode(key); block == nil {
49		return nil, ErrKeyMustBePEMEncoded
50	}
51
52	var parsedKey interface{}
53
54	var blockDecrypted []byte
55	if blockDecrypted, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil {
56		return nil, err
57	}
58
59	if parsedKey, err = x509.ParsePKCS1PrivateKey(blockDecrypted); err != nil {
60		if parsedKey, err = x509.ParsePKCS8PrivateKey(blockDecrypted); err != nil {
61			return nil, err
62		}
63	}
64
65	var pkey *rsa.PrivateKey
66	var ok bool
67	if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok {
68		return nil, ErrNotRSAPrivateKey
69	}
70
71	return pkey, nil
72}
73
74// Parse PEM encoded PKCS1 or PKCS8 public key
75func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) {
76	var err error
77
78	// Parse PEM block
79	var block *pem.Block
80	if block, _ = pem.Decode(key); block == nil {
81		return nil, ErrKeyMustBePEMEncoded
82	}
83
84	// Parse the key
85	var parsedKey interface{}
86	if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
87		if cert, err := x509.ParseCertificate(block.Bytes); err == nil {
88			parsedKey = cert.PublicKey
89		} else {
90			return nil, err
91		}
92	}
93
94	var pkey *rsa.PublicKey
95	var ok bool
96	if pkey, ok = parsedKey.(*rsa.PublicKey); !ok {
97		return nil, ErrNotRSAPublicKey
98	}
99
100	return pkey, nil
101}
102