Skip to content

Commit

Permalink
Added support for RS384 and RS512 signing methods
Browse files Browse the repository at this point in the history
Renamed type SigningMethodRS256 to SigningMethodRSA
Added contstants SigningMethodRS256, SigningMethodRS384, and SigningMethodRS512 to support each of these methods
Added simple tests to support these new methods
  • Loading branch information
dgrijalva committed Jul 5, 2014
1 parent 97430c0 commit 629af62
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 17 deletions.
52 changes: 37 additions & 15 deletions rsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,47 @@ import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"errors"
)

type SigningMethodRS256 struct{}
type SigningMethodRSA struct {
Name string
Hash crypto.Hash
}

var (
SigningMethodRS256 *SigningMethodRSA
SigningMethodRS384 *SigningMethodRSA
SigningMethodRS512 *SigningMethodRSA
)

func init() {
RegisterSigningMethod("RS256", func() SigningMethod {
return new(SigningMethodRS256)
// RS256
SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256}
RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod {
return SigningMethodRS256
})

// RS384
SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384}
RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod {
return SigningMethodRS384
})

// RS512
SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512}
RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod {
return SigningMethodRS512
})
}

func (m *SigningMethodRS256) Alg() string {
return "RS256"
func (m *SigningMethodRSA) Alg() string {
return m.Name
}

func (m *SigningMethodRS256) Verify(signingString, signature string, key []byte) error {
func (m *SigningMethodRSA) Verify(signingString, signature string, key []byte) error {
var err error

// Decode the signature
Expand All @@ -38,30 +60,30 @@ func (m *SigningMethodRS256) Verify(signingString, signature string, key []byte)
}

// Create hasher
hasher := sha256.New()
hasher := m.Hash.New()
hasher.Write([]byte(signingString))

// Verify the signature
return rsa.VerifyPKCS1v15(rsaKey, crypto.SHA256, hasher.Sum(nil), sig)
return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig)
}

// Implements the Sign method from SigningMethod
// For this signing method, must be PEM encoded PKCS1 or PKCS8 RSA private key
func (m *SigningMethodRS256) Sign(signingString string, key []byte) (string, error) {
func (m *SigningMethodRSA) Sign(signingString string, key []byte) (string, error) {
var err error

// Key
// Parse private key
var rsaKey *rsa.PrivateKey
if rsaKey, err = m.parsePrivateKey(key); err != nil {
return "", err
}

// Create the hasher
hasher := sha256.New()
hasher := m.Hash.New()
hasher.Write([]byte(signingString))

// Sign the string and return the encoded bytes
if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, crypto.SHA256, hasher.Sum(nil)); err == nil {
if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil {
return EncodeSegment(sigBytes), nil
} else {
return "", err
Expand All @@ -70,7 +92,7 @@ func (m *SigningMethodRS256) Sign(signingString string, key []byte) (string, err
}

// Parse PEM encoded PKCS1 or PKCS8 public key
func (m *SigningMethodRS256) parsePublicKey(key []byte) (*rsa.PublicKey, error) {
func (m *SigningMethodRSA) parsePublicKey(key []byte) (*rsa.PublicKey, error) {
var err error

// Parse PEM block
Expand Down Expand Up @@ -99,7 +121,7 @@ func (m *SigningMethodRS256) parsePublicKey(key []byte) (*rsa.PublicKey, error)
}

// Parse PEM encoded PKCS1 or PKCS8 private key
func (m *SigningMethodRS256) parsePrivateKey(key []byte) (*rsa.PrivateKey, error) {
func (m *SigningMethodRSA) parsePrivateKey(key []byte) (*rsa.PrivateKey, error) {
var err error

// Parse PEM block
Expand Down
18 changes: 16 additions & 2 deletions rsa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,26 @@ var rsaTestData = []struct {
valid bool
}{
{
"basic: foo => bar",
"Basic RS256",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
"RS256",
map[string]interface{}{"foo": "bar"},
true,
},
{
"Basic RS384",
"eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.W-jEzRfBigtCWsinvVVuldiuilzVdU5ty0MvpLaSaqK9PlAWWlDQ1VIQ_qSKzwL5IXaZkvZFJXT3yL3n7OUVu7zCNJzdwznbC8Z-b0z2lYvcklJYi2VOFRcGbJtXUqgjk2oGsiqUMUMOLP70TTefkpsgqDxbRh9CDUfpOJgW-dU7cmgaoswe3wjUAUi6B6G2YEaiuXC0XScQYSYVKIzgKXJV8Zw-7AN_DBUI4GkTpsvQ9fVVjZM9csQiEXhYekyrKu1nu_POpQonGd8yqkIyXPECNmmqH5jH4sFiF67XhD7_JpkvLziBpI-uh86evBUadmHhb9Otqw3uV3NTaXLzJw",
"RS384",
map[string]interface{}{"foo": "bar"},
true,
},
{
"Basic RS512",
"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.zBlLlmRrUxx4SJPUbV37Q1joRcI9EW13grnKduK3wtYKmDXbgDpF1cZ6B-2Jsm5RB8REmMiLpGms-EjXhgnyh2TSHE-9W2gA_jvshegLWtwRVDX40ODSkTb7OVuaWgiy9y7llvcknFBTIg-FnVPVpXMmeV_pvwQyhaz1SSwSPrDyxEmksz1hq7YONXhXPpGaNbMMeDTNP_1oj8DZaqTIL9TwV8_1wb2Odt_Fy58Ke2RVFijsOLdnyEAjt2n9Mxihu9i3PhNBkkxa2GbnXBfq3kzvZ_xxGGopLdHhJjcGWXO-NiwI9_tiu14NRv4L2xC0ItD9Yz68v2ZIZEp_DuzwRQ",
"RS512",
map[string]interface{}{"foo": "bar"},
true,
},
{
"basic invalid: foo => bar",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
Expand Down Expand Up @@ -68,7 +82,7 @@ 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").(*SigningMethodRS256)
method := GetSigningMethod("RS256").(*SigningMethodRSA)

if _, e := method.parsePrivateKey(key); e != nil {
t.Errorf("Failed to parse valid private key: %v", e)
Expand Down

0 comments on commit 629af62

Please sign in to comment.