@@ -256,24 +256,116 @@ public string GetDigest()
256
256
257
257
public override string ToString ( )
258
258
{
259
- string authHeader = AuthHeaders . AUTH_DIGEST_KEY + " " ;
260
-
261
- authHeader += ( Username != null && Username . Trim ( ) . Length != 0 ) ? AuthHeaders . AUTH_USERNAME_KEY + "=\" " + Username + "\" " : null ;
262
- authHeader += ( authHeader . IndexOf ( '=' ) != - 1 ) ? "," + AuthHeaders . AUTH_REALM_KEY + "=\" " + Realm + "\" " : AuthHeaders . AUTH_REALM_KEY + "=\" " + Realm + "\" " ;
263
- authHeader += ( Nonce != null ) ? "," + AuthHeaders . AUTH_NONCE_KEY + "=\" " + Nonce + "\" " : null ;
264
- authHeader += ( URI != null && URI . Trim ( ) . Length != 0 ) ? "," + AuthHeaders . AUTH_URI_KEY + "=\" " + URI + "\" " : null ;
265
- authHeader += ( Response != null && Response . Length != 0 ) ? "," + AuthHeaders . AUTH_RESPONSE_KEY + "=\" " + Response + "\" " : null ;
266
- authHeader += ( Cnonce != null ) ? "," + AuthHeaders . AUTH_CNONCE_KEY + "=\" " + Cnonce + "\" " : null ;
267
- authHeader += ( NonceCount != 0 ) ? "," + AuthHeaders . AUTH_NONCECOUNT_KEY + "=" + GetPaddedNonceCount ( NonceCount ) : null ;
268
- authHeader += ( Qop != null ) ? "," + AuthHeaders . AUTH_QOP_KEY + "=" + Qop : null ;
269
- authHeader += ( Opaque != null ) ? "," + AuthHeaders . AUTH_OPAQUE_KEY + "=\" " + Opaque + "\" " : null ;
270
-
271
- string algorithmID = ( DigestAlgorithm == DigestAlgorithmsEnum . SHA256 ) ? SHA256_ALGORITHM_ID : DigestAlgorithm . ToString ( ) ;
272
- authHeader += ( Response != null ) ? "," + AuthHeaders . AUTH_ALGORITHM_KEY + "=" + algorithmID : null ;
273
-
274
- return authHeader ;
259
+ var builder = new ValueStringBuilder ( ) ;
260
+
261
+ try
262
+ {
263
+ ToString ( ref builder ) ;
264
+
265
+ return builder . ToString ( ) ;
266
+ }
267
+ finally
268
+ {
269
+ builder . Dispose ( ) ;
270
+ }
271
+ }
272
+
273
+ internal void ToString ( ref ValueStringBuilder builder )
274
+ {
275
+ builder . Append ( AuthHeaders . AUTH_DIGEST_KEY ) ;
276
+ builder . Append ( ' ' ) ;
277
+
278
+ bool hasUsername = ! string . IsNullOrWhiteSpace ( Username ) ;
279
+ if ( hasUsername )
280
+ {
281
+ builder . Append ( AuthHeaders . AUTH_USERNAME_KEY ) ;
282
+ builder . Append ( "=\" " ) ;
283
+ builder . Append ( Username ) ;
284
+ builder . Append ( '"' ) ;
285
+ }
286
+
287
+ builder . Append ( hasUsername ? ',' : '\0 ' ) ;
288
+ builder . Append ( AuthHeaders . AUTH_REALM_KEY ) ;
289
+ builder . Append ( "=\" " ) ;
290
+ builder . Append ( Realm ) ;
291
+ builder . Append ( '"' ) ;
292
+
293
+ if ( Nonce != null )
294
+ {
295
+ builder . Append ( ',' ) ;
296
+ builder . Append ( AuthHeaders . AUTH_NONCE_KEY ) ;
297
+ builder . Append ( "=\" " ) ;
298
+ builder . Append ( Nonce ) ;
299
+ builder . Append ( '"' ) ;
300
+ }
301
+
302
+ if ( ! string . IsNullOrWhiteSpace ( URI ) )
303
+ {
304
+ builder . Append ( ',' ) ;
305
+ builder . Append ( AuthHeaders . AUTH_URI_KEY ) ;
306
+ builder . Append ( "=\" " ) ;
307
+ builder . Append ( URI ) ;
308
+ builder . Append ( '"' ) ;
309
+ }
310
+
311
+ if ( ! string . IsNullOrEmpty ( Response ) )
312
+ {
313
+ builder . Append ( ',' ) ;
314
+ builder . Append ( AuthHeaders . AUTH_RESPONSE_KEY ) ;
315
+ builder . Append ( "=\" " ) ;
316
+ builder . Append ( Response ) ;
317
+ builder . Append ( '"' ) ;
318
+ }
319
+
320
+ if ( Cnonce != null )
321
+ {
322
+ builder . Append ( ',' ) ;
323
+ builder . Append ( AuthHeaders . AUTH_CNONCE_KEY ) ;
324
+ builder . Append ( "=\" " ) ;
325
+ builder . Append ( Cnonce ) ;
326
+ builder . Append ( '"' ) ;
327
+ }
328
+
329
+ if ( NonceCount != 0 )
330
+ {
331
+ builder . Append ( ',' ) ;
332
+ builder . Append ( AuthHeaders . AUTH_NONCECOUNT_KEY ) ;
333
+ builder . Append ( '=' ) ;
334
+ builder . Append ( GetPaddedNonceCount ( NonceCount ) ) ;
335
+ }
336
+
337
+ if ( Qop != null )
338
+ {
339
+ builder . Append ( ',' ) ;
340
+ builder . Append ( AuthHeaders . AUTH_QOP_KEY ) ;
341
+ builder . Append ( '=' ) ;
342
+ builder . Append ( Qop ) ;
343
+ }
344
+
345
+ if ( Opaque != null )
346
+ {
347
+ builder . Append ( ',' ) ;
348
+ builder . Append ( AuthHeaders . AUTH_OPAQUE_KEY ) ;
349
+ builder . Append ( "=\" " ) ;
350
+ builder . Append ( Opaque ) ;
351
+ builder . Append ( '"' ) ;
352
+ }
353
+
354
+ if ( Response != null )
355
+ {
356
+ builder . Append ( ',' ) ;
357
+ builder . Append ( AuthHeaders . AUTH_ALGORITHM_KEY ) ;
358
+ builder . Append ( '=' ) ;
359
+
360
+ string algorithmID = ( DigestAlgorithm == DigestAlgorithmsEnum . SHA256 )
361
+ ? SHA256_ALGORITHM_ID
362
+ : DigestAlgorithm . ToString ( ) ;
363
+
364
+ builder . Append ( algorithmID ) ;
365
+ }
275
366
}
276
367
368
+
277
369
public SIPAuthorisationDigest CopyOf ( )
278
370
{
279
371
var copy = new SIPAuthorisationDigest ( AuthorisationType , Realm , Username , Password , URI , Nonce , RequestType , DigestAlgorithm ) ;
@@ -385,21 +477,21 @@ public static string GetHashHex(DigestAlgorithmsEnum hashAlg, string val)
385
477
case DigestAlgorithmsEnum . SHA256 :
386
478
using ( var hash = new SHA256CryptoServiceProvider ( ) )
387
479
{
388
- return hash . ComputeHash ( Encoding . UTF8 . GetBytes ( val ) ) . HexStr ( ) . ToLower ( ) ;
480
+ return hash . ComputeHash ( Encoding . UTF8 . GetBytes ( val ) ) . AsSpan ( ) . HexStr ( lowercase : true ) ;
389
481
}
390
482
// This is commented because RFC8760 does not have an SHA-512 option. Instead it's HSA-512-sess which
391
483
// means the SIP request body needs to be included in the digest as well. Including the body will require
392
484
// some additional changes that can be done at a later date.
393
485
//case DigestAlgorithmsEnum.SHA512:
394
486
// using (var hash = new SHA512CryptoServiceProvider())
395
487
// {
396
- // return hash.ComputeHash(Encoding.UTF8.GetBytes(val)).HexStr().ToLower( );
488
+ // return hash.ComputeHash(Encoding.UTF8.GetBytes(val)).HexStr(lowercase: false );
397
489
// }
398
490
case DigestAlgorithmsEnum . MD5 :
399
491
default :
400
492
using ( var hash = new MD5CryptoServiceProvider ( ) )
401
493
{
402
- return hash . ComputeHash ( Encoding . UTF8 . GetBytes ( val ) ) . HexStr ( ) . ToLower ( ) ;
494
+ return hash . ComputeHash ( Encoding . UTF8 . GetBytes ( val ) ) . AsSpan ( ) . HexStr ( lowercase : true ) ;
403
495
}
404
496
}
405
497
#pragma warning restore SYSLIB0021
0 commit comments