Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c68a1be

Browse files
Align SlhDsa API with MLKem (#115290)
1 parent aa3b802 commit c68a1be

File tree

10 files changed

+255
-134
lines changed

10 files changed

+255
-134
lines changed

src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs

+113-35
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,21 @@ public void Dispose()
9393
}
9494

9595
/// <summary>
96-
/// Sign the specified data, writing the signature into the provided buffer.
96+
/// Signs the specified data, writing the signature into the provided buffer.
9797
/// </summary>
9898
/// <param name="data">
9999
/// The data to sign.
100100
/// </param>
101101
/// <param name="destination">
102-
/// The buffer to receive the signature.
102+
/// The buffer to receive the signature. Its length must be exactly
103+
/// <see cref="SlhDsaAlgorithm.SignatureSizeInBytes"/>.
103104
/// </param>
104105
/// <param name="context">
105106
/// An optional context-specific value to limit the scope of the signature.
106107
/// The default value is an empty buffer.
107108
/// </param>
108-
/// <returns>
109-
/// The number of bytes written to the <paramref name="destination" /> buffer.
110-
/// </returns>
111109
/// <exception cref="ArgumentException">
112-
/// The buffer in <paramref name="destination"/> is too small to hold the signature.
110+
/// The buffer in <paramref name="destination"/> is the incorrect length to receive the signature.
113111
/// </exception>
114112
/// <exception cref="ArgumentOutOfRangeException">
115113
/// <paramref name="context"/> has a <see cref="ReadOnlySpan{T}.Length"/> in excess of
@@ -123,8 +121,17 @@ public void Dispose()
123121
/// <para>-or-</para>
124122
/// <para>An error occurred while signing the data.</para>
125123
/// </exception>
126-
public int SignData(ReadOnlySpan<byte> data, Span<byte> destination, ReadOnlySpan<byte> context = default)
124+
public void SignData(ReadOnlySpan<byte> data, Span<byte> destination, ReadOnlySpan<byte> context = default)
127125
{
126+
int signatureSizeInBytes = Algorithm.SignatureSizeInBytes;
127+
128+
if (destination.Length != signatureSizeInBytes)
129+
{
130+
throw new ArgumentException(
131+
SR.Format(SR.Argument_DestinationImprecise, signatureSizeInBytes),
132+
nameof(destination));
133+
}
134+
128135
if (context.Length > MaxContextLength)
129136
{
130137
throw new ArgumentOutOfRangeException(
@@ -133,17 +140,45 @@ public int SignData(ReadOnlySpan<byte> data, Span<byte> destination, ReadOnlySpa
133140
SR.Argument_SignatureContextTooLong255);
134141
}
135142

136-
int signatureSizeInBytes = Algorithm.SignatureSizeInBytes;
143+
ThrowIfDisposed();
137144

138-
if (destination.Length < signatureSizeInBytes)
139-
{
140-
throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination));
141-
}
145+
SignDataCore(data, context, destination);
146+
}
142147

143-
ThrowIfDisposed();
148+
/// <summary>
149+
/// Signs the specified data.
150+
/// </summary>
151+
/// <param name="data">
152+
/// The data to sign.
153+
/// </param>
154+
/// <param name="context">
155+
/// An optional context-specific value to limit the scope of the signature.
156+
/// The default value is <see langword="null" />.
157+
/// </param>
158+
/// <exception cref="ArgumentNullException">
159+
/// <paramref name="data"/> is <see langword="null"/>.
160+
/// </exception>
161+
/// <exception cref="ArgumentOutOfRangeException">
162+
/// <paramref name="context"/> has a length in excess of 255 bytes.
163+
/// </exception>
164+
/// <exception cref="ObjectDisposedException">
165+
/// This instance has been disposed.
166+
/// </exception>
167+
/// <exception cref="CryptographicException">
168+
/// <para>The instance represents only a public key.</para>
169+
/// <para>-or-</para>
170+
/// <para>An error occurred while signing the data.</para>
171+
/// </exception>
172+
/// <remarks>
173+
/// A <see langword="null" /> context is treated as empty.
174+
/// </remarks>
175+
public byte[] SignData(byte[] data, byte[]? context = default)
176+
{
177+
ArgumentNullException.ThrowIfNull(data);
144178

145-
SignDataCore(data, context, destination.Slice(0, signatureSizeInBytes));
146-
return signatureSizeInBytes;
179+
byte[] destination = new byte[Algorithm.SignatureSizeInBytes];
180+
SignData(new ReadOnlySpan<byte>(data), destination.AsSpan(), new ReadOnlySpan<byte>(context));
181+
return destination;
147182
}
148183

149184
/// <summary>
@@ -194,6 +229,47 @@ public bool VerifyData(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature, Re
194229
return VerifyDataCore(data, context, signature);
195230
}
196231

232+
/// <summary>
233+
/// Verifies that the specified signature is valid for this key and the provided data.
234+
/// </summary>
235+
/// <param name="data">
236+
/// The data to verify.
237+
/// </param>
238+
/// <param name="signature">
239+
/// The signature to verify.
240+
/// </param>
241+
/// <param name="context">
242+
/// The context value which was provided during signing.
243+
/// The default value is <see langword="null" />.
244+
/// </param>
245+
/// <returns>
246+
/// <see langword="true"/> if the signature validates the data; otherwise, <see langword="false"/>.
247+
/// </returns>
248+
/// <exception cref="ArgumentNullException">
249+
/// <paramref name="data"/> or <paramref name="signature"/> is <see langword="null"/>.
250+
/// </exception>
251+
/// <exception cref="ArgumentOutOfRangeException">
252+
/// <paramref name="context"/> has a length in excess of 255 bytes.
253+
/// </exception>
254+
/// <exception cref="ObjectDisposedException">
255+
/// This instance has been disposed.
256+
/// </exception>
257+
/// <exception cref="CryptographicException">
258+
/// <para>The instance represents only a public key.</para>
259+
/// <para>-or-</para>
260+
/// <para>An error occurred while signing the data.</para>
261+
/// </exception>
262+
/// <remarks>
263+
/// A <see langword="null" /> context is treated as empty.
264+
/// </remarks>
265+
public bool VerifyData(byte[] data, byte[] signature, byte[]? context = default)
266+
{
267+
ArgumentNullException.ThrowIfNull(data);
268+
ArgumentNullException.ThrowIfNull(signature);
269+
270+
return VerifyData(new ReadOnlySpan<byte>(data), new ReadOnlySpan<byte>(signature), new ReadOnlySpan<byte>(context));
271+
}
272+
197273
/// <summary>
198274
/// Exports the public-key portion of the current key in the X.509 SubjectPublicKeyInfo format.
199275
/// </summary>
@@ -758,31 +834,34 @@ public string ExportEncryptedPkcs8PrivateKeyPem(
758834
/// Exports the public-key portion of the current key in the FIPS 205 public key format.
759835
/// </summary>
760836
/// <param name="destination">
761-
/// The buffer to receive the public key.
837+
/// The buffer to receive the public key. Its length must be exactly
838+
/// <see cref="SlhDsaAlgorithm.SecretKeySizeInBytes"/>.
762839
/// </param>
763-
/// <returns>
764-
/// The number of bytes written to <paramref name="destination"/>.
765-
/// </returns>
766840
/// <exception cref="ArgumentException">
767-
/// <paramref name="destination"/> is too small to hold the public key.
841+
/// <paramref name="destination"/> is the incorrect length to receive the public key.
768842
/// </exception>
769843
/// <exception cref="CryptographicException">
770844
/// <para>An error occurred while exporting the key.</para>
771845
/// </exception>
772846
/// <exception cref="ObjectDisposedException">The object has already been disposed.</exception>
773-
public int ExportSlhDsaPublicKey(Span<byte> destination)
847+
/// <remarks>
848+
/// <paramref name="destination"/> is required to be exactly
849+
/// <see cref="SlhDsaAlgorithm.PublicKeySizeInBytes"/> in length.
850+
/// </remarks>
851+
public void ExportSlhDsaPublicKey(Span<byte> destination)
774852
{
775853
int publicKeySizeInBytes = Algorithm.PublicKeySizeInBytes;
776854

777-
if (destination.Length < publicKeySizeInBytes)
855+
if (destination.Length != publicKeySizeInBytes)
778856
{
779-
throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination));
857+
throw new ArgumentException(
858+
SR.Format(SR.Argument_DestinationImprecise, publicKeySizeInBytes),
859+
nameof(destination));
780860
}
781861

782862
ThrowIfDisposed();
783863

784-
ExportSlhDsaPublicKeyCore(destination.Slice(0, publicKeySizeInBytes));
785-
return publicKeySizeInBytes;
864+
ExportSlhDsaPublicKeyCore(destination);
786865
}
787866

788867
/// <summary>
@@ -808,33 +887,32 @@ public byte[] ExportSlhDsaPublicKey()
808887
/// Exports the current key in the FIPS 205 secret key format.
809888
/// </summary>
810889
/// <param name="destination">
811-
/// The buffer to receive the secret key.
890+
/// The buffer to receive the secret key. Its length must be exactly
891+
/// <see cref="SlhDsaAlgorithm.SecretKeySizeInBytes"/>.
812892
/// </param>
813-
/// <returns>
814-
/// The number of bytes written to <paramref name="destination"/>.
815-
/// </returns>
816893
/// <exception cref="ArgumentException">
817-
/// <paramref name="destination"/> is too small to hold the secret key.
894+
/// <paramref name="destination"/> is the incorrect length to receive the secret key.
818895
/// </exception>
819896
/// <exception cref="CryptographicException">
820897
/// <para>The current instance cannot export a secret key.</para>
821898
/// <para>-or-</para>
822899
/// <para>An error occurred while exporting the key.</para>
823900
/// </exception>
824901
/// <exception cref="ObjectDisposedException">The object has already been disposed.</exception>
825-
public int ExportSlhDsaSecretKey(Span<byte> destination)
902+
public void ExportSlhDsaSecretKey(Span<byte> destination)
826903
{
827904
int secretKeySizeInBytes = Algorithm.SecretKeySizeInBytes;
828905

829-
if (destination.Length < secretKeySizeInBytes)
906+
if (destination.Length != secretKeySizeInBytes)
830907
{
831-
throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination));
908+
throw new ArgumentException(
909+
SR.Format(SR.Argument_DestinationImprecise, secretKeySizeInBytes),
910+
nameof(destination));
832911
}
833912

834913
ThrowIfDisposed();
835914

836-
ExportSlhDsaSecretKeyCore(destination.Slice(0, secretKeySizeInBytes));
837-
return secretKeySizeInBytes;
915+
ExportSlhDsaSecretKeyCore(destination);
838916
}
839917

840918
/// <summary>

0 commit comments

Comments
 (0)