1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-21 12:05:42 +01: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:
Justin Baur 2024-02-20 13:07:54 -05:00 committed by GitHub
parent 80a3979be1
commit a661ffdb3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 4 additions and 52 deletions

View File

@ -1,4 +1,4 @@
using System.Buffers;
using System.Buffers.Text;
using System.ComponentModel.DataAnnotations;
using Bit.Core.Enums;
@ -110,7 +110,7 @@ public class EncryptedStringAttribute : ValidationAttribute
if (requiredPieces == 1)
{
// 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;
}
@ -127,7 +127,7 @@ public class EncryptedStringAttribute : ValidationAttribute
}
// Is the required chunk valid base 64?
if (!IsValidBase64(chunk))
if (chunk.IsEmpty || !Base64.IsValid(chunk))
{
return false;
}
@ -140,37 +140,4 @@ public class EncryptedStringAttribute : ValidationAttribute
// No more parts are required, so check there are no extra parts
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);
}
}

View File

@ -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]
public void CheckForUnderlyingTypeChange()
{