public static string valueOf(JWTAlgorithm jWTAlgorithm, Error error) { switch (jWTAlgorithm) { case JWTAlgorithm.HS256: return("HS256"); case JWTAlgorithm.HS512: return("HS512"); case JWTAlgorithm.RS256: return("RS256"); case JWTAlgorithm.RS512: return("RS512"); case JWTAlgorithm.ES256: return("ES256"); case JWTAlgorithm.ES384: return("ES384"); case JWTAlgorithm.ES512: return("ES512"); default: error.setError("JA001", "Unrecognized algorithm"); return("Unrecognized algorithm"); } }
/// <summary> /// Hash a token signature /// </summary> /// <param name="algorithm"><see cref="JWTAlgorithm"/> to encrypt</param> /// <param name="keyBytes">Key</param> /// <param name="payloadBytes">Payload</param> /// <returns>Hashed Signature</returns> public static byte[] HashSignature(JWTAlgorithm algorithm, byte[] keyBytes, byte[] payloadBytes) { byte[] hashedBytes = null; switch (algorithm) { case JWTAlgorithm.HS256: HMACSHA256 encHMAC256 = new HMACSHA256(keyBytes); hashedBytes = encHMAC256.ComputeHash(payloadBytes); break; case JWTAlgorithm.HS384: HMACSHA384 encHMAC384 = new HMACSHA384(keyBytes); hashedBytes = encHMAC384.ComputeHash(payloadBytes); break; case JWTAlgorithm.HS512: HMACSHA512 encHMAC512 = new HMACSHA512(keyBytes); hashedBytes = encHMAC512.ComputeHash(payloadBytes); break; default: // temporary impementation of a default encryption goto case JWTAlgorithm.HS256; } return(hashedBytes); }
internal static SigningCredentials getSigningCredentials(JWTAlgorithm jWTAlgorithm, SecurityKey key, Error error) { switch (jWTAlgorithm) { case JWTAlgorithm.HS256: return(new SigningCredentials(key, SecurityAlgorithms.HmacSha256)); case JWTAlgorithm.HS512: return(new SigningCredentials(key, SecurityAlgorithms.HmacSha512)); case JWTAlgorithm.RS256: return(new SigningCredentials(key, SecurityAlgorithms.RsaSha256)); case JWTAlgorithm.RS512: return(new SigningCredentials(key, SecurityAlgorithms.RsaSha512)); case JWTAlgorithm.ES256: return(new SigningCredentials(key, SecurityAlgorithms.EcdsaSha256)); case JWTAlgorithm.ES384: return(new SigningCredentials(key, SecurityAlgorithms.EcdsaSha384)); case JWTAlgorithm.ES512: return(new SigningCredentials(key, SecurityAlgorithms.EcdsaSha512)); default: error.setError("JA003", "Unknown algorithm"); return(null); } }
public static bool isPrivate(JWTAlgorithm jWTAlgorithm) { switch (jWTAlgorithm) { case JWTAlgorithm.RS256: case JWTAlgorithm.RS512: case JWTAlgorithm.ES256: case JWTAlgorithm.ES384: case JWTAlgorithm.ES512: return(true); default: return(false); } }
private static JWTHeader GetHeader(VssSigningCredentials credentials, bool allowExpired) { //note credentials are allowed to be null here, see ValidateSigningCredentials JWTHeader header = new JWTHeader(); JWTAlgorithm alg = JsonWebTokenUtilities.ValidateSigningCredentials(credentials, allowExpired); header.Algorithm = alg; if (alg != JWTAlgorithm.None) { // Some signing credentials may need to set headers for the JWT var jwtHeaderProvider = credentials as IJsonWebTokenHeaderProvider; if (jwtHeaderProvider != null) { jwtHeaderProvider.SetHeaders(header); } } return(header); }
//if we alread have the alg, we assume that the creds have been validated already, //to save the expense of validating twice in the create function... private static byte[] GetSignature(JWTHeader header, JWTPayload payload, JWTAlgorithm alg, VssSigningCredentials signingCredentials) { if (alg == JWTAlgorithm.None) { return(null); } ArgumentUtility.CheckForNull(header, nameof(header)); ArgumentUtility.CheckForNull(payload, nameof(payload)); string encoding = string.Format("{0}.{1}", header.JsonEncode(), payload.JsonEncode()); byte[] bytes = Encoding.UTF8.GetBytes(encoding); switch (alg) { case JWTAlgorithm.HS256: case JWTAlgorithm.RS256: return(signingCredentials.SignData(bytes)); default: throw new InvalidOperationException(); } }
private static byte[] GetSignature(JWTHeader header, JWTPayload payload, VssSigningCredentials credentials, bool allowExpired) { JWTAlgorithm alg = JsonWebTokenUtilities.ValidateSigningCredentials(credentials, allowExpired); return(GetSignature(header, payload, alg, credentials)); }
/// <summary> /// Verifies asynchronously if this token is valid using the token signature /// </summary> /// <returns><see cref="bool"/></returns> public static Task <bool> VerifyAsync(string token, string key) { var task = Task.Run(() => { DateTime startTime = DateTime.Now; if (string.IsNullOrEmpty(token)) { throw new ArgumentNullException("Token"); } if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("Key"); } string[] parts = token.Split('.'); if (parts.Count() < 3) { throw new ArgumentException("Token not correcty constructed."); } string headerJson = parts[0].Base64UrlDecode().GetString(); string payloadJson = parts[1].Base64UrlDecode().GetString(); string signatureJson = parts[2].Base64UrlDecode().GetString(); Dictionary <string, object> header = null; try { header = JsonConvert.DeserializeObject <Dictionary <string, object> >(headerJson); if (header == null) { return(false); } } catch { return(false); } JWTAlgorithm algorithm = JWTAlgorithm.Empty; if (header.ContainsKey("alg")) { Enum.TryParse((string)header["alg"], out algorithm); } else { return(false); } string signatureDecoded = HashSignature(algorithm, key.GetBytes(), $"{parts[0]}.{parts[1]}".GetBytes()).Base64UrlEncode(); TimeSpan ts = DateTime.Now.Subtract(startTime); Console.WriteLine($"=> Verifying took: {ts.Seconds}"); if (signatureDecoded == parts[2]) { return(true); } return(false); }); return(task); }
public string DoCreate(string algorithm, PrivateClaims privateClaims, JWTOptions options) { this.error.cleanError(); if (options.HasError()) { this.error = options.GetError(); return(""); } JWTAlgorithm alg = JWTAlgorithmUtils.getJWTAlgorithm(algorithm, this.error); if (this.HasError()) { return(""); } if (this.HasError()) { return(""); } /***Hack to support 1024 RSA key lengths - BEGIN***/ AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap["RS256"] = 1024; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap["RS512"] = 1024; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap["RS384"] = 1024; /***Hack to support 1024 RSA key lengths - END***/ /***Hack to support 192 ECDSA key lengths - BEGIN***/ AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap["ES256"] = 112; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap["ES512"] = 112; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap["ES384"] = 112; /***Hack to support 192 ECDSA key lengths - END***/ JwtPayload payload = doBuildPayload(privateClaims, options); SecurityKey genericKey = null; if (JWTAlgorithmUtils.isPrivate(alg)) { PrivateKeyManager key = options.GetPrivateKey(); if (key.HasError()) { this.error = key.GetError(); return(""); } if (SecurityUtils.compareStrings(key.getPrivateKeyAlgorithm(), "RSA")) { try { genericKey = new RsaSecurityKey((RSA)key.getPrivateKeyForJWT()); }catch (Exception) { this.error = key.GetError(); return(""); } } else if (SecurityUtils.compareStrings(key.getPrivateKeyAlgorithm(), "ECDSA")) { try { genericKey = new ECDsaSecurityKey((ECDsa)key.getPrivateKeyForJWT()); } catch (Exception) { this.error = key.GetError(); return(""); } } else { this.error.setError("JW012", "Not recognized key algorithm"); return(""); } if (genericKey == null) { this.error = key.GetError(); return(""); } } else { SymmetricSecurityKey symKey = new SymmetricSecurityKey(options.getSecret()); genericKey = symKey; } SigningCredentials signingCredentials = JWTAlgorithmUtils.getSigningCredentials(alg, genericKey, this.error); if (this.HasError()) { return(""); } string signedJwt = ""; try { JwtHeader header = new JwtHeader(signingCredentials); if (!options.GetHeaderParameters().IsEmpty()) { AddHeaderParameters(header, options); } JwtSecurityToken secToken = new JwtSecurityToken(header, payload); JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); signedJwt = handler.WriteToken(secToken); } catch (Exception e) { this.error.setError("JW003", "key size: " + /*genericKey.KeySize.ToString()*/ e.Message + e.StackTrace); return(""); } return(signedJwt); }
private bool DoVerify(string token, string expectedAlgorithm, PrivateClaims privateClaims, JWTOptions options, bool verifyClaims, bool verifyRegClaims) { this.error.cleanError(); if (options.HasError()) { this.error = options.GetError(); return(false); } JWTAlgorithm expectedJWTAlgorithm = JWTAlgorithmUtils.getJWTAlgorithm(expectedAlgorithm, this.error); if (this.HasError()) { return(false); } /***Hack to support 1024 RSA key lengths - BEGIN***/ AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["RS256"] = 1024; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["RS512"] = 1024; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["RS384"] = 1024; /***Hack to support 1024 RSA key lengths - END***/ /***Hack to support 192 ECDSA key lengths - BEGIN***/ AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["EcdsaSha256"] = 112; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["EcdsaSha512"] = 112; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["EcdsaSha384"] = 112; /***Hack to support 192 ECDSA key lengths - END***/ /***Hack to support 192 ECDSA key lengths - BEGIN***/ AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["ES256"] = 112; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["ES512"] = 112; AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap["ES384"] = 112; /***Hack to support 192 ECDSA key lengths - END***/ JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = new JwtSecurityToken(token); if (isRevoqued(jwtToken, options)) { return(false); } if (verifyRegClaims) { if (!validateRegisteredClaims(jwtToken, options)) { return(false); } } if (verifyClaims) { if (!verifyPrivateClaims(jwtToken, privateClaims, options) || !VerifyHeader(jwtToken, options)) { return(false); } } //if validates all registered claims and it is not on revocation list TokenValidationParameters parms = new TokenValidationParameters(); parms.ValidateLifetime = false; parms.ValidateAudience = false; parms.ValidateIssuer = false; parms.ValidateActor = false; JWTAlgorithm alg = JWTAlgorithmUtils.getJWTAlgorithm_forVerification(jwtToken.Header.Alg, this.error); if (this.HasError()) { return(false); } if (JWTAlgorithmUtils.getJWTAlgorithm(jwtToken.Header.Alg, this.error) != expectedJWTAlgorithm || this.HasError()) { this.error.setError("JW008", "Expected algorithm does not match token algorithm"); return(false); } SecurityKey genericKey = null; if (JWTAlgorithmUtils.isPrivate(alg)) { CertificateX509 cert = options.GetCertificate(); if (cert.HasError()) { this.error = cert.GetError(); return(false); } if (SecurityUtils.compareStrings(cert.getPublicKeyAlgorithm(), "RSA")) { try { genericKey = new RsaSecurityKey((RSA)cert.getPublicKeyJWT()); } catch (Exception) { this.error = cert.GetError(); return(false); } } else if (SecurityUtils.compareStrings(cert.getPublicKeyAlgorithm(), "ECDSA")) { try { genericKey = new ECDsaSecurityKey((ECDsa)cert.getPublicKeyJWT()); } catch (Exception) { this.error = cert.GetError(); return(false); } } else { this.error.setError("JW013", "Not recognized key algorithm"); return(false); } } else { SymmetricSecurityKey symKey = new SymmetricSecurityKey(options.getSecret()); genericKey = symKey; } genericKey.KeyId = "256"; SigningCredentials signingCredentials = JWTAlgorithmUtils.getSigningCredentials(alg, genericKey, this.error); parms.IssuerSigningKey = genericKey; SecurityToken validatedToken; try { handler.ValidateToken(token, parms, out validatedToken); } catch (Exception e) { this.error.setError("JW004", e.Message); return(false); } return(true); }