diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml
index 2467b1348ac786..e6101a539349f9 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml
+++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml
@@ -2,8 +2,7 @@
+ namespace="System.Security.Cryptography.Asn1">
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml.cs
index cb41a1559f8549..1dd2b4dc52f808 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPrivateKeyAsn.xml.cs
@@ -12,14 +12,14 @@ namespace System.Security.Cryptography.Asn1
internal partial struct RSAPrivateKeyAsn
{
internal int Version;
- internal System.Numerics.BigInteger Modulus;
- internal System.Numerics.BigInteger PublicExponent;
- internal System.Numerics.BigInteger PrivateExponent;
- internal System.Numerics.BigInteger Prime1;
- internal System.Numerics.BigInteger Prime2;
- internal System.Numerics.BigInteger Exponent1;
- internal System.Numerics.BigInteger Exponent2;
- internal System.Numerics.BigInteger Coefficient;
+ internal ReadOnlyMemory Modulus;
+ internal ReadOnlyMemory PublicExponent;
+ internal ReadOnlyMemory PrivateExponent;
+ internal ReadOnlyMemory Prime1;
+ internal ReadOnlyMemory Prime2;
+ internal ReadOnlyMemory Exponent1;
+ internal ReadOnlyMemory Exponent2;
+ internal ReadOnlyMemory Coefficient;
internal readonly void Encode(AsnWriter writer)
{
@@ -31,14 +31,14 @@ internal readonly void Encode(AsnWriter writer, Asn1Tag tag)
writer.PushSequence(tag);
writer.WriteInteger(Version);
- writer.WriteInteger(Modulus);
- writer.WriteInteger(PublicExponent);
- writer.WriteInteger(PrivateExponent);
- writer.WriteInteger(Prime1);
- writer.WriteInteger(Prime2);
- writer.WriteInteger(Exponent1);
- writer.WriteInteger(Exponent2);
- writer.WriteInteger(Coefficient);
+ writer.WriteInteger(Modulus.Span);
+ writer.WriteInteger(PublicExponent.Span);
+ writer.WriteInteger(PrivateExponent.Span);
+ writer.WriteInteger(Prime1.Span);
+ writer.WriteInteger(Prime2.Span);
+ writer.WriteInteger(Exponent1.Span);
+ writer.WriteInteger(Exponent2.Span);
+ writer.WriteInteger(Coefficient.Span);
writer.PopSequence(tag);
}
@@ -53,7 +53,7 @@ internal static RSAPrivateKeyAsn Decode(Asn1Tag expectedTag, ReadOnlyMemory rebind, out RSAPrivateKeyAsn decoded)
{
- Decode(ref reader, Asn1Tag.Sequence, out decoded);
+ Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
}
- internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, out RSAPrivateKeyAsn decoded)
+ internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, out RSAPrivateKeyAsn decoded)
{
try
{
- DecodeCore(ref reader, expectedTag, out decoded);
+ DecodeCore(ref reader, expectedTag, rebind, out decoded);
}
catch (AsnContentException e)
{
@@ -80,10 +80,13 @@ internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, out
}
}
- private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, out RSAPrivateKeyAsn decoded)
+ private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, out RSAPrivateKeyAsn decoded)
{
decoded = default;
AsnValueReader sequenceReader = reader.ReadSequence(expectedTag);
+ ReadOnlySpan rebindSpan = rebind.Span;
+ int offset;
+ ReadOnlySpan tmpSpan;
if (!sequenceReader.TryReadInt32(out decoded.Version))
@@ -91,14 +94,22 @@ private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, o
sequenceReader.ThrowIfNotEmpty();
}
- decoded.Modulus = sequenceReader.ReadInteger();
- decoded.PublicExponent = sequenceReader.ReadInteger();
- decoded.PrivateExponent = sequenceReader.ReadInteger();
- decoded.Prime1 = sequenceReader.ReadInteger();
- decoded.Prime2 = sequenceReader.ReadInteger();
- decoded.Exponent1 = sequenceReader.ReadInteger();
- decoded.Exponent2 = sequenceReader.ReadInteger();
- decoded.Coefficient = sequenceReader.ReadInteger();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.Modulus = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.PublicExponent = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.PrivateExponent = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.Prime1 = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.Prime2 = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.Exponent1 = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.Exponent2 = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.Coefficient = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
sequenceReader.ThrowIfNotEmpty();
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml
index a0b90d25c84879..d74ed507512a39 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml
+++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml
@@ -2,8 +2,7 @@
+ namespace="System.Security.Cryptography.Asn1">
-
-
+
+
\ No newline at end of file
diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml.cs
index fbbf3cea960f26..acaf3474954359 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/RSAPublicKeyAsn.xml.cs
@@ -11,8 +11,8 @@ namespace System.Security.Cryptography.Asn1
[StructLayout(LayoutKind.Sequential)]
internal partial struct RSAPublicKeyAsn
{
- internal System.Numerics.BigInteger Modulus;
- internal System.Numerics.BigInteger PublicExponent;
+ internal ReadOnlyMemory Modulus;
+ internal ReadOnlyMemory PublicExponent;
internal readonly void Encode(AsnWriter writer)
{
@@ -23,8 +23,8 @@ internal readonly void Encode(AsnWriter writer, Asn1Tag tag)
{
writer.PushSequence(tag);
- writer.WriteInteger(Modulus);
- writer.WriteInteger(PublicExponent);
+ writer.WriteInteger(Modulus.Span);
+ writer.WriteInteger(PublicExponent.Span);
writer.PopSequence(tag);
}
@@ -39,7 +39,7 @@ internal static RSAPublicKeyAsn Decode(Asn1Tag expectedTag, ReadOnlyMemory
{
AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet);
- DecodeCore(ref reader, expectedTag, out RSAPublicKeyAsn decoded);
+ DecodeCore(ref reader, expectedTag, encoded, out RSAPublicKeyAsn decoded);
reader.ThrowIfNotEmpty();
return decoded;
}
@@ -49,16 +49,16 @@ internal static RSAPublicKeyAsn Decode(Asn1Tag expectedTag, ReadOnlyMemory
}
}
- internal static void Decode(ref AsnValueReader reader, out RSAPublicKeyAsn decoded)
+ internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory rebind, out RSAPublicKeyAsn decoded)
{
- Decode(ref reader, Asn1Tag.Sequence, out decoded);
+ Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
}
- internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, out RSAPublicKeyAsn decoded)
+ internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, out RSAPublicKeyAsn decoded)
{
try
{
- DecodeCore(ref reader, expectedTag, out decoded);
+ DecodeCore(ref reader, expectedTag, rebind, out decoded);
}
catch (AsnContentException e)
{
@@ -66,13 +66,18 @@ internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, out
}
}
- private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, out RSAPublicKeyAsn decoded)
+ private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory rebind, out RSAPublicKeyAsn decoded)
{
decoded = default;
AsnValueReader sequenceReader = reader.ReadSequence(expectedTag);
+ ReadOnlySpan rebindSpan = rebind.Span;
+ int offset;
+ ReadOnlySpan tmpSpan;
- decoded.Modulus = sequenceReader.ReadInteger();
- decoded.PublicExponent = sequenceReader.ReadInteger();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.Modulus = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
+ tmpSpan = sequenceReader.ReadIntegerBytes();
+ decoded.PublicExponent = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
sequenceReader.ThrowIfNotEmpty();
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.RSA.cs b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.RSA.cs
index ad5b058229009a..7755d12fd6a271 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.RSA.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/CompositeMLDsaManaged.RSA.cs
@@ -91,21 +91,39 @@ public static RsaComponent ImportPrivateKey(RsaAlgorithm algorithm, ReadOnlySpan
try
{
+ int bytesRead;
rsa = CreateRSA();
#if NET
- rsa.ImportRSAPrivateKey(source, out int bytesRead);
+ rsa.ImportRSAPrivateKey(source, out bytesRead);
+#else
+ try
+ {
+ AsnDecoder.ReadEncodedValue(
+ source,
+ AsnEncodingRules.BER,
+ out _,
+ out _,
+ out bytesRead);
+
+ RSAKeyFormatHelper.FromPkcs1PrivateKey(
+ source.Slice(0, bytesRead),
+ rsaParameters =>
+ {
+ rsa.ImportParameters(rsaParameters);
+ return true;
+ });
+ }
+ catch (AsnContentException e)
+ {
+ throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
+ }
+#endif
if (bytesRead != source.Length)
{
throw new CryptographicException(SR.Argument_PrivateKeyWrongSizeForAlgorithm);
}
-#else
- ConvertRSAPrivateKeyToParameters(algorithm, source, (in parameters) =>
- {
- rsa.ImportParameters(parameters);
- });
-#endif
}
catch (CryptographicException)
{
@@ -124,21 +142,39 @@ public static RsaComponent ImportPublicKey(RsaAlgorithm algorithm, ReadOnlySpan<
try
{
+ int bytesRead;
rsa = CreateRSA();
#if NET
- rsa.ImportRSAPublicKey(source, out int bytesRead);
+ rsa.ImportRSAPublicKey(source, out bytesRead);
+#else
+ try
+ {
+ AsnDecoder.ReadEncodedValue(
+ source,
+ AsnEncodingRules.BER,
+ out _,
+ out _,
+ out bytesRead);
+
+ RSAKeyFormatHelper.FromPkcs1PublicKey(
+ source.Slice(0, bytesRead),
+ rsaParameters =>
+ {
+ rsa.ImportParameters(rsaParameters);
+ return true;
+ });
+ }
+ catch (AsnContentException e)
+ {
+ throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
+ }
+#endif
if (bytesRead != source.Length)
{
throw new CryptographicException(SR.Argument_PublicKeyWrongSizeForAlgorithm);
}
-#else
- ConvertRSAPublicKeyToParameters(algorithm, source, (in parameters) =>
- {
- rsa.ImportParameters(parameters);
- });
-#endif
}
catch (CryptographicException)
{
@@ -199,118 +235,6 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}
-
-#if !NET
- private delegate void ConvertRSAKeyToParametersCallback(in RSAParameters source);
-
- private static unsafe void ConvertRSAPublicKeyToParameters(
- RsaAlgorithm algorithm,
- ReadOnlySpan key,
- ConvertRSAKeyToParametersCallback callback)
- {
- Debug.Assert(algorithm.KeySizeInBits % 8 == 0);
- int modulusLength = algorithm.KeySizeInBits / 8;
- RSAParameters parameters = default;
-
- try
- {
- AsnValueReader reader = new AsnValueReader(key, AsnEncodingRules.BER);
- AsnValueReader sequenceReader = reader.ReadSequence(Asn1Tag.Sequence);
-
- parameters.Modulus = sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes();
-
- if (parameters.Modulus.Length != modulusLength)
- {
- throw new CryptographicException(SR.Cryptography_NotValidPrivateKey);
- }
-
- parameters.Exponent = sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes();
-
- sequenceReader.ThrowIfNotEmpty();
- reader.ThrowIfNotEmpty();
- }
- catch (AsnContentException e)
- {
- throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
- }
-
- callback(in parameters);
- }
-
- private static unsafe void ConvertRSAPrivateKeyToParameters(
- RsaAlgorithm algorithm,
- ReadOnlySpan key,
- ConvertRSAKeyToParametersCallback callback)
- {
- int modulusLength = algorithm.KeySizeInBits / 8;
- int halfModulusLength = modulusLength / 2;
-
- RSAParameters parameters = new()
- {
- D = new byte[modulusLength],
- P = new byte[halfModulusLength],
- Q = new byte[halfModulusLength],
- DP = new byte[halfModulusLength],
- DQ = new byte[halfModulusLength],
- InverseQ = new byte[halfModulusLength],
- };
-
- using (PinAndClear.Track(parameters.D))
- using (PinAndClear.Track(parameters.P))
- using (PinAndClear.Track(parameters.Q))
- using (PinAndClear.Track(parameters.DP))
- using (PinAndClear.Track(parameters.DQ))
- using (PinAndClear.Track(parameters.InverseQ))
- {
- try
- {
- AsnValueReader reader = new AsnValueReader(key, AsnEncodingRules.BER);
- AsnValueReader sequenceReader = reader.ReadSequence(Asn1Tag.Sequence);
-
- if (!sequenceReader.TryReadInt32(out int version))
- {
- sequenceReader.ThrowIfNotEmpty();
- }
-
- const int MaxSupportedVersion = 0;
-
- if (version > MaxSupportedVersion)
- {
- throw new CryptographicException(
- SR.Format(
- SR.Cryptography_RSAPrivateKey_VersionTooNew,
- version,
- MaxSupportedVersion));
- }
-
- parameters.Modulus = sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes();
-
- if (parameters.Modulus.Length != modulusLength)
- {
- throw new CryptographicException(SR.Cryptography_NotValidPrivateKey);
- }
-
- parameters.Exponent = sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes();
-
- sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes(parameters.D);
- sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes(parameters.P);
- sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes(parameters.Q);
- sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes(parameters.DP);
- sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes(parameters.DQ);
- sequenceReader.ReadIntegerBytes().ToUnsignedIntegerBytes(parameters.InverseQ);
-
- sequenceReader.ThrowIfNotEmpty();
- reader.ThrowIfNotEmpty();
- }
- catch (AsnContentException e)
- {
- throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
- }
-
- callback(in parameters);
- }
- }
-#endif
}
}
}
diff --git a/src/libraries/Common/src/System/Security/Cryptography/KeyBlobHelpers.cs b/src/libraries/Common/src/System/Security/Cryptography/KeyBlobHelpers.cs
index a761d7264225c9..d2570a9173dc19 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/KeyBlobHelpers.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/KeyBlobHelpers.cs
@@ -3,48 +3,47 @@
using System.Diagnostics;
using System.Formats.Asn1;
-using System.Numerics;
namespace System.Security.Cryptography
{
internal static partial class KeyBlobHelpers
{
- internal static byte[] ToUnsignedIntegerBytes(this ReadOnlySpan span)
+ internal static byte[] ToUnsignedIntegerBytes(this ReadOnlyMemory memory)
{
- if (span.Length > 1 && span[0] == 0)
+ if (memory.Length > 1 && memory.Span[0] == 0)
{
- return span.Slice(1).ToArray();
+ return memory.Slice(1).ToArray();
}
- return span.ToArray();
+ return memory.ToArray();
}
- internal static void ToUnsignedIntegerBytes(this ReadOnlySpan span, Span destination)
+ internal static void ToUnsignedIntegerBytes(this ReadOnlyMemory memory, Span destination)
{
int length = destination.Length;
- if (span.Length == length)
+ if (memory.Length == length)
{
- span.CopyTo(destination);
+ memory.Span.CopyTo(destination);
return;
}
- if (span.Length == length + 1)
+ if (memory.Length == length + 1)
{
- if (span[0] == 0)
+ if (memory.Span[0] == 0)
{
- span.Slice(1).CopyTo(destination);
+ memory.Span.Slice(1).CopyTo(destination);
return;
}
}
- if (span.Length > length)
+ if (memory.Length > length)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}
- destination.Slice(0, destination.Length - span.Length).Clear();
- span.CopyTo(destination.Slice(length - span.Length));
+ destination.Slice(0, destination.Length - memory.Length).Clear();
+ memory.Span.CopyTo(destination.Slice(length - memory.Length));
}
internal static void WriteKeyParameterInteger(this AsnWriter writer, ReadOnlySpan integer)
diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.Pkcs1.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.Pkcs1.cs
index d8a6783f15e572..016082439bc35c 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.Pkcs1.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.Pkcs1.cs
@@ -2,14 +2,121 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Buffers;
-using System.Diagnostics;
using System.Formats.Asn1;
+using System.Runtime.InteropServices;
using System.Security.Cryptography.Asn1;
namespace System.Security.Cryptography
{
internal static partial class RSAKeyFormatHelper
{
+ internal delegate TRet RSAParametersCallback(RSAParameters parameters);
+
+ internal static unsafe TRet FromPkcs1PrivateKey(
+ ReadOnlySpan keyData,
+ RSAParametersCallback parametersReader,
+ bool pinAndClearParameters = true)
+ {
+ fixed (byte* ptr = &MemoryMarshal.GetReference(keyData))
+ {
+ using (MemoryManager manager = new PointerMemoryManager(ptr, keyData.Length))
+ {
+ return FromPkcs1PrivateKey(manager.Memory, parametersReader, pinAndClearParameters);
+ }
+ }
+ }
+
+ internal static TRet FromPkcs1PrivateKey(
+ ReadOnlyMemory keyData,
+ RSAParametersCallback parametersReader,
+ bool pinAndClearParameters = true)
+ {
+ RSAPrivateKeyAsn key = RSAPrivateKeyAsn.Decode(keyData, AsnEncodingRules.BER);
+
+ const int MaxSupportedVersion = 0;
+
+ if (key.Version > MaxSupportedVersion)
+ {
+ throw new CryptographicException(
+ SR.Format(
+ SR.Cryptography_RSAPrivateKey_VersionTooNew,
+ key.Version,
+ MaxSupportedVersion));
+ }
+
+ // The modulus size determines the encoded output size of the CRT parameters.
+ byte[] n = key.Modulus.ToUnsignedIntegerBytes();
+ int halfModulusLength = (n.Length + 1) / 2;
+
+ RSAParameters parameters = new RSAParameters
+ {
+ Modulus = n,
+ Exponent = key.PublicExponent.ToUnsignedIntegerBytes(),
+
+ D = new byte[n.Length],
+ P = new byte[halfModulusLength],
+ Q = new byte[halfModulusLength],
+ DP = new byte[halfModulusLength],
+ DQ = new byte[halfModulusLength],
+ InverseQ = new byte[halfModulusLength],
+ };
+
+ if (pinAndClearParameters)
+ {
+ using (PinAndClear.Track(parameters.D))
+ using (PinAndClear.Track(parameters.P))
+ using (PinAndClear.Track(parameters.Q))
+ using (PinAndClear.Track(parameters.DP))
+ using (PinAndClear.Track(parameters.DQ))
+ using (PinAndClear.Track(parameters.InverseQ))
+ {
+ return ExtractParametersWithCallback(parametersReader, ref key, ref parameters);
+ }
+ }
+ else
+ {
+ return ExtractParametersWithCallback(parametersReader, ref key, ref parameters);
+ }
+
+ static TRet ExtractParametersWithCallback(RSAParametersCallback parametersReader, ref RSAPrivateKeyAsn key, ref RSAParameters parameters)
+ {
+ key.PrivateExponent.ToUnsignedIntegerBytes(parameters.D);
+ key.Prime1.ToUnsignedIntegerBytes(parameters.P);
+ key.Prime2.ToUnsignedIntegerBytes(parameters.Q);
+ key.Exponent1.ToUnsignedIntegerBytes(parameters.DP);
+ key.Exponent2.ToUnsignedIntegerBytes(parameters.DQ);
+ key.Coefficient.ToUnsignedIntegerBytes(parameters.InverseQ);
+
+ return parametersReader(parameters);
+ }
+ }
+
+ internal static unsafe TRet FromPkcs1PublicKey(
+ ReadOnlySpan keyData,
+ RSAParametersCallback parametersReader)
+ {
+ fixed (byte* ptr = &MemoryMarshal.GetReference(keyData))
+ {
+ using (MemoryManager manager = new PointerMemoryManager(ptr, keyData.Length))
+ {
+ return FromPkcs1PublicKey(manager.Memory, parametersReader);
+ }
+ }
+ }
+
+ internal static TRet FromPkcs1PublicKey(ReadOnlyMemory keyData, RSAParametersCallback parametersReader)
+ {
+ RSAPublicKeyAsn key = RSAPublicKeyAsn.Decode(keyData, AsnEncodingRules.BER);
+
+ RSAParameters parameters = new RSAParameters
+ {
+ Modulus = key.Modulus.ToUnsignedIntegerBytes(),
+ Exponent = key.PublicExponent.ToUnsignedIntegerBytes(),
+ };
+
+ return parametersReader(parameters);
+ }
+
internal static AsnWriter WritePkcs1PublicKey(in RSAParameters rsaParameters)
{
if (rsaParameters.Modulus == null || rsaParameters.Exponent == null)
diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.cs
index c3732580830a6a..7f62903d67f0f1 100644
--- a/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.cs
+++ b/src/libraries/Common/src/System/Security/Cryptography/RSAKeyFormatHelper.cs
@@ -15,48 +15,17 @@ internal static partial class RSAKeyFormatHelper
Oids.Rsa,
};
- // TODO Currently reading PKCS#1 keys uses BigInteger which is not optimal and uses APIs that are not
- // available downlevel. These methods should eventually be replaced with a more efficient implementation
- // and they should be moved into the RSAKeyFormatHelper.Pkcs1 (which is shared between S.S.C. and M.B.C.).
-
internal static void FromPkcs1PrivateKey(
ReadOnlyMemory keyData,
in AlgorithmIdentifierAsn algId,
out RSAParameters ret)
{
- RSAPrivateKeyAsn key = RSAPrivateKeyAsn.Decode(keyData, AsnEncodingRules.BER);
-
if (!algId.HasNullEquivalentParameters())
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}
- const int MaxSupportedVersion = 0;
-
- if (key.Version > MaxSupportedVersion)
- {
- throw new CryptographicException(
- SR.Format(
- SR.Cryptography_RSAPrivateKey_VersionTooNew,
- key.Version,
- MaxSupportedVersion));
- }
-
- // The modulus size determines the encoded output size of the CRT parameters.
- byte[] n = key.Modulus.ToByteArray(isUnsigned: true, isBigEndian: true);
- int halfModulusLength = (n.Length + 1) / 2;
-
- ret = new RSAParameters
- {
- Modulus = n,
- Exponent = key.PublicExponent.ToByteArray(isUnsigned: true, isBigEndian: true),
- D = key.PrivateExponent.ExportKeyParameter(n.Length),
- P = key.Prime1.ExportKeyParameter(halfModulusLength),
- Q = key.Prime2.ExportKeyParameter(halfModulusLength),
- DP = key.Exponent1.ExportKeyParameter(halfModulusLength),
- DQ = key.Exponent2.ExportKeyParameter(halfModulusLength),
- InverseQ = key.Coefficient.ExportKeyParameter(halfModulusLength),
- };
+ ret = FromPkcs1PrivateKey(keyData, rsaParameters => rsaParameters, pinAndClearParameters: false);
}
internal static void ReadRsaPublicKey(
@@ -64,13 +33,7 @@ internal static void ReadRsaPublicKey(
in AlgorithmIdentifierAsn algId,
out RSAParameters ret)
{
- RSAPublicKeyAsn key = RSAPublicKeyAsn.Decode(keyData, AsnEncodingRules.BER);
-
- ret = new RSAParameters
- {
- Modulus = key.Modulus.ToByteArray(isUnsigned: true, isBigEndian: true),
- Exponent = key.PublicExponent.ToByteArray(isUnsigned: true, isBigEndian: true),
- };
+ ret = FromPkcs1PublicKey(keyData, rsaParameters => rsaParameters);
}
internal static void ReadRsaPublicKey(
@@ -135,19 +98,6 @@ internal static unsafe int CheckSubjectPublicKeyInfo(ReadOnlySpan source)
return bytesRead;
}
- public static void ReadPkcs8(
- ReadOnlySpan source,
- out int bytesRead,
- out RSAParameters key)
- {
- KeyFormatHelper.ReadPkcs8(
- s_validOids,
- source,
- FromPkcs1PrivateKey,
- out bytesRead,
- out key);
- }
-
internal static ReadOnlyMemory ReadPkcs8(
ReadOnlyMemory source,
out int bytesRead)
diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj
index af50013e0e9a3f..78f0acde32cf9d 100644
--- a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj
+++ b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj
@@ -173,6 +173,20 @@
Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.manual.cs
Common\System\Security\Cryptography\Asn1\Rc2CbcParameters.xml
+
+ Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml
+
+
+ Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml.cs
+ Common\System\Security\Cryptography\Asn1\RSAPrivateKeyAsn.xml
+
+
+ Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml
+
+
+ Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml.cs
+ Common\System\Security\Cryptography\Asn1\RSAPublicKeyAsn.xml
+
Common\System\Security\Cryptography\Asn1\SubjectPublicKeyInfoAsn.xml
diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj
index 9a20a59f785336..bc2b1a9e817464 100644
--- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj
+++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj
@@ -863,6 +863,7 @@
+
diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyBlobHelpers.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyBlobHelpers.cs
index 63cc64160d532f..22c10081c26107 100644
--- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyBlobHelpers.cs
+++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/KeyBlobHelpers.cs
@@ -1,16 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Diagnostics;
-using System.Formats.Asn1;
using System.Numerics;
namespace System.Security.Cryptography
{
internal static partial class KeyBlobHelpers
{
- internal static byte[] ToUnsignedIntegerBytes(this ReadOnlyMemory memory) => memory.Span.ToUnsignedIntegerBytes();
-
internal static byte[] ToUnsignedIntegerBytes(this ReadOnlyMemory memory, int length)
{
if (memory.Length == length)
diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs
index e653c0fc268361..e9454c4f76a7f6 100644
--- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs
+++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSA.cs
@@ -929,36 +929,15 @@ public virtual unsafe void ImportRSAPrivateKey(ReadOnlySpan source, out in
out _,
out int firstValueLength);
- fixed (byte* ptr = &MemoryMarshal.GetReference(source))
- {
- using (MemoryManager manager = new PointerMemoryManager(ptr, firstValueLength))
- {
- ReadOnlyMemory firstValue = manager.Memory;
- int localRead = firstValue.Length;
-
- AlgorithmIdentifierAsn ignored = default;
- RSAKeyFormatHelper.FromPkcs1PrivateKey(firstValue, ignored, out RSAParameters rsaParameters);
-
- fixed (byte* dPin = rsaParameters.D)
- fixed (byte* pPin = rsaParameters.P)
- fixed (byte* qPin = rsaParameters.Q)
- fixed (byte* dpPin = rsaParameters.DP)
- fixed (byte* dqPin = rsaParameters.DQ)
- fixed (byte* qInvPin = rsaParameters.InverseQ)
+ RSAKeyFormatHelper.FromPkcs1PrivateKey(
+ source.Slice(0, firstValueLength),
+ rsaParameters =>
{
- try
- {
- ImportParameters(rsaParameters);
- }
- finally
- {
- ClearPrivateParameters(rsaParameters);
- }
- }
+ ImportParameters(rsaParameters);
+ return true;
+ });
- bytesRead = localRead;
- }
- }
+ bytesRead = firstValueLength;
}
catch (AsnContentException e)
{