Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2386467

Browse files
Use UTF-8 PEM overloads in .NET 10.
Avoid an unnecessary decode from bytes to a string. See https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10/libraries#find-pem-encoded-data-in-asciiutf-8. Signed-off-by: Bradley Grainger <bgrainger@gmail.com>
1 parent e6299cd commit 2386467

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

‎src/MySqlConnector/Core/ServerSession.cs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ private async Task<PayloadData> SendClearPasswordAsync(string password, IOBehavi
972972

973973
private async Task<PayloadData> SendEncryptedPasswordAsync(
974974
byte[] switchRequestData,
975-
string rsaPublicKey,
975+
byte[] rsaPublicKey,
976976
string password,
977977
IOBehavior ioBehavior,
978978
CancellationToken cancellationToken)
@@ -993,7 +993,7 @@ private async Task<PayloadData> SendEncryptedPasswordAsync(
993993
RSAParameters rsaParameters;
994994
try
995995
{
996-
rsaParameters = Utility.GetRsaParameters(rsaPublicKey);
996+
rsaParameters = Utility.GetRsaParameters(Encoding.ASCII.GetString(rsaPublicKey));
997997
}
998998
catch (Exception ex)
999999
{
@@ -1020,13 +1020,13 @@ private async Task<PayloadData> SendEncryptedPasswordAsync(
10201020
return await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
10211021
}
10221022

1023-
private async Task<string> GetRsaPublicKeyAsync(string switchRequestName, ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)
1023+
private async Task<byte[]> GetRsaPublicKeyAsync(string switchRequestName, ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)
10241024
{
10251025
if (cs.ServerRsaPublicKeyFile.Length != 0)
10261026
{
10271027
try
10281028
{
1029-
return File.ReadAllText(cs.ServerRsaPublicKeyFile);
1029+
return File.ReadAllBytes(cs.ServerRsaPublicKeyFile);
10301030
}
10311031
catch (IOException ex)
10321032
{
@@ -1042,7 +1042,7 @@ private async Task<string> GetRsaPublicKeyAsync(string switchRequestName, Connec
10421042
await SendReplyAsync(new PayloadData([payloadContent]), ioBehavior, cancellationToken).ConfigureAwait(false);
10431043
var payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
10441044
var publicKeyPayload = AuthenticationMoreDataPayload.Create(payload.Span);
1045-
return Encoding.ASCII.GetString(publicKeyPayload.Data);
1045+
return publicKeyPayload.Data;
10461046
}
10471047

10481048
Log.CouldNotUseAuthenticationMethodForRsa(m_logger, Id, switchRequestName);

‎src/MySqlConnector/Utilities/Utility.cs‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,44 @@ public static unsafe int GetByteCount(this Encoder encoder, ReadOnlySpan<char> c
8888
}
8989
#endif
9090

91+
#if NET5_0_OR_GREATER
92+
/// <summary>
93+
/// Loads a RSA key from PEM bytes.
94+
/// </summary>
95+
public static void LoadRsaParameters(byte[] key, RSA rsa)
96+
{
97+
#if NET10_0_OR_GREATER
98+
if (!PemEncoding.TryFindUtf8(key, out var pemFields))
99+
throw new FormatException("Unrecognized PEM data: " + Encoding.ASCII.GetString(key.AsSpan(0, Math.Min(key.Length, 80))));
100+
var isPrivate = key.AsSpan()[pemFields.Label].SequenceEqual("RSA PRIVATE KEY"u8);
101+
102+
var keyBytes = key.AsSpan()[pemFields.Base64Data];
103+
var bufferLength = keyBytes.Length / 4 * 3;
104+
byte[]? buffer = null;
105+
Span<byte> bufferBytes = bufferLength > 1024 ?
106+
(Span<byte>) (buffer = ArrayPool<byte>.Shared.Rent(bufferLength)) :
107+
stackalloc byte[bufferLength];
108+
try
109+
{
110+
if (Base64.DecodeFromUtf8(keyBytes, bufferBytes, out _, out var bytesWritten) != OperationStatus.Done)
111+
throw new FormatException("The input is not a valid Base-64 string.");
112+
if (isPrivate)
113+
rsa.ImportRSAPrivateKey(bufferBytes[..bytesWritten], out var _);
114+
else
115+
rsa.ImportSubjectPublicKeyInfo(bufferBytes[..bytesWritten], out var _);
116+
}
117+
finally
118+
{
119+
if (buffer is not null)
120+
ArrayPool<byte>.Shared.Return(buffer);
121+
}
122+
#else
123+
LoadRsaParameters(Encoding.ASCII.GetString(key), rsa);
124+
#endif
125+
}
126+
#endif
127+
128+
#if !NET10_0_OR_GREATER
91129
/// <summary>
92130
/// Loads a RSA key from a PEM string.
93131
/// </summary>
@@ -176,6 +214,7 @@ public static RSAParameters GetRsaParameters(string key)
176214
return GetRsaParameters(System.Convert.FromBase64String(key), isPrivate);
177215
#endif
178216
}
217+
#endif
179218

180219
#if !NET5_0_OR_GREATER
181220
// Derived from: https://stackoverflow.com/a/32243171/, https://stackoverflow.com/a/26978561/, http://luca.ntop.org/Teaching/Appunti/asn1.html

‎tests/MySqlConnector.Tests/MySqlConnector.Tests.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup Condition=" '$(Configuration)' != 'MySqlData' ">
4-
<TargetFrameworks>net481;net10.0</TargetFrameworks>
4+
<TargetFrameworks>net481;net8.0;net10.0</TargetFrameworks>
55
</PropertyGroup>
66

77
<PropertyGroup Condition=" '$(Configuration)' == 'MySqlData' ">

‎tests/MySqlConnector.Tests/UtilityTests.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public void DecodePublicKey(string pre, string post)
9494
{
9595
#if NET5_0_OR_GREATER
9696
using var rsa = RSA.Create();
97-
Utility.LoadRsaParameters(pre + c_publicKey + post, rsa);
97+
Utility.LoadRsaParameters(Encoding.ASCII.GetBytes(pre + c_publicKey + post), rsa);
9898
var parameters = rsa.ExportParameters(false);
9999
#else
100100
var parameters = Utility.GetRsaParameters(pre + c_publicKey + post);
@@ -112,7 +112,7 @@ public void DecodePrivateKey(string pre, string post)
112112
{
113113
#if NET5_0_OR_GREATER
114114
using var rsa = RSA.Create();
115-
Utility.LoadRsaParameters(pre + c_privateKey + post, rsa);
115+
Utility.LoadRsaParameters(Encoding.ASCII.GetBytes(pre + c_privateKey + post), rsa);
116116
var parameters = rsa.ExportParameters(true);
117117
#else
118118
var parameters = Utility.GetRsaParameters(pre + c_privateKey + post);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /