2016-03-23 23 views
6

Ho un token, un file che contiene la chiave pubblica e voglio verificare la firma. Ho provato a verificare la firma in base a this.C# Come verificare la firma JWT?

Tuttavia, decodedCrypto e decodedSignature non corrispondono.

Ecco il mio codice:

public static string Decode(string token, string key, bool verify) 
    { 
     var parts = token.Split('.'); 
     var header = parts[0]; 
     var payload = parts[1]; 
     byte[] crypto = Base64UrlDecode(parts[2]); 

     var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header)); 
     var headerData = JObject.Parse(headerJson); 
     var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload)); 
     var payloadData = JObject.Parse(payloadJson); 

     if (verify) 
     { 
      var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload)); 
      var keyBytes = Encoding.UTF8.GetBytes(key); 
      var algorithm = (string)headerData["alg"]; 
      var signature = HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign); 
      var decodedCrypto = Convert.ToBase64String(crypto); 
      var decodedSignature = Convert.ToBase64String(signature); 

      if (decodedCrypto != decodedSignature) 
      { 
       throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature)); 
      } 
     } 

     return payloadData.ToString(); 
    } 

Sono sicuro che la firma di token è valido. Provo a verificare su https://jwt.io/ e ha dimostrato che la firma è stata verificata. Quindi il problema è l'algoritmo da codificare, decodificare.

C'è qualcuno in grado di risolvere questo problema? L'algoritmo è RS256

enter image description here

risposta

4

Ho finalmente ottenuto una soluzione dal mio collega.

Per coloro che hanno lo stesso problema, provare il mio codice:

public static string Decode(string token, string key, bool verify = true) 
     { 
      string[] parts = token.Split('.'); 
      string header = parts[0]; 
      string payload = parts[1]; 
      byte[] crypto = Base64UrlDecode(parts[2]); 

      string headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header)); 
      JObject headerData = JObject.Parse(headerJson); 

      string payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload)); 
      JObject payloadData = JObject.Parse(payloadJson); 

      if (verify) 
      { 
       var keyBytes = Convert.FromBase64String(key); // your key here 

       AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes); 
       RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter; 
       RSAParameters rsaParameters = new RSAParameters(); 
       rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned(); 
       rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned(); 
       RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 
       rsa.ImportParameters(rsaParameters); 

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

       RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa); 
       rsaDeformatter.SetHashAlgorithm("SHA256"); 
       if (!rsaDeformatter.VerifySignature(hash, FromBase64Url(parts[2]))) 
        throw new ApplicationException(string.Format("Invalid signature")); 
      } 

      return payloadData.ToString(); 
     } 

Funziona per me. L'algoritmo è RS256.

2

Come sull'utilizzo JwtSecurityTokenHandler? potrebbe sembrare qualcosa di simile:

public bool ValidateToken(string token, byte[] secret) 
{ 
    var tokenHandler = new JwtSecurityTokenHandler(); 

    var validationParameters = new TokenValidationParameters 
    { 
     ValidateIssuerSigningKey = true, 
     IssuerSigningToken = new BinarySecretSecurityToken(secret) 
    }; 

    SecurityToken validatedToken; 
    try 
    { 
     tokenHandler.ValidateToken(token, validationParameters, out validatedToken); 
    } 
    catch (Exception) 
    { 
     return false; 
    } 

    return validatedToken != null; 
} 

essere consapevoli non ho ancora testato, ma abbiamo utilizzato un'implementazione simile in uno dei progetti

+0

Che cos'è "BinarySecretSecurityToken" qui? Nessun riferimento qui – anhtv13

+0

@ANguyen: https://msdn.microsoft.com/en-us/library/system.servicemodel.security.tokens.binarysecretsecuritytoken(v=vs.110).aspx – Helikaon

+0

Fa parte della libreria 'IdentityModel' . –

0

byte[] crypto = Base64UrlDecode(parts[2]);

In questa linea si è decodifica base64 firma la parte del token JWT, ma come so che la parte non è codificata in Base64. Si prega di provare questo codice. (Ho commentato linee inutili)

public static string Decode(string token, string key, bool verify) 
{ 
    var parts = token.Split('.'); 
    var header = parts[0]; 
    var payload = parts[1]; 
    // byte[] crypto = Base64UrlDecode(parts[2]); 
    var jwtSignature = parts[2]; 

    var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header)); 
    var headerData = JObject.Parse(headerJson); 
    var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload)); 
    var payloadData = JObject.Parse(payloadJson); 

    if (verify) 
    { 
     var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload)); 
     var keyBytes = Encoding.UTF8.GetBytes(key); 
     var algorithm = (string)headerData["alg"]; 
     var computedJwtSignature = Encoding.UTF8.GetString(HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign)); 
     // var decodedCrypto = Convert.ToBase64String(crypto); 
     // var decodedSignature = Convert.ToBase64String(signature); 

     if (jwtSignature != computedJwtSignature) 
     { 
      throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature)); 
     } 
    } 

    return payloadData.ToString(); 
} 
+0

computedJwtSignature restituisce "{ 3 R4p/ g o 1 G # i" E non corrispondono. Il mio algoritmo è RS256 – anhtv13

+0

Cosa restituisce questa riga?(valore e tipo per favore) 'HashAlgorithms [GetHashAlgorithm (algoritmo)] (keyBytes, bytesToSign)' –

+0

è {byte [32]} – anhtv13

4

So che questo è un vecchio thread, ma avrei potuto recommended di utilizzare this library invece di scrivere da soli. Ha una buona documentazione per iniziare. Sto usando senza problemi.