mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 07:36:14 -05:00
[PM-15608] Create more KDF defaults for prelogin (#5122)
* kdf defaults on null map to email hash * cleanup code. add some randomness as well * remove null check * fix test * move to private method * remove random options * tests for random defaults * SetDefaultKdfHmacKey for old test
This commit is contained in:
@ -82,6 +82,7 @@ public class GlobalSettings : IGlobalSettings
|
||||
public virtual ILaunchDarklySettings LaunchDarkly { get; set; } = new LaunchDarklySettings();
|
||||
public virtual string DevelopmentDirectory { get; set; }
|
||||
public virtual bool EnableEmailVerification { get; set; }
|
||||
public virtual string KdfDefaultHashKey { get; set; }
|
||||
public virtual string PricingUri { get; set; }
|
||||
|
||||
public string BuildExternalUri(string explicitValue, string name)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
@ -15,6 +16,7 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Tokens;
|
||||
using Bit.Core.Tools.Enums;
|
||||
using Bit.Core.Tools.Models.Business;
|
||||
@ -44,6 +46,41 @@ public class AccountsController : Controller
|
||||
private readonly IFeatureService _featureService;
|
||||
private readonly IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> _registrationEmailVerificationTokenDataFactory;
|
||||
|
||||
private readonly byte[] _defaultKdfHmacKey = null;
|
||||
private static readonly List<UserKdfInformation> _defaultKdfResults =
|
||||
[
|
||||
// The first result (index 0) should always return the "normal" default.
|
||||
new()
|
||||
{
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
|
||||
},
|
||||
// We want more weight for this default, so add it again
|
||||
new()
|
||||
{
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
|
||||
},
|
||||
// Add some other possible defaults...
|
||||
new()
|
||||
{
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = 100_000,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = 5_000,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Kdf = KdfType.Argon2id,
|
||||
KdfIterations = AuthConstants.ARGON2_ITERATIONS.Default,
|
||||
KdfMemory = AuthConstants.ARGON2_MEMORY.Default,
|
||||
KdfParallelism = AuthConstants.ARGON2_PARALLELISM.Default,
|
||||
}
|
||||
];
|
||||
|
||||
public AccountsController(
|
||||
ICurrentContext currentContext,
|
||||
ILogger<AccountsController> logger,
|
||||
@ -55,7 +92,8 @@ public class AccountsController : Controller
|
||||
ISendVerificationEmailForRegistrationCommand sendVerificationEmailForRegistrationCommand,
|
||||
IReferenceEventService referenceEventService,
|
||||
IFeatureService featureService,
|
||||
IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> registrationEmailVerificationTokenDataFactory
|
||||
IDataProtectorTokenFactory<RegistrationEmailVerificationTokenable> registrationEmailVerificationTokenDataFactory,
|
||||
GlobalSettings globalSettings
|
||||
)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
@ -69,6 +107,11 @@ public class AccountsController : Controller
|
||||
_referenceEventService = referenceEventService;
|
||||
_featureService = featureService;
|
||||
_registrationEmailVerificationTokenDataFactory = registrationEmailVerificationTokenDataFactory;
|
||||
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.KdfDefaultHashKey))
|
||||
{
|
||||
_defaultKdfHmacKey = Encoding.UTF8.GetBytes(globalSettings.KdfDefaultHashKey);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("register")]
|
||||
@ -217,11 +260,7 @@ public class AccountsController : Controller
|
||||
var kdfInformation = await _userRepository.GetKdfInformationByEmailAsync(model.Email);
|
||||
if (kdfInformation == null)
|
||||
{
|
||||
kdfInformation = new UserKdfInformation
|
||||
{
|
||||
Kdf = KdfType.PBKDF2_SHA256,
|
||||
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
|
||||
};
|
||||
kdfInformation = GetDefaultKdf(model.Email);
|
||||
}
|
||||
return new PreloginResponseModel(kdfInformation);
|
||||
}
|
||||
@ -240,4 +279,26 @@ public class AccountsController : Controller
|
||||
Token = token
|
||||
};
|
||||
}
|
||||
|
||||
private UserKdfInformation GetDefaultKdf(string email)
|
||||
{
|
||||
if (_defaultKdfHmacKey == null)
|
||||
{
|
||||
return _defaultKdfResults[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute the HMAC hash of the email
|
||||
var hmacMessage = Encoding.UTF8.GetBytes(email.Trim().ToLowerInvariant());
|
||||
using var hmac = new System.Security.Cryptography.HMACSHA256(_defaultKdfHmacKey);
|
||||
var hmacHash = hmac.ComputeHash(hmacMessage);
|
||||
// Convert the hash to a number
|
||||
var hashHex = BitConverter.ToString(hmacHash).Replace("-", string.Empty).ToLowerInvariant();
|
||||
var hashFirst8Bytes = hashHex.Substring(0, 16);
|
||||
var hashNumber = long.Parse(hashFirst8Bytes, System.Globalization.NumberStyles.HexNumber);
|
||||
// Find the default KDF value for this hash number
|
||||
var hashIndex = (int)(Math.Abs(hashNumber) % _defaultKdfResults.Count);
|
||||
return _defaultKdfResults[hashIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user