C#

2015-12-21 16 views
23

'da ortak anahtar kullanan RS256 algoritması ile imzalanmış JWT'yi doğrulayarak Tamam, sorduğum sorunun oldukça açık olabileceğini anlıyorum, ancak maalesef bu konuda bilgi eksikliği var ve bu görev benim için oldukça zor görünüyor.C#

OpenID Connect Provider tarafından döndürülen bir kimlik belirtecine (JWT) sahibim. İşte burada:

eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ

Onun başlık ve taşınan bu şekilde deşifre edilir:

{ 
"kty":"RSA", 
"kid":"1e9gdk7", 
"n":"w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ", 
"e":"AQAB" 
} 

Yani, soru tam olarak nasıl C# geçerli: IODC sağlayıcının keşif itibaren

{ 
"kid":"1e9gdk7", 
"alg":"RS256" 
}. 
{ 
"iss": "http://server.example.com", 
"sub": "248289761001", 
"aud": "s6BhdRkqt3", 
"nonce": "n-0S6_WzA2Mj", 
"exp": 1311281970, 
"iat": 1311280970, 
"c_hash": "LDktKdoQak3Pk0cnXxCltA" 
} 

, ben ortak anahtarı (JWK) var Bu JWT'yi, sahip olduğum RS256 algoritması için ortak anahtarı kullanarak doğrulayabilir miyim? Açıkça bu prosedürü açıklayan iyi bir öğretici varsa harika olurdu. Bununla birlikte, System.IdentityModel.Tokens.Jwt'u kullanarak nasıl yapılacağına dair bir örnek de iyi çalışacaktır.

GÜNCELLEME: Ben aşağıda kodu gibi bir şey yapmak gerektiğini, anlıyorum ama SHA256 karma hesaplamak için 'anahtar' almak için hiçbir fikrim yok. jwilleke için

string tokenStr = "eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ"; 
    string[] tokenParts = tokenStr.Split('.'); 

    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
    rsa.ImportParameters(
    new RSAParameters() { 
     Modulus = FromBase64Url("w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ"), 
     Exponent = FromBase64Url("AQAB") 
    }); 

    HMACSHA256 sha = new HMACSHA256(key); 
    byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(tokenParts[0] + '.' + tokenParts[1])); 
    byte[] signature = rsa.Encrypt(hash, false); 
    string strSignature = Base64UrlEncode(signature); 
    if (String.Compare(strSignature, tokenParts[2], false) == 0) 
    return true; 
+0

sen yerine getiren rolü Burada

benim örnek verilerin kesin kodudur? (İstemci, Kaynak Sunucu?) – jwilleke

+0

Bu bir istemci uygulamasıdır. RS256 imzalama algoritmasını kullanan özel bir OIDC sağlayıcısı (üzerinde denetimi yoktur) ile çalışmalıdır. Her şey yolunda gayet iyi çalışıyor ve imza doğrulaması karşılaştığım en son engel. –

+1

Bu yardımcı olur mu? https://msdn.microsoft.com/en-us/library/0h05c7e2(v=vs.110).aspx – jwilleke

cevap

20

sayesinde ben bir çözüm var. Bir JWT'nin RS256 imzasını doğrulamak için RSAPKCS1SignatureDeformatter sınıfını ve VerifySignature yöntemini kullanmanız gerekir. İşte

string tokenStr = "eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ"; 
    string[] tokenParts = tokenStr.Split('.'); 

    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
    rsa.ImportParameters(
    new RSAParameters() { 
     Modulus = FromBase64Url("w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ"), 
     Exponent = FromBase64Url("AQAB") 
    }); 

    SHA256 sha256 = SHA256.Create(); 
    byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(tokenParts[0] + '.' + tokenParts[1])); 

    RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa); 
    rsaDeformatter.SetHashAlgorithm("SHA256"); 
    if (rsaDeformatter.VerifySignature(hash, FromBase64Url(tokenParts[2]))) 
    MessageBox.Show("Signature is verified"); 

//... 
    static byte[] FromBase64Url(string base64Url) 
    { 
    string padded = base64Url.Length % 4 == 0 
     ? base64Url : base64Url + "====".Substring(base64Url.Length % 4); 
    string base64 = padded.Replace("_", "/") 
          .Replace("-", "+"); 
    return Convert.FromBase64String(base64); 
    } 
+0

Sadece System.IdentityModel.Tokens.Jwt' yerine düşük düzeyli yapıları kullanmayı tercih ettiğinizi merak ediyor musunuz? – explunit

+3

Her şeyden önce, 'System.IdentityModel.Tokens.Jwt' belgelerine sahip olmak korkunç ve güncel değil. Bu paketin geçerli sürümü, MSDN'de belgelenenlerden farklı olan diğer API'lere sahiptir. Kullanmayı denedim ve genel olarak benim için çalıştı, ancak bu basit jeton imzası doğrulamasını gerçekleştirmenin bir yolunu bulamadım. –

+0

Ve ikinci nedeni, özel OIDC sağlayıcıları ile çalışacağım ve bunlardan biri için ortak anahtarlar listesini alamam mümkün olması. Bu durumda, 'System.IdentityModel.Tokens.Jwt' ile imkansız olan imzayı doğrulamayı atlaman gerekecek. –

6

doğrulama için IdentityModel.Tokens.Jwt kullanarak bir örnek olduğu:

string tokenStr = "eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ"; 

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
rsa.ImportParameters(
    new RSAParameters() 
    { 
     Modulus = FromBase64Url("w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ"), 
     Exponent = FromBase64Url("AQAB") 
    }); 

var validationParameters = new TokenValidationParameters 
       { 
        RequireExpirationTime = true, 
        RequireSignedTokens = true, 
        ValidateAudience = false, 
        ValidateIssuer = false, 
        ValidateLifetime = false, 
        IssuerSigningKey = new RsaSecurityKey(rsa) 
       }; 

SecurityToken validatedSecurityToken = null; 
var handler = new JwtSecurityTokenHandler(); 
handler.ValidateToken(tokenStr, validationParameters, out validatedSecurityToken); 
JwtSecurityToken validatedJwt = validatedSecurityToken as JwtSecurityToken;