@@ -416,52 +416,36 @@ public byte[] Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additiona
416416 additionalAuthenticatedData . Validate ( ) ;
417417 var plainTextSpan = plaintext . AsSpan ( ) ;
418418
419+ #if NET10_0_OR_GREATER
420+ var size = GetEncryptedSize ( plainTextSpan . Length ) ;
421+ var retVal = new byte [ size ] ;
422+ if ( ! TryEncrypt ( plaintext . AsSpan ( ) , additionalAuthenticatedData . AsSpan ( ) , retVal , out var bytesWritten ) )
423+ {
424+ // TODO understand what we really expect here
425+ throw Error . CryptCommon_GenericError ( ) ;
426+ }
427+
428+ Debug . Assert ( bytesWritten == size , "bytesWritten == size" ) ;
429+ return retVal ;
430+ #endif
431+
419432 try
420433 {
421434 var keyModifierLength = KEY_MODIFIER_SIZE_IN_BYTES ;
422435 var ivLength = _symmetricAlgorithmBlockSizeInBytes ;
423436
424- #if NET10_0_OR_GREATER
425- Span < byte > decryptedKdk = _keyDerivationKey . Length <= 256
426- ? stackalloc byte [ 256 ] . Slice ( 0 , _keyDerivationKey . Length )
427- : new byte [ _keyDerivationKey . Length ] ;
428- #else
429437 var decryptedKdk = new byte [ _keyDerivationKey . Length ] ;
430- #endif
431-
432- #if NET10_0_OR_GREATER
433- byte [ ] ? validationSubkeyArray = null ;
434- Span < byte > validationSubkey = _validationAlgorithmSubkeyLengthInBytes <= 128
435- ? stackalloc byte [ 128 ] . Slice ( 0 , _validationAlgorithmSubkeyLengthInBytes )
436- : ( validationSubkeyArray = new byte [ _validationAlgorithmSubkeyLengthInBytes ] ) ;
437- #else
438438 var validationSubkeyArray = new byte [ _validationAlgorithmSubkeyLengthInBytes ] ;
439439 var validationSubkey = validationSubkeyArray . AsSpan ( ) ;
440- #endif
441-
442- #if NET10_0_OR_GREATER
443- Span < byte > encryptionSubkey = _symmetricAlgorithmSubkeyLengthInBytes <= 128
444- ? stackalloc byte [ 128 ] . Slice ( 0 , _symmetricAlgorithmSubkeyLengthInBytes )
445- : new byte [ _symmetricAlgorithmSubkeyLengthInBytes ] ;
446- #else
447440 byte [ ] encryptionSubkey = new byte [ _symmetricAlgorithmSubkeyLengthInBytes ] ;
448- #endif
449441
450442 fixed ( byte * decryptedKdkUnsafe = decryptedKdk )
451443 fixed ( byte * __unused__1 = encryptionSubkey )
452444 fixed ( byte * __unused__2 = validationSubkeyArray )
453445 {
454446 // Step 1: Generate a random key modifier and IV for this operation.
455447 // Both will be equal to the block size of the block cipher algorithm.
456- #if NET10_0_OR_GREATER
457- Span < byte > keyModifier = keyModifierLength <= 128
458- ? stackalloc byte [ 128 ] . Slice ( 0 , keyModifierLength )
459- : new byte [ keyModifierLength ] ;
460-
461- _genRandom . GenRandom ( keyModifier ) ;
462- #else
463448 var keyModifier = _genRandom . GenRandom ( keyModifierLength ) ;
464- #endif
465449
466450 try
467451 {
@@ -475,78 +459,15 @@ public byte[] Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additiona
475459 operationSubkey : encryptionSubkey ,
476460 validationSubkey : validationSubkey ) ;
477461
478- #if NET10_0_OR_GREATER
479- // idea of optimization here is firstly get all the types preset
480- // for calculating length of the output array and allocating it.
481- // then we are filling it with the data directly, without any additional copying
482-
483- using var symmetricAlgorithm = CreateSymmetricAlgorithm ( ) ;
484- symmetricAlgorithm . SetKey ( encryptionSubkey ) ; // setKey is a single-shot usage of symmetricAlgorithm. Not allocatey
485-
486- using var validationAlgorithm = CreateValidationAlgorithm ( ) ;
487-
488- // Later framework has an API to pre-calculate optimal length of the ciphertext.
489- // That means we can avoid allocating more data than we need.
490-
491- var cipherTextLength = symmetricAlgorithm . GetCiphertextLengthCbc ( plainTextSpan . Length ) ; // CBC because symmetricAlgorithm is created with CBC mode
492- var macLength = _validationAlgorithmDigestLengthInBytes ;
493-
494- // allocating an array of a specific required length
495- var outputArray = new byte [ keyModifierLength + ivLength + cipherTextLength + macLength ] ;
496- var outputSpan = outputArray . AsSpan ( ) ;
497- #else
498462 var outputStream = new MemoryStream ( ) ;
499- #endif
500-
501- #if NET10_0_OR_GREATER
502- // Step 2: Copy the key modifier to the output stream (part of a header)
503- keyModifier . CopyTo ( outputSpan . Slice ( start : 0 , length : keyModifierLength ) ) ;
504463
505- // Step 3: Generate IV for this operation right into the output stream (no allocation)
506- // key modifier and IV together act as a header.
507- var iv = outputSpan . Slice ( start : keyModifierLength , length : ivLength ) ;
508- _genRandom . GenRandom ( iv ) ;
509- #else
510464 // Step 2: Copy the key modifier and the IV to the output stream since they'll act as a header.
511465 outputStream . Write ( keyModifier , 0 , keyModifier . Length ) ;
512466
513467 // Step 3: Generate IV for this operation right into the result array
514468 var iv = _genRandom . GenRandom ( _symmetricAlgorithmBlockSizeInBytes ) ;
515469 outputStream . Write ( iv , 0 , iv . Length ) ;
516- #endif
517470
518- #if NET10_0_OR_GREATER
519- // Step 4: Perform the encryption operation.
520- // encrypting plaintext into the target array directly
521- symmetricAlgorithm . EncryptCbc ( plainTextSpan , iv , outputSpan . Slice ( start : keyModifierLength + ivLength , length : cipherTextLength ) ) ;
522-
523- // At this point, outputStream := { keyModifier || IV || ciphertext }
524-
525- // Step 5: Calculate the digest over the IV and ciphertext.
526- // We don't need to calculate the digest over the key modifier since that
527- // value has already been mixed into the KDF used to generate the MAC key.
528-
529- var ivAndCipherTextSpan = outputSpan . Slice ( start : keyModifierLength , length : ivLength + cipherTextLength ) ;
530- var macDestinationSpan = outputSpan . Slice ( keyModifierLength + ivLength + cipherTextLength , macLength ) ;
531-
532- // if we can use an optimized method for specific algorithm - we use it (no extra alloc for subKey)
533- if ( validationAlgorithm is HMACSHA256 )
534- {
535- HMACSHA256 . HashData ( key : validationSubkey , source : ivAndCipherTextSpan , destination : macDestinationSpan ) ;
536- }
537- else if ( validationAlgorithm is HMACSHA512 )
538- {
539- HMACSHA512 . HashData ( key : validationSubkey , source : ivAndCipherTextSpan , destination : macDestinationSpan ) ;
540- }
541- else
542- {
543- validationAlgorithm . Key = validationSubkeyArray ?? validationSubkey . ToArray ( ) ;
544- validationAlgorithm . TryComputeHash ( source : ivAndCipherTextSpan , destination : macDestinationSpan , bytesWritten : out _ ) ;
545- }
546-
547- // At this point, outputArray := { keyModifier || IV || ciphertext || MAC(IV || ciphertext) }
548- return outputArray ;
549- #else
550471 // Step 4: Perform the encryption operation.
551472 using ( var symmetricAlgorithm = CreateSymmetricAlgorithm ( ) )
552473 using ( var cryptoTransform = symmetricAlgorithm . CreateEncryptor ( encryptionSubkey , iv ) )
@@ -573,17 +494,11 @@ public byte[] Encrypt(ArraySegment<byte> plaintext, ArraySegment<byte> additiona
573494 return outputStream . ToArray ( ) ;
574495 }
575496 }
576- #endif
577497 }
578498 finally
579499 {
580- #if NET10_0_OR_GREATER
581- keyModifier . Clear ( ) ;
582- decryptedKdk . Clear ( ) ;
583- #else
584500 Array . Clear ( keyModifier , 0 , keyModifierLength ) ;
585501 Array . Clear ( decryptedKdk , 0 , decryptedKdk . Length ) ;
586- #endif
587502 }
588503 }
589504 }
0 commit comments