mirror of
https://github.com/bitwarden/server
synced 2026-01-05 01:53:17 +00:00
[PM-23229] Add extra validation to kdf changes + authentication data + unlock data (#6121)
* Added MasterPasswordUnlock to UserDecryptionOptions as part of identity response * Implement support for authentication data and unlock data in kdf change * Extract to kdf command and add tests * Fix namespace * Delete empty file * Fix build * Clean up tests * Fix tests * Add comments * Cleanup * Cleanup * Cleanup * Clean-up and fix build * Address feedback; force new parameters on KDF change request * Clean-up and add tests * Re-add logger * Update logger to interface * Clean up, remove Kdf Request Model * Remove kdf request model tests * Fix types in test * Address feedback to rename request model and re-add tests * Fix namespace * Move comments * Rename InnerKdfRequestModel to KdfRequestModel --------- Co-authored-by: Maciej Zieniuk <mzieniuk@bitwarden.com>
This commit is contained in:
38
src/Core/KeyManagement/Models/Data/KdfSettings.cs
Normal file
38
src/Core/KeyManagement/Models/Data/KdfSettings.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Core.KeyManagement.Models.Data;
|
||||
|
||||
public class KdfSettings
|
||||
{
|
||||
public required KdfType KdfType { get; init; }
|
||||
public required int Iterations { get; init; }
|
||||
public int? Memory { get; init; }
|
||||
public int? Parallelism { get; init; }
|
||||
|
||||
public void ValidateUnchangedForUser(User user)
|
||||
{
|
||||
if (user.Kdf != KdfType || user.KdfIterations != Iterations || user.KdfMemory != Memory || user.KdfParallelism != Parallelism)
|
||||
{
|
||||
throw new ArgumentException("Invalid KDF settings.");
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (obj is not KdfSettings other)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return KdfType == other.KdfType &&
|
||||
Iterations == other.Iterations &&
|
||||
Memory == other.Memory &&
|
||||
Parallelism == other.Parallelism;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(KdfType, Iterations, Memory, Parallelism);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Bit.Core.Entities;
|
||||
|
||||
namespace Bit.Core.KeyManagement.Models.Data;
|
||||
|
||||
public class MasterPasswordAuthenticationData
|
||||
{
|
||||
public required KdfSettings Kdf { get; init; }
|
||||
public required string MasterPasswordAuthenticationHash { get; init; }
|
||||
public required string Salt { get; init; }
|
||||
|
||||
public void ValidateSaltUnchangedForUser(User user)
|
||||
{
|
||||
if (user.GetMasterPasswordSalt() != Salt)
|
||||
{
|
||||
throw new ArgumentException("Invalid master password salt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#nullable enable
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Core.KeyManagement.Models.Data;
|
||||
|
||||
public class MasterPasswordUnlockAndAuthenticationData
|
||||
{
|
||||
public KdfType KdfType { get; set; }
|
||||
public int KdfIterations { get; set; }
|
||||
public int? KdfMemory { get; set; }
|
||||
public int? KdfParallelism { get; set; }
|
||||
|
||||
public required string Email { get; set; }
|
||||
public required string MasterKeyAuthenticationHash { get; set; }
|
||||
public required string MasterKeyEncryptedUserKey { get; set; }
|
||||
public string? MasterPasswordHint { get; set; }
|
||||
|
||||
public bool ValidateForUser(User user)
|
||||
{
|
||||
if (KdfType != user.Kdf || KdfMemory != user.KdfMemory || KdfParallelism != user.KdfParallelism || KdfIterations != user.KdfIterations)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (Email != user.Email)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,20 @@
|
||||
#nullable enable
|
||||
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
|
||||
namespace Bit.Core.KeyManagement.Models.Data;
|
||||
|
||||
public class MasterPasswordUnlockData
|
||||
{
|
||||
public KdfType KdfType { get; set; }
|
||||
public int KdfIterations { get; set; }
|
||||
public int? KdfMemory { get; set; }
|
||||
public int? KdfParallelism { get; set; }
|
||||
public required KdfSettings Kdf { get; init; }
|
||||
public required string MasterKeyWrappedUserKey { get; init; }
|
||||
public required string Salt { get; init; }
|
||||
|
||||
public required string Email { get; set; }
|
||||
public required string MasterKeyAuthenticationHash { get; set; }
|
||||
public required string MasterKeyEncryptedUserKey { get; set; }
|
||||
public string? MasterPasswordHint { get; set; }
|
||||
|
||||
public bool ValidateForUser(User user)
|
||||
public void ValidateSaltUnchangedForUser(User user)
|
||||
{
|
||||
if (KdfType != user.Kdf || KdfMemory != user.KdfMemory || KdfParallelism != user.KdfParallelism || KdfIterations != user.KdfIterations)
|
||||
if (user.GetMasterPasswordSalt() != Salt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (Email != user.Email)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
throw new ArgumentException("Invalid master password salt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public class RotateUserAccountKeysData
|
||||
public string AccountPublicKey { get; set; }
|
||||
|
||||
// All methods to get to the userkey
|
||||
public MasterPasswordUnlockData MasterPasswordUnlockData { get; set; }
|
||||
public MasterPasswordUnlockAndAuthenticationData MasterPasswordUnlockData { get; set; }
|
||||
public IEnumerable<EmergencyAccess> EmergencyAccesses { get; set; }
|
||||
public IReadOnlyList<OrganizationUser> OrganizationUsers { get; set; }
|
||||
public IEnumerable<WebAuthnLoginRotateKeyData> WebAuthnKeys { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user