J'ai un jeton, un fichier contenant une clé publique et je veux vérifier la signature. J'ai essayé de vérifier la signature sur la base de this .
Cependant, decodedCrypto et decodedSignature ne correspondent pas.
Voici mon code:
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();
}
Je suis sûr que la signature du token est valide. J'essaie de vérifier sur https://jwt.io/ et cela a montré que la signature était vérifiée. Le problème est donc l'algorithme pour encoder, décoder.
Y a-t-il quelqu'un pour résoudre ce problème? L'algorithme est RS256
J'ai finalement obtenu une solution de mon collègue.
Pour ceux qui ont le même problème, essayez mon code:
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();
}
Ça marche pour moi. L'algorithme est RS256.
Je sais que c'est un vieux fil mais je pourrais avoir recommended
à utiliser cette bibliothèque au lieu d'écrire tout seul. Il a une bonne documentation pour commencer. Je l'utilise sans aucun problème.
Que diriez-vous d'utiliser JwtSecurityTokenHandler
? cela pourrait ressembler à ceci:
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;
}
Sachez que je ne l'ai pas testé mais nous avons utilisé une implémentation similaire dans l'un des projets
byte[] crypto = Base64UrlDecode(parts[2]);
Dans cette ligne, vous êtes en train de décoder une partie de signature en base64 du jeton JWT
, mais comme je le sais, cette partie n'est pas codée en base64. Veuillez essayer ce code. (J'ai commenté des lignes inutiles)
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();
}