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
This commit is contained in:
Dave Grijalva 2014-07-05 15:34:31 -07:00
parent 97430c0b8b
commit 629af62465
2 changed files with 53 additions and 17 deletions

52
rsa.go
View File

@ -4,25 +4,47 @@ import (
"crypto" "crypto"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/sha256"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors" "errors"
) )
type SigningMethodRS256 struct{} type SigningMethodRSA struct {
Name string
Hash crypto.Hash
}
var (
SigningMethodRS256 *SigningMethodRSA
SigningMethodRS384 *SigningMethodRSA
SigningMethodRS512 *SigningMethodRSA
)
func init() { func init() {
RegisterSigningMethod("RS256", func() SigningMethod { // RS256
return new(SigningMethodRS256) 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 { func (m *SigningMethodRSA) Alg() string {
return "RS256" 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 var err error
// Decode the signature // Decode the signature
@ -38,30 +60,30 @@ func (m *SigningMethodRS256) Verify(signingString, signature string, key []byte)
} }
// Create hasher // Create hasher
hasher := sha256.New() hasher := m.Hash.New()
hasher.Write([]byte(signingString)) hasher.Write([]byte(signingString))
// Verify the signature // 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 // Implements the Sign method from SigningMethod
// For this signing method, must be PEM encoded PKCS1 or PKCS8 RSA private key // 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 var err error
// Key // Parse private key
var rsaKey *rsa.PrivateKey var rsaKey *rsa.PrivateKey
if rsaKey, err = m.parsePrivateKey(key); err != nil { if rsaKey, err = m.parsePrivateKey(key); err != nil {
return "", err return "", err
} }
// Create the hasher // Create the hasher
hasher := sha256.New() hasher := m.Hash.New()
hasher.Write([]byte(signingString)) hasher.Write([]byte(signingString))
// Sign the string and return the encoded bytes // 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 return EncodeSegment(sigBytes), nil
} else { } else {
return "", err return "", err
@ -70,7 +92,7 @@ func (m *SigningMethodRS256) Sign(signingString string, key []byte) (string, err
} }
// Parse PEM encoded PKCS1 or PKCS8 public key // 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 var err error
// Parse PEM block // Parse PEM block
@ -99,7 +121,7 @@ func (m *SigningMethodRS256) parsePublicKey(key []byte) (*rsa.PublicKey, error)
} }
// Parse PEM encoded PKCS1 or PKCS8 private key // 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 var err error
// Parse PEM block // Parse PEM block

View File

@ -14,12 +14,26 @@ var rsaTestData = []struct {
valid bool valid bool
}{ }{
{ {
"basic: foo => bar", "Basic RS256",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg",
"RS256", "RS256",
map[string]interface{}{"foo": "bar"}, map[string]interface{}{"foo": "bar"},
true, 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", "basic invalid: foo => bar",
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", "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") key, _ := ioutil.ReadFile("test/sample_key")
pubKey, _ := ioutil.ReadFile("test/sample_key.pub") pubKey, _ := ioutil.ReadFile("test/sample_key.pub")
badKey := []byte("All your base are belong to key") badKey := []byte("All your base are belong to key")
method := GetSigningMethod("RS256").(*SigningMethodRS256) method := GetSigningMethod("RS256").(*SigningMethodRSA)
if _, e := method.parsePrivateKey(key); e != nil { if _, e := method.parsePrivateKey(key); e != nil {
t.Errorf("Failed to parse valid private key: %v", e) t.Errorf("Failed to parse valid private key: %v", e)