@@ -93,23 +93,21 @@ public void Dispose()
93
93
}
94
94
95
95
/// <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.
97
97
/// </summary>
98
98
/// <param name="data">
99
99
/// The data to sign.
100
100
/// </param>
101
101
/// <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"/>.
103
104
/// </param>
104
105
/// <param name="context">
105
106
/// An optional context-specific value to limit the scope of the signature.
106
107
/// The default value is an empty buffer.
107
108
/// </param>
108
- /// <returns>
109
- /// The number of bytes written to the <paramref name="destination" /> buffer.
110
- /// </returns>
111
109
/// <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.
113
111
/// </exception>
114
112
/// <exception cref="ArgumentOutOfRangeException">
115
113
/// <paramref name="context"/> has a <see cref="ReadOnlySpan{T}.Length"/> in excess of
@@ -123,8 +121,17 @@ public void Dispose()
123
121
/// <para>-or-</para>
124
122
/// <para>An error occurred while signing the data.</para>
125
123
/// </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 )
127
125
{
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
+
128
135
if ( context . Length > MaxContextLength )
129
136
{
130
137
throw new ArgumentOutOfRangeException (
@@ -133,17 +140,45 @@ public int SignData(ReadOnlySpan<byte> data, Span<byte> destination, ReadOnlySpa
133
140
SR . Argument_SignatureContextTooLong255 ) ;
134
141
}
135
142
136
- int signatureSizeInBytes = Algorithm . SignatureSizeInBytes ;
143
+ ThrowIfDisposed ( ) ;
137
144
138
- if ( destination . Length < signatureSizeInBytes )
139
- {
140
- throw new ArgumentException ( SR . Argument_DestinationTooShort , nameof ( destination ) ) ;
141
- }
145
+ SignDataCore ( data , context , destination ) ;
146
+ }
142
147
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 ) ;
144
178
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 ;
147
182
}
148
183
149
184
/// <summary>
@@ -194,6 +229,47 @@ public bool VerifyData(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature, Re
194
229
return VerifyDataCore ( data , context , signature ) ;
195
230
}
196
231
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
+
197
273
/// <summary>
198
274
/// Exports the public-key portion of the current key in the X.509 SubjectPublicKeyInfo format.
199
275
/// </summary>
@@ -758,31 +834,34 @@ public string ExportEncryptedPkcs8PrivateKeyPem(
758
834
/// Exports the public-key portion of the current key in the FIPS 205 public key format.
759
835
/// </summary>
760
836
/// <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"/>.
762
839
/// </param>
763
- /// <returns>
764
- /// The number of bytes written to <paramref name="destination"/>.
765
- /// </returns>
766
840
/// <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.
768
842
/// </exception>
769
843
/// <exception cref="CryptographicException">
770
844
/// <para>An error occurred while exporting the key.</para>
771
845
/// </exception>
772
846
/// <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 )
774
852
{
775
853
int publicKeySizeInBytes = Algorithm . PublicKeySizeInBytes ;
776
854
777
- if ( destination . Length < publicKeySizeInBytes )
855
+ if ( destination . Length != publicKeySizeInBytes )
778
856
{
779
- throw new ArgumentException ( SR . Argument_DestinationTooShort , nameof ( destination ) ) ;
857
+ throw new ArgumentException (
858
+ SR . Format ( SR . Argument_DestinationImprecise , publicKeySizeInBytes ) ,
859
+ nameof ( destination ) ) ;
780
860
}
781
861
782
862
ThrowIfDisposed ( ) ;
783
863
784
- ExportSlhDsaPublicKeyCore ( destination . Slice ( 0 , publicKeySizeInBytes ) ) ;
785
- return publicKeySizeInBytes ;
864
+ ExportSlhDsaPublicKeyCore ( destination ) ;
786
865
}
787
866
788
867
/// <summary>
@@ -808,33 +887,32 @@ public byte[] ExportSlhDsaPublicKey()
808
887
/// Exports the current key in the FIPS 205 secret key format.
809
888
/// </summary>
810
889
/// <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"/>.
812
892
/// </param>
813
- /// <returns>
814
- /// The number of bytes written to <paramref name="destination"/>.
815
- /// </returns>
816
893
/// <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.
818
895
/// </exception>
819
896
/// <exception cref="CryptographicException">
820
897
/// <para>The current instance cannot export a secret key.</para>
821
898
/// <para>-or-</para>
822
899
/// <para>An error occurred while exporting the key.</para>
823
900
/// </exception>
824
901
/// <exception cref="ObjectDisposedException">The object has already been disposed.</exception>
825
- public int ExportSlhDsaSecretKey ( Span < byte > destination )
902
+ public void ExportSlhDsaSecretKey ( Span < byte > destination )
826
903
{
827
904
int secretKeySizeInBytes = Algorithm . SecretKeySizeInBytes ;
828
905
829
- if ( destination . Length < secretKeySizeInBytes )
906
+ if ( destination . Length != secretKeySizeInBytes )
830
907
{
831
- throw new ArgumentException ( SR . Argument_DestinationTooShort , nameof ( destination ) ) ;
908
+ throw new ArgumentException (
909
+ SR . Format ( SR . Argument_DestinationImprecise , secretKeySizeInBytes ) ,
910
+ nameof ( destination ) ) ;
832
911
}
833
912
834
913
ThrowIfDisposed ( ) ;
835
914
836
- ExportSlhDsaSecretKeyCore ( destination . Slice ( 0 , secretKeySizeInBytes ) ) ;
837
- return secretKeySizeInBytes ;
915
+ ExportSlhDsaSecretKeyCore ( destination ) ;
838
916
}
839
917
840
918
/// <summary>
0 commit comments