mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 07:36:14 -05:00
[PM-3565] Enforce higher minimum KDF (#3304)
Extract KDF logic into a new Range class. Increase minimum iterations for PBKDF.
This commit is contained in:
@ -2,11 +2,10 @@
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Auth.Models.Request.Accounts;
|
||||
|
||||
public class SetKeyConnectorKeyRequestModel : IValidatableObject
|
||||
public class SetKeyConnectorKeyRequestModel
|
||||
{
|
||||
[Required]
|
||||
public string Key { get; set; }
|
||||
@ -31,9 +30,4 @@ public class SetKeyConnectorKeyRequestModel : IValidatableObject
|
||||
Keys.ToUser(existingUser);
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
return KdfSettingsValidator.Validate(Kdf, KdfIterations, KdfMemory, KdfParallelism);
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,10 @@
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.Api.Auth.Models.Request.Accounts;
|
||||
|
||||
public class SetPasswordRequestModel : IValidatableObject
|
||||
public class SetPasswordRequestModel
|
||||
{
|
||||
[Required]
|
||||
[StringLength(300)]
|
||||
@ -35,9 +34,4 @@ public class SetPasswordRequestModel : IValidatableObject
|
||||
Keys?.ToUser(existingUser);
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
return KdfSettingsValidator.Validate(Kdf, KdfIterations, KdfMemory, KdfParallelism);
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ public class AccountsController : Controller
|
||||
kdfInformation = new UserKdfInformation
|
||||
{
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = 100000,
|
||||
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
|
||||
};
|
||||
}
|
||||
return new PreloginResponseModel(kdfInformation);
|
||||
|
@ -31,6 +31,45 @@ public static class Constants
|
||||
public const string IdentityProvider = "bitwarden";
|
||||
}
|
||||
|
||||
public static class AuthConstants
|
||||
{
|
||||
public static readonly RangeConstant PBKDF2_ITERATIONS = new(600_000, 2_000_000, 600_000);
|
||||
|
||||
public static readonly RangeConstant ARGON2_ITERATIONS = new(2, 10, 3);
|
||||
public static readonly RangeConstant ARGON2_MEMORY = new(15, 1024, 64);
|
||||
public static readonly RangeConstant ARGON2_PARALLELISM = new(1, 16, 4);
|
||||
|
||||
}
|
||||
|
||||
public class RangeConstant
|
||||
{
|
||||
public int Default { get; }
|
||||
public int Min { get; }
|
||||
public int Max { get; }
|
||||
|
||||
public RangeConstant(int min, int max, int defaultValue)
|
||||
{
|
||||
Default = defaultValue;
|
||||
Min = min;
|
||||
Max = max;
|
||||
|
||||
if (Min > Max)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"{Min} is larger than {Max}.");
|
||||
}
|
||||
|
||||
if (!InsideRange(defaultValue))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"{Default} is outside allowed range of {Min}-{Max}.");
|
||||
}
|
||||
}
|
||||
|
||||
public bool InsideRange(int number)
|
||||
{
|
||||
return Min <= number && number <= Max;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TokenPurposes
|
||||
{
|
||||
public const string LinkSso = "LinkSso";
|
||||
|
@ -10,23 +10,23 @@ public static class KdfSettingsValidator
|
||||
switch (kdfType)
|
||||
{
|
||||
case KdfType.PBKDF2_SHA256:
|
||||
if (kdfIterations < 5000 || kdfIterations > 2_000_000)
|
||||
if (!AuthConstants.PBKDF2_ITERATIONS.InsideRange(kdfIterations))
|
||||
{
|
||||
yield return new ValidationResult("KDF iterations must be between 5000 and 2000000.");
|
||||
yield return new ValidationResult($"KDF iterations must be between {AuthConstants.PBKDF2_ITERATIONS.Min} and {AuthConstants.PBKDF2_ITERATIONS.Max}.");
|
||||
}
|
||||
break;
|
||||
case KdfType.Argon2id:
|
||||
if (kdfIterations <= 0)
|
||||
if (!AuthConstants.ARGON2_ITERATIONS.InsideRange(kdfIterations))
|
||||
{
|
||||
yield return new ValidationResult("Argon2 iterations must be greater than 0.");
|
||||
yield return new ValidationResult($"Argon2 iterations must be between {AuthConstants.ARGON2_ITERATIONS.Min} and {AuthConstants.ARGON2_ITERATIONS.Max}.");
|
||||
}
|
||||
else if (!kdfMemory.HasValue || kdfMemory.Value < 15 || kdfMemory.Value > 1024)
|
||||
else if (!kdfMemory.HasValue || !AuthConstants.ARGON2_MEMORY.InsideRange(kdfMemory.Value))
|
||||
{
|
||||
yield return new ValidationResult("Argon2 memory must be between 15mb and 1024mb.");
|
||||
yield return new ValidationResult($"Argon2 memory must be between {AuthConstants.ARGON2_MEMORY.Min}mb and {AuthConstants.ARGON2_MEMORY.Max}mb.");
|
||||
}
|
||||
else if (!kdfParallelism.HasValue || kdfParallelism.Value < 1 || kdfParallelism.Value > 16)
|
||||
else if (!kdfParallelism.HasValue || !AuthConstants.ARGON2_PARALLELISM.InsideRange(kdfParallelism.Value))
|
||||
{
|
||||
yield return new ValidationResult("Argon2 parallelism must be between 1 and 16.");
|
||||
yield return new ValidationResult($"Argon2 parallelism must be between {AuthConstants.ARGON2_PARALLELISM.Min} and {AuthConstants.ARGON2_PARALLELISM.Max}.");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -75,7 +75,7 @@ public class AccountsController : Controller
|
||||
kdfInformation = new UserKdfInformation
|
||||
{
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = 100000,
|
||||
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
|
||||
};
|
||||
}
|
||||
return new PreloginResponseModel(kdfInformation);
|
||||
|
Reference in New Issue
Block a user