/// <summary> /// Validates user input against stored input. /// </summary> /// <param name="input">Input to compare.</param> /// <param name="reference">Reference password.</param> /// <returns>Whether the passwords match.</returns> public async Task <bool> ValidatePasswordHashAsync(string input, byte[] reference) { var salt = reference.AsSpan(0, SaltSize).ToArray(); var utfinput = AbstractionUtilities.UTF8.GetBytes(input); var output = await this.KeyDeriver.DeriveHashAsync(utfinput, salt, PasswordSize); return(AbstractionUtilities.ConstantTimeEquals(output, reference.AsSpan(SaltSize), PasswordSize)); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddHsts(opts => { opts.Preload = true; opts.IncludeSubDomains = true; opts.MaxAge = TimeSpan.FromDays(365); }); services.AddAntiforgery(x => { x.Cookie.Name = "Rosetta-XSRF-Token"; x.HeaderName = "X-Rosetta-XSRF"; }); services.AddOptions <Data.ConfigurationRoot>() .Bind(this.Configuration) .ValidateDataAnnotations(); services.AddOptions <ConfigurationDatastore>() .Bind(this.Configuration.GetSection("Database")) .ValidateDataAnnotations(); services.AddOptions <ConfigurationCache>() .Bind(this.Configuration.GetSection("Cache")) .ValidateDataAnnotations(); services.AddOptions <ConfigurationHttp>() .Bind(this.Configuration.GetSection("Http")) .ValidateDataAnnotations(); services.AddOptions <ConfigurationHttpProxy>() .Bind(this.Configuration.GetSection("Http:ForwardHeaders")) .ValidateDataAnnotations(); services.AddOptions <ConfigurationAuthentication>() .Bind(this.Configuration.GetSection("Authentication")) .ValidateDataAnnotations(); services.AddOptions <ConfigurationOAuth>() .Bind(this.Configuration.GetSection("Authentication:OAuth")) .ValidateDataAnnotations(); services.AddOptions <ConfigurationSecurity>() .Bind(this.Configuration.GetSection("KeyDerivation")) .ValidateDataAnnotations(); services.AddAuthentication(JwtAuthenticationOptions.SchemeName) .AddScheme <JwtAuthenticationOptions, JwtAuthenticationHandler>(JwtAuthenticationOptions.SchemeName, opts => { }); services.AddAuthorization(); // Configure datastore providers var implSelector = new ImplementationSelector(); services.AddSingleton(implSelector); implSelector.ConfigureCtfConfigurationLoaderProvider("yaml", services); implSelector.ConfigureDatabaseProvider(this.Configuration["Database:Type"], services); implSelector.ConfigureCacheProvider(this.Configuration["Cache:Type"], services); implSelector.ConfigureOAuthProviders(this.Configuration .GetSection("Authentication:OAuth:Providers") .Get <ConfigurationOAuthProvider[]>() .Select(x => x.Type), services); services.AddTransient <UserPreviewRepository>() .AddTransient <ChallengePreviewRepository>() .AddSingleton <OAuthTokenHandler>() .AddSingleton <ActionTokenPairHandler>() .AddSingleton <HttpClient>() .AddSingleton <JwtHandler>() .AddTransient <PasswordHandler>() .AddSingleton <IdGenerator>() .AddTransient <IPasswordHashDeriver, Argon2idHashDeriver>() .AddTransient <IKeyDeriver, Pbkdf2KeyDeriver>() .AddSingleton <EnumDisplayConverter>() .AddTransient <IScoringModel, SlowLogisticDecayScoringModel>() .AddSingleton <OAuthConfigurationProvider>() .AddScoped <OAuthProviderSelector>() .AddScoped <LoginSettingsRepository>() .AddTransient <MfaValidatorService>() .AddScoped <ScoreCalculatorService>() .AddSingleton <ScoreLockService>(); services.AddHostedService <ChallengeBootstrapperService>(); // filters services.AddScoped <ValidRosettaUserFilter>() .AddScoped <OptionalRosettaUserFilter>() .AddScoped <EventNotStartedFilter>() .AddScoped <EventStartedFilter>() .AddScoped <EventNotOverFilter>(); #if !DEBUG services.AddControllers(); foreach (var xsrfType in AbstractionUtilities.FindAntiforgeryFilters()) { services.AddSingleton(xsrfType); } #else services.AddControllersWithViews(); services.AddSpaStaticFiles(cfg => cfg.RootPath = $"{this.SpaConfiguration.Root}/dist"); #endif }