using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Web; namespace TokenJWT { public enum JwtHashAlgorithm { RS256, HS384, HS512, HS256 } public class JsonWebToken { private static Dictionary> HashAlgorithms; static JsonWebToken() { HashAlgorithms = new Dictionary> { { JwtHashAlgorithm.RS256, (key, value) => { using (var sha = new HMACSHA256(key)) { return sha.ComputeHash(value); } } }, { JwtHashAlgorithm.HS384, (key, value) => { using (var sha = new HMACSHA384(key)) { return sha.ComputeHash(value); } } }, { JwtHashAlgorithm.HS512, (key, value) => { using (var sha = new HMACSHA512(key)) { return sha.ComputeHash(value); } } }, { JwtHashAlgorithm.HS256, (key, value) => { using (var sha = new HMACSHA256(key)) { return sha.ComputeHash(value); } } } }; } public static string Encode(object payload, string key, JwtHashAlgorithm algorithm) { return Encode(payload, Encoding.UTF8.GetBytes(key), algorithm); } public static string Encode(object payload, byte[] keyBytes, JwtHashAlgorithm algorithm) { var segments = new List(); var header = new { alg = algorithm.ToString(), typ = "JWT" }; byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None)); byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None)); segments.Add(Base64UrlEncode(headerBytes)); segments.Add(Base64UrlEncode(payloadBytes)); var stringToSign = string.Join(".", segments.ToArray()); var bytesToSign = Encoding.UTF8.GetBytes(stringToSign); byte[] signature = HashAlgorithms[algorithm](keyBytes, bytesToSign); segments.Add(Base64UrlEncode(signature)); var encoding = new System.Text.ASCIIEncoding(); byte[] keyByte1 = encoding.GetBytes("aqF5DsZDGmQ2dWC1QG5R9mHlOdx8aaU8"); var alg1 = new HMACSHA256(keyByte1); var hash1 = alg1.ComputeHash(bytesToSign); var sign = Base64UrlEncode(hash1); return string.Join(".", segments.ToArray()); } public static string Decode(string token, string key) { return Decode(token, key, true); } 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(); } public static void VerifySignature() { string jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJIYlZCZDYyRUNxWWNUTGdyODAwOWlocDhZaUZlcm5BeSIsImV4cCI6MTU4MTYyNjA3NH0.LSRvPniuJVKLkt_w9GePlagptcmIjd11xDhmy1xV7K0"; string[] parts = jwt.Split(".".ToCharArray()); var header = parts[0]; var payload = parts[1]; var signature = parts[2];//Base64UrlEncoded signature from the token byte[] bytesToSign = getBytes(string.Join(".", header, payload,signature)); byte[] secret = getBytes("aqF5DsZDGmQ2dWC1QG5R9mHlOdx8aaU8"); var alg = new HMACSHA256(secret); //var sh_h256 = CryptoJS.HmacSHA256(header + "." + payload, "aqF5DsZDGmQ2dWC1QG5R9mHlOdx8aaU8"); var hash = alg.ComputeHash(bytesToSign); var computedSignature = Base64UrlEncode(hash); string result = "No"; if(signature == computedSignature) { result = "Yes"; } } private static byte[] getBytes(string value) { return Encoding.UTF8.GetBytes(value); } private static JwtHashAlgorithm GetHashAlgorithm(string algorithm) { switch (algorithm) { case "RS256": return JwtHashAlgorithm.RS256; case "HS384": return JwtHashAlgorithm.HS384; case "HS512": return JwtHashAlgorithm.HS512; case "HS256": return JwtHashAlgorithm.HS256; default: throw new InvalidOperationException("Algorithm not supported."); } } // from JWT spec private static string Base64UrlEncode(byte[] input) { var output = Convert.ToBase64String(input); output = output.Split('=')[0]; // Remove any trailing '='s output = output.Replace('+', '-'); // 62nd char of encoding output = output.Replace('/', '_'); // 63rd char of encoding return output; } // from JWT spec private static byte[] Base64UrlDecode(string input) { var output = input; output = output.Replace('-', '+'); // 62nd char of encoding output = output.Replace('_', '/'); // 63rd char of encoding switch (output.Length % 4) // Pad with trailing '='s { case 0: break; // No pad chars in this case case 2: output += "=="; break; // Two pad chars case 3: output += "="; break; // One pad char default: throw new System.Exception("Illegal base64url string!"); } var converted = Convert.FromBase64String(output); // Standard base64 decoder return converted; } } }