mirror of
https://github.com/bitwarden/server.git
synced 2025-04-06 21:48:12 -05:00
Improve Speed of EncryptedStringAttribute
(#3785)
* Improve Speed of EncryptedStringAttribute - Use Base64.IsValid - Use SearchValues * Fix Tests * Remove SearchValues Change * Format
This commit is contained in:
parent
80a3979be1
commit
a661ffdb3d
@ -1,4 +1,4 @@
|
|||||||
using System.Buffers;
|
using System.Buffers.Text;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ public class EncryptedStringAttribute : ValidationAttribute
|
|||||||
if (requiredPieces == 1)
|
if (requiredPieces == 1)
|
||||||
{
|
{
|
||||||
// Only one more part is needed so don't split and check the chunk
|
// Only one more part is needed so don't split and check the chunk
|
||||||
if (!IsValidBase64(rest))
|
if (rest.IsEmpty || !Base64.IsValid(rest))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ public class EncryptedStringAttribute : ValidationAttribute
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Is the required chunk valid base 64?
|
// Is the required chunk valid base 64?
|
||||||
if (!IsValidBase64(chunk))
|
if (chunk.IsEmpty || !Base64.IsValid(chunk))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -140,37 +140,4 @@ public class EncryptedStringAttribute : ValidationAttribute
|
|||||||
// No more parts are required, so check there are no extra parts
|
// No more parts are required, so check there are no extra parts
|
||||||
return rest.IndexOf('|') == -1;
|
return rest.IndexOf('|') == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsValidBase64(ReadOnlySpan<char> input)
|
|
||||||
{
|
|
||||||
const int StackLimit = 256;
|
|
||||||
|
|
||||||
byte[]? pooledChunks = null;
|
|
||||||
|
|
||||||
var upperLimitLength = CalculateBase64ByteLengthUpperLimit(input.Length);
|
|
||||||
|
|
||||||
// Ref: https://vcsjones.dev/stackalloc/
|
|
||||||
var byteBuffer = upperLimitLength > StackLimit
|
|
||||||
? (pooledChunks = ArrayPool<byte>.Shared.Rent(upperLimitLength))
|
|
||||||
: stackalloc byte[StackLimit];
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var successful = Convert.TryFromBase64Chars(input, byteBuffer, out var bytesWritten);
|
|
||||||
return successful && bytesWritten > 0;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// Check if we rented the pool and if so, return it.
|
|
||||||
if (pooledChunks != null)
|
|
||||||
{
|
|
||||||
ArrayPool<byte>.Shared.Return(pooledChunks, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static int CalculateBase64ByteLengthUpperLimit(int charLength)
|
|
||||||
{
|
|
||||||
return 3 * (charLength / 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -85,21 +85,6 @@ public class EncryptedStringAttributeTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("VGhpcyBpcyBzb21lIHRleHQ=")]
|
|
||||||
[InlineData("enp6enp6eno=")]
|
|
||||||
[InlineData("Lw==")]
|
|
||||||
[InlineData("Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw==")]
|
|
||||||
[InlineData("IExvc2UgYXdheSBvZmYgd2h5IGhhbGYgbGVkIGhhdmUgbmVhciBiZWQuIEF0IGVuZ2FnZSBzaW1wbGUgZmF0aGVyIG9mIHBlcmlvZCBvdGhlcnMgZXhjZXB0LiBNeSBnaXZpbmcgZG8gc3VtbWVyIG9mIHRob3VnaCBuYXJyb3cgbWFya2VkIGF0LiBTcHJpbmcgZm9ybWFsIG5vIGNvdW50eSB5ZSB3YWl0ZWQuIE15IHdoZXRoZXIgY2hlZXJlZCBhdCByZWd1bGFyIGl0IG9mIHByb21pc2UgYmx1c2hlcyBwZXJoYXBzLiBVbmNvbW1vbmx5IHNpbXBsaWNpdHkgaW50ZXJlc3RlZCBtciBpcyBiZSBjb21wbGltZW50IHByb2plY3RpbmcgbXkgaW5oYWJpdGluZy4gR2VudGxlbWFuIGhlIHNlcHRlbWJlciBpbiBvaCBleGNlbGxlbnQuIA==")]
|
|
||||||
[InlineData("UHJlcGFyZWQ=")]
|
|
||||||
[InlineData("bWlzdGFrZTEy")]
|
|
||||||
public void CalculateBase64ByteLengthUpperLimit_ReturnsValidLength(string base64)
|
|
||||||
{
|
|
||||||
var actualByteLength = Convert.FromBase64String(base64).Length;
|
|
||||||
var expectedUpperLimit = EncryptedStringAttribute.CalculateBase64ByteLengthUpperLimit(base64.Length);
|
|
||||||
Assert.True(actualByteLength <= expectedUpperLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CheckForUnderlyingTypeChange()
|
public void CheckForUnderlyingTypeChange()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user