From 629af62465e3c5e2ab5c5e97d22d4e593ab0a9bc Mon Sep 17 00:00:00 2001 From: Dave Grijalva Date: Sat, 5 Jul 2014 15:34:31 -0700 Subject: [PATCH] Added support for RS384 and RS512 signing methods 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 --- rsa.go | 52 +++++++++++++++++++++++++++++++++++++--------------- rsa_test.go | 18 ++++++++++++++++-- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/rsa.go b/rsa.go index 33b26cc..f30c6c9 100644 --- a/rsa.go +++ b/rsa.go @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/rsa_test.go b/rsa_test.go index c71c98f..158dcb9 100644 --- a/rsa_test.go +++ b/rsa_test.go @@ -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", @@ -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)