Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Demo/TestController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Text;
using System.Buffers.Text;
using System.Text;
using System.Text.Json;

using Fido2NetLib;
using Fido2NetLib.Development;
using Fido2NetLib.Objects;
Expand Down Expand Up @@ -42,7 +44,7 @@ public OkObjectResult MakeCredentialOptionsTest([FromBody] TEST_MakeCredentialPa

try
{
username = Base64Url.Decode(opts.Username);
username = Base64Url.DecodeFromChars(opts.Username);
}
catch (FormatException)
{
Expand Down
158 changes: 0 additions & 158 deletions Src/Fido2.Models/Base64Url.cs

This file was deleted.

65 changes: 60 additions & 5 deletions Src/Fido2.Models/Converters/Base64UrlConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using System.Text.Json;
#nullable enable

using System.Buffers;
using System.Buffers.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Fido2NetLib;
Expand All @@ -8,20 +12,71 @@ namespace Fido2NetLib;
/// </summary>
public sealed class Base64UrlConverter : JsonConverter<byte[]>
{
public static bool EnableRelaxedDecoding { get; set; }

public override byte[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (!reader.HasValueSequence)
byte[]? rentedBuffer = null;

scoped ReadOnlySpan<byte> source;

if (!reader.HasValueSequence && !reader.ValueIsEscaped)
{
return Base64Url.DecodeUtf8(reader.ValueSpan);
source = reader.ValueSpan;
}
else
{
return Base64Url.Decode(reader.GetString());
int valueLength = reader.HasValueSequence ? checked((int)reader.ValueSequence.Length) : reader.ValueSpan.Length;

Span<byte> buffer = valueLength <= 32 ? stackalloc byte[32] : (rentedBuffer = ArrayPool<byte>.Shared.Rent(valueLength));
int bytesRead = reader.CopyString(buffer);
source = buffer[..bytesRead];
}

try
{
return Base64Url.DecodeFromUtf8(source);
}
catch
{
if (Base64.IsValid(source))
{
if (EnableRelaxedDecoding)
{
return Base64Url.DecodeFromUtf8(source);
}
else
{
throw new JsonException("Expected data to be in Base64Url format, but received Base64 encoding instead.");
}
}
else
{
throw new JsonException("Invalid Base64Url data");
}
}
finally
{
if (rentedBuffer != null)
{
ArrayPool<byte>.Shared.Return(rentedBuffer);
}
}
}

public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options)
{
writer.WriteStringValue(Base64Url.Encode(value));
var rentedBuffer = ArrayPool<byte>.Shared.Rent(Base64Url.GetEncodedLength(value.Length));

try
{
Base64Url.EncodeToUtf8(value, rentedBuffer, out _, out int written);

writer.WriteStringValue(rentedBuffer.AsSpan(0..written));
}
finally
{
ArrayPool<byte>.Shared.Return(rentedBuffer);
}
}
}
6 changes: 5 additions & 1 deletion Src/Fido2.Models/Fido2.Models.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(SupportedTargetFrameworks)</TargetFrameworks>
Expand All @@ -9,4 +9,8 @@
<IsPackable>true</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Bcl.Memory" Version="9.0.0" />
</ItemGroup>

</Project>
3 changes: 1 addition & 2 deletions Src/Fido2.Models/Metadata/BiometricStatusReport.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization;

namespace Fido2NetLib;

Expand Down
3 changes: 2 additions & 1 deletion Src/Fido2/AttestationFormat/AndroidSafetyNet.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
Expand Down Expand Up @@ -46,7 +47,7 @@ public override async ValueTask<VerifyAttestationResult> VerifyAsync(VerifyAttes

try
{
jwtHeaderBytes = Base64Url.Decode(jwtComponents[0]);
jwtHeaderBytes = Base64Url.DecodeFromChars(jwtComponents[0]);
}
catch (FormatException)
{
Expand Down
1 change: 0 additions & 1 deletion Src/Fido2/AuthenticatorAssertionResponse.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
Expand Down
4 changes: 2 additions & 2 deletions Src/Fido2/Fido2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

<ItemGroup>
<ProjectReference Include="..\Fido2.Models\Fido2.Models.csproj" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
<PackageReference Include="NSec.Cryptography" Version="22.4.0" />
<PackageReference Include="System.Formats.Cbor" Version="8.0.0" />
<PackageReference Include="System.Formats.Cbor" Version="9.0.0" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.2.0" />
</ItemGroup>

Expand Down
4 changes: 1 addition & 3 deletions Src/Fido2/MakeAssertionParams.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel;

namespace Fido2NetLib;

Expand Down
5 changes: 3 additions & 2 deletions Src/Fido2/Metadata/ConformanceMetadataRepository.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
Expand Down Expand Up @@ -132,7 +133,7 @@ public async Task<MetadataBLOBPayload> DeserializeAndValidateBlobAsync(string ra
throw new Fido2MetadataException("The JWT does not have the 3 expected components");

var blobHeader = jwtParts[0];
using var jsonDoc = JsonDocument.Parse(Base64Url.Decode(blobHeader));
using var jsonDoc = JsonDocument.Parse(Base64Url.DecodeFromChars(blobHeader));
var tokenHeader = jsonDoc.RootElement;

var blobAlg = tokenHeader.TryGetProperty("alg", out var algEl)
Expand Down Expand Up @@ -235,7 +236,7 @@ public async Task<MetadataBLOBPayload> DeserializeAndValidateBlobAsync(string ra

var blobPayload = ((JsonWebToken)validateTokenResult.SecurityToken).EncodedPayload;

MetadataBLOBPayload blob = JsonSerializer.Deserialize(Base64Url.Decode(blobPayload), FidoModelSerializerContext.Default.MetadataBLOBPayload)!;
MetadataBLOBPayload blob = JsonSerializer.Deserialize(Base64Url.DecodeFromChars(blobPayload), FidoModelSerializerContext.Default.MetadataBLOBPayload)!;
blob.JwtAlg = blobAlg;
return blob;
}
Expand Down
5 changes: 3 additions & 2 deletions Src/Fido2/Metadata/Fido2MetadataServiceRepository.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Buffers.Text;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
Expand Down Expand Up @@ -67,7 +68,7 @@ private async Task<MetadataBLOBPayload> DeserializeAndValidateBlobAsync(string r
throw new ArgumentException("The JWT does not have the 3 expected components");

var blobHeaderString = jwtParts[0];
using var blobHeaderDoc = JsonDocument.Parse(Base64Url.Decode(blobHeaderString));
using var blobHeaderDoc = JsonDocument.Parse(Base64Url.DecodeFromChars(blobHeaderString));
var blobHeader = blobHeaderDoc.RootElement;

string blobAlg = blobHeader.TryGetProperty("alg", out var algEl)
Expand Down Expand Up @@ -186,7 +187,7 @@ private async Task<MetadataBLOBPayload> DeserializeAndValidateBlobAsync(string r

var blobPayload = ((JsonWebToken)validateTokenResult.SecurityToken).EncodedPayload;

MetadataBLOBPayload blob = JsonSerializer.Deserialize(Base64Url.Decode(blobPayload), FidoModelSerializerContext.Default.MetadataBLOBPayload)!;
MetadataBLOBPayload blob = JsonSerializer.Deserialize(Base64Url.DecodeFromChars(blobPayload), FidoModelSerializerContext.Default.MetadataBLOBPayload)!;
blob.JwtAlg = blobAlg;
return blob;
}
Expand Down
2 changes: 2 additions & 0 deletions Src/Fido2/Objects/CredentialPublicKey.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

using Fido2NetLib.Cbor;

using NSec.Cryptography;

namespace Fido2NetLib.Objects;
Expand Down
5 changes: 3 additions & 2 deletions Src/Fido2/TokenBindingDto.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using System.Buffers.Text;
using System.Text.Json.Serialization;
namespace Fido2NetLib;

public class TokenBindingDto
Expand All @@ -25,7 +26,7 @@ public void Verify(byte[]? requestTokenbinding)
case "present":
if (string.IsNullOrEmpty(Id))
throw new Fido2VerificationException("TokenBinding status was present but Id is missing");
var b64 = Base64Url.Encode(requestTokenbinding);
var b64 = Base64Url.EncodeToString(requestTokenbinding);
if (Id != b64)
throw new Fido2VerificationException("Tokenbinding Id does not match");
break;
Expand Down
Loading
Loading