Skip to content

Commit

Permalink
Adjust evaluation logic to config v6 schema changes (length prefixed …
Browse files Browse the repository at this point in the history
…comparison values)
  • Loading branch information
adams85 committed Oct 26, 2023
1 parent 537a906 commit d19d11a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 26 deletions.
40 changes: 33 additions & 7 deletions src/ConfigCatClient/Evaluation/RolloutEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
using ConfigCat.Client.Utils;
using ConfigCat.Client.Versioning;

Expand Down Expand Up @@ -475,7 +476,7 @@ private static bool EvaluateSensitiveTextEquals(string text, string? comparisonV
{
EnsureComparisonValue(comparisonValue);

var hash = HashComparisonValue(text.AsSpan(), configJsonSalt, contextSalt);
var hash = HashComparisonValue(text, configJsonSalt, contextSalt);

return hash.Equals(hexString: comparisonValue.AsSpan()) ^ negate;
}
Expand All @@ -499,7 +500,7 @@ private static bool EvaluateSensitiveIsOneOf(string text, string[]? comparisonVa
{
EnsureComparisonValue(comparisonValues);

var hash = HashComparisonValue(text.AsSpan(), configJsonSalt, contextSalt);
var hash = HashComparisonValue(text, configJsonSalt, contextSalt);

for (var i = 0; i < comparisonValues.Length; i++)
{
Expand Down Expand Up @@ -540,6 +541,8 @@ private static bool EvaluateSensitiveTextSliceEqualsAnyOf(string text, string[]?
{
EnsureComparisonValue(comparisonValues);

var textUtf8Bytes = Encoding.UTF8.GetBytes(text);

for (var i = 0; i < comparisonValues.Length; i++)
{
var item = EnsureComparisonValue(comparisonValues[i]);
Expand All @@ -555,12 +558,12 @@ private static bool EvaluateSensitiveTextSliceEqualsAnyOf(string text, string[]?
break; // execution should never get here (this is just for keeping the compiler happy)
}

if (text.Length < sliceLength)
if (textUtf8Bytes.Length < sliceLength)
{
continue;
}

var slice = startsWith ? text.AsSpan(0, sliceLength) : text.AsSpan(text.Length - sliceLength);
var slice = startsWith ? textUtf8Bytes.AsSpan(0, sliceLength) : textUtf8Bytes.AsSpan(textUtf8Bytes.Length - sliceLength);

var hash = HashComparisonValue(slice, configJsonSalt, contextSalt);
if (hash.Equals(hexString: hash2))
Expand Down Expand Up @@ -693,7 +696,7 @@ private static bool EvaluateSensitiveArrayContainsAnyOf(string[] array, string[]

for (var i = 0; i < array.Length; i++)
{
var hash = HashComparisonValue(array[i].AsSpan(), configJsonSalt, contextSalt);
var hash = HashComparisonValue(array[i], configJsonSalt, contextSalt);

for (var j = 0; j < comparisonValues.Length; j++)
{
Expand Down Expand Up @@ -822,9 +825,32 @@ private bool EvaluateSegmentCondition(SegmentCondition condition, ref EvaluateCo
return result;
}

private static byte[] HashComparisonValue(ReadOnlySpan<char> value, string configJsonSalt, string contextSalt)
private static byte[] HashComparisonValue(ReadOnlySpan<byte> value, string configJsonSalt, string contextSalt)
{
var valueLength = value.Length;
var configJsonSaltLength = Encoding.UTF8.GetByteCount(configJsonSalt);
var contextSaltLength = Encoding.UTF8.GetByteCount(contextSalt);
var bytes = new byte[valueLength + configJsonSaltLength + contextSaltLength];

value.CopyTo(bytes);
Encoding.UTF8.GetBytes(configJsonSalt, 0, configJsonSalt.Length, bytes, valueLength);
Encoding.UTF8.GetBytes(contextSalt, 0, contextSalt.Length, bytes, valueLength + configJsonSaltLength);

return bytes.Sha256();
}

private static byte[] HashComparisonValue(string value, string configJsonSalt, string contextSalt)
{
return string.Concat(value.ToConcatenable(), configJsonSalt, contextSalt).Sha256();
var valueLength = Encoding.UTF8.GetByteCount(value);
var configJsonSaltLength = Encoding.UTF8.GetByteCount(configJsonSalt);
var contextSaltLength = Encoding.UTF8.GetByteCount(contextSalt);
var bytes = new byte[valueLength + configJsonSaltLength + contextSaltLength];

Encoding.UTF8.GetBytes(value, 0, valueLength, bytes, 0);
Encoding.UTF8.GetBytes(configJsonSalt, 0, configJsonSalt.Length, bytes, valueLength);
Encoding.UTF8.GetBytes(contextSalt, 0, contextSalt.Length, bytes, valueLength + configJsonSaltLength);

return bytes.Sha256();
}

private static string EnsureConfigJsonSalt([NotNull] string? value)
Expand Down
22 changes: 3 additions & 19 deletions src/ConfigCatClient/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,13 @@ public static byte[] Sha1(this string text)
#endif
}

public static byte[] Sha256(this string text)
public static byte[] Sha256(this byte[] bytes)
{
var textBytes = Encoding.UTF8.GetBytes(text);
#if NET5_0_OR_GREATER
return SHA256.HashData(textBytes);
return SHA256.HashData(bytes);
#else
using var hash = SHA256.Create();
return hash.ComputeHash(textBytes);
#endif
}

public static
#if NET5_0_OR_GREATER
ReadOnlySpan<char>
#else
string
#endif
ToConcatenable(this ReadOnlySpan<char> s)
{
#if NET5_0_OR_GREATER
return s;
#else
return s.ToString();
return hash.ComputeHash(bytes);
#endif
}

Expand Down

0 comments on commit d19d11a

Please sign in to comment.