1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-03 00:52:49 -05:00

Allow for binning of comb IDs by date and value

This commit is contained in:
Matt Gibson
2024-07-01 19:15:54 -07:00
parent 554a004d7a
commit 787996bc8a
2 changed files with 58 additions and 0 deletions

View File

@ -76,6 +76,39 @@ public static class CoreHelpers
return new Guid(guidArray); return new Guid(guidArray);
} }
internal static DateTime DateFromComb(Guid combGuid)
{
var guidArray = combGuid.ToByteArray();
var daysArray = new byte[4];
var msecsArray = new byte[4];
Array.Copy(guidArray, guidArray.Length - 6, daysArray, 2, 2);
Array.Copy(guidArray, guidArray.Length - 4, msecsArray, 0, 4);
Array.Reverse(daysArray);
Array.Reverse(msecsArray);
var days = BitConverter.ToInt32(daysArray, 0);
var msecs = BitConverter.ToInt32(msecsArray, 0);
var time = new TimeSpan(days, 0, 0, 0, (int)(msecs * 3.333333));
return new DateTime(_baseDateTicks + time.Ticks, DateTimeKind.Utc);
}
internal static double BinForComb(Guid combGuid, int binCount)
{
// From System.Web.Util.HashCodeCombiner
uint CombineHashCodes(uint h1, byte h2)
{
return (uint)(((h1 << 5) + h1) ^ h2);
}
var guidArray = combGuid.ToByteArray();
var randomArray = new byte[10];
Array.Copy(guidArray, 0, randomArray, 0, 10);
var hash = randomArray.Aggregate((uint)randomArray.Length, CombineHashCodes);
return hash % binCount;
}
public static string CleanCertificateThumbprint(string thumbprint) public static string CleanCertificateThumbprint(string thumbprint)
{ {
// Clean possible garbage characters from thumbprint copy/paste // Clean possible garbage characters from thumbprint copy/paste

View File

@ -71,6 +71,31 @@ public class CoreHelpersTests
Assert.Equal(expectedComb, comb); Assert.Equal(expectedComb, comb);
} }
[Theory]
[MemberData(nameof(GenerateCombCases))]
public void DateFromComb_WithComb_Success(Guid inputGuid, DateTime inputTime)
{
var comb = CoreHelpers.GenerateComb(inputGuid, inputTime);
var inverseComb = CoreHelpers.DateFromComb(comb);
Assert.Equal(inputTime, inverseComb, TimeSpan.FromMilliseconds(4));
}
[Theory]
[InlineData("00000000-0000-0000-0000-000000000000", 1, 0)]
[InlineData("00000000-0000-0000-0000-000000000001", 1, 0)]
[InlineData("00000000-0000-0000-0000-000000000000", 500, 430)]
[InlineData("00000000-0000-0000-0000-000000000001", 500, 430)]
[InlineData("10000000-0000-0000-0000-000000000001", 500, 454)]
[InlineData("00000000-0000-0100-0000-000000000001", 500, 19)]
public void BinForComb_Success(string guidString, int nbins, int expectedBin)
{
var guid = Guid.Parse(guidString);
var bin = CoreHelpers.BinForComb(guid, nbins);
Assert.Equal(expectedBin, bin);
}
/* /*
[Fact] [Fact]
public void ToGuidIdArrayTVP_Success() public void ToGuidIdArrayTVP_Success()