diff --git a/rsa.go b/rsa.go index bb71685..08de8a3 100644 --- a/rsa.go +++ b/rsa.go @@ -4,8 +4,6 @@ import ( "crypto" "crypto/rand" "crypto/rsa" - "crypto/x509" - "encoding/pem" "errors" ) @@ -60,7 +58,7 @@ func (m *SigningMethodRSA) Verify(signingString, signature string, key interface switch k := key.(type) { case []byte: - if rsaKey, err = m.parsePublicKey(k); err != nil { + if rsaKey, err = ParsePublicKeyFromPEM(k); err != nil { return err } case *rsa.PublicKey: @@ -86,7 +84,7 @@ func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, switch k := key.(type) { case []byte: - if rsaKey, err = m.parsePrivateKey(k); err != nil { + if rsaKey, err = ParsePrivateKeyFromPEM(k); err != nil { return "", err } case *rsa.PrivateKey: @@ -105,58 +103,3 @@ func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, return "", err } } - -// Parse PEM encoded PKCS1 or PKCS8 public key -func (m *SigningMethodRSA) parsePublicKey(key []byte) (*rsa.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - if cert, err := x509.ParseCertificate(block.Bytes); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - var pkey *rsa.PublicKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { - return nil, errors.New("Key is not a valid RSA public key") - } - - return pkey, nil -} - -// Parse PEM encoded PKCS1 or PKCS8 private key -func (m *SigningMethodRSA) parsePrivateKey(key []byte) (*rsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") - } - - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - } - - var pkey *rsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, errors.New("Key is not a valid RSA private key") - } - - return pkey, nil -} diff --git a/rsa_test.go b/rsa_test.go index 7bbacf3..c0d7782 100644 --- a/rsa_test.go +++ b/rsa_test.go @@ -81,7 +81,7 @@ func TestRSASign(t *testing.T) { func TestRSAVerifyWithPreParsedPrivateKey(t *testing.T) { key, _ := ioutil.ReadFile("test/sample_key.pub") method := GetSigningMethod("RS256").(*SigningMethodRSA) - parsedKey, err := method.parsePublicKey(key) + parsedKey, err := ParsePublicKeyFromPEM(key) if err != nil { t.Fatal(err) } @@ -96,7 +96,7 @@ func TestRSAVerifyWithPreParsedPrivateKey(t *testing.T) { func TestRSAWithPreParsedPrivateKey(t *testing.T) { key, _ := ioutil.ReadFile("test/sample_key") method := GetSigningMethod("RS256").(*SigningMethodRSA) - parsedKey, err := method.parsePrivateKey(key) + parsedKey, err := ParsePrivateKeyFromPEM(key) if err != nil { t.Fatal(err) } @@ -115,31 +115,30 @@ func TestRSAKeyParsing(t *testing.T) { key, _ := ioutil.ReadFile("test/sample_key") pubKey, _ := ioutil.ReadFile("test/sample_key.pub") badKey := []byte("All your base are belong to key") - method := GetSigningMethod("RS256").(*SigningMethodRSA) // Test parsePrivateKey - if _, e := method.parsePrivateKey(key); e != nil { + if _, e := ParsePrivateKeyFromPEM(key); e != nil { t.Errorf("Failed to parse valid private key: %v", e) } - if k, e := method.parsePrivateKey(pubKey); e == nil { + if k, e := ParsePrivateKeyFromPEM(pubKey); e == nil { t.Errorf("Parsed public key as valid private key: %v", k) } - if k, e := method.parsePrivateKey(badKey); e == nil { + if k, e := ParsePrivateKeyFromPEM(badKey); e == nil { t.Errorf("Parsed invalid key as valid private key: %v", k) } // Test parsePublicKey - if _, e := method.parsePublicKey(pubKey); e != nil { + if _, e := ParsePublicKeyFromPEM(pubKey); e != nil { t.Errorf("Failed to parse valid public key: %v", e) } - if k, e := method.parsePublicKey(key); e == nil { + if k, e := ParsePublicKeyFromPEM(key); e == nil { t.Errorf("Parsed private key as valid public key: %v", k) } - if k, e := method.parsePublicKey(badKey); e == nil { + if k, e := ParsePublicKeyFromPEM(badKey); e == nil { t.Errorf("Parsed invalid key as valid private key: %v", k) } diff --git a/rsa_utils.go b/rsa_utils.go new file mode 100644 index 0000000..f108d76 --- /dev/null +++ b/rsa_utils.go @@ -0,0 +1,63 @@ +package jwt + +import ( + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" +) + +// Parse PEM encoded PKCS1 or PKCS8 private key +func ParsePrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") + } + + var parsedKey interface{} + if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { + if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { + return nil, err + } + } + + var pkey *rsa.PrivateKey + var ok bool + if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { + return nil, errors.New("Key is not a valid RSA private key") + } + + return pkey, nil +} + +// Parse PEM encoded PKCS1 or PKCS8 public key +func ParsePublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") + } + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { + if cert, err := x509.ParseCertificate(block.Bytes); err == nil { + parsedKey = cert.PublicKey + } else { + return nil, err + } + } + + var pkey *rsa.PublicKey + var ok bool + if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { + return nil, errors.New("Key is not a valid RSA public key") + } + + return pkey, nil +}