44using System . Buffers . Binary ;
55using System . Globalization ;
66using System . Net ;
7+ using System . Security . Cryptography ;
78using System . Text ;
89using Microsoft . AspNetCore . DataProtection . AuthenticatedEncryption ;
910using Microsoft . AspNetCore . DataProtection . AuthenticatedEncryption . ConfigurationModel ;
1011using Microsoft . AspNetCore . DataProtection . KeyManagement . Internal ;
12+ using Microsoft . AspNetCore . DataProtection . Managed ;
1113using Microsoft . AspNetCore . InternalTesting ;
1214using Microsoft . Extensions . DependencyInjection ;
1315using Microsoft . Extensions . Logging ;
@@ -620,11 +622,87 @@ public void CreateProtector_ChainsPurposes()
620622 Assert . Equal ( expectedProtectedData , retVal ) ;
621623 }
622624
623- [ Fact ]
624- public void GetProtectedSize_TryProtect_CorrectlyEstimatesDataLength ( )
625+ [ Theory ]
626+ [ InlineData ( "" , EncryptionAlgorithm . AES_128_CBC , ValidationAlgorithm . HMACSHA256 ) ]
627+ [ InlineData ( "small" , EncryptionAlgorithm . AES_128_CBC , ValidationAlgorithm . HMACSHA256 ) ]
628+ [ InlineData ( "This is a medium length plaintext message" , EncryptionAlgorithm . AES_128_CBC , ValidationAlgorithm . HMACSHA256 ) ]
629+ [ InlineData ( "This is a very long plaintext message that spans multiple blocks and should test the encryption and size estimation with larger payloads to ensure everything works correctly" , EncryptionAlgorithm . AES_128_CBC , ValidationAlgorithm . HMACSHA256 ) ]
630+ [ InlineData ( "small" , EncryptionAlgorithm . AES_256_CBC , ValidationAlgorithm . HMACSHA256 ) ]
631+ [ InlineData ( "This is a medium length plaintext message" , EncryptionAlgorithm . AES_256_CBC , ValidationAlgorithm . HMACSHA512 ) ]
632+ [ InlineData ( "small" , EncryptionAlgorithm . AES_128_GCM , ValidationAlgorithm . HMACSHA256 ) ]
633+ [ InlineData ( "This is a medium length plaintext message" , EncryptionAlgorithm . AES_256_GCM , ValidationAlgorithm . HMACSHA256 ) ]
634+ public void GetProtectedSize_TryProtect_CorrectlyEstimatesDataLength_MultipleScenarios ( string plaintextStr , EncryptionAlgorithm encryptionAlgorithm , ValidationAlgorithm validationAlgorithm )
625635 {
626636 // Arrange
627- byte [ ] plaintext = new byte [ ] { 0x10 , 0x20 , 0x30 , 0x40 , 0x50 } ;
637+ byte [ ] plaintext = Encoding . UTF8 . GetBytes ( plaintextStr ) ;
638+ var encryptorFactory = new AuthenticatedEncryptorFactory ( NullLoggerFactory . Instance ) ;
639+
640+ // Create a configuration for the specified encryption and validation algorithms
641+ var configuration = new AuthenticatedEncryptorConfiguration
642+ {
643+ EncryptionAlgorithm = encryptionAlgorithm ,
644+ ValidationAlgorithm = validationAlgorithm
645+ } ;
646+
647+ Key key = new Key ( Guid . NewGuid ( ) , DateTimeOffset . Now , DateTimeOffset . Now , DateTimeOffset . Now , configuration . CreateNewDescriptor ( ) , new [ ] { encryptorFactory } ) ;
648+ var keyRing = new KeyRing ( key , new [ ] { key } ) ;
649+ var mockKeyRingProvider = new Mock < IKeyRingProvider > ( ) ;
650+ mockKeyRingProvider . Setup ( o => o . GetCurrentKeyRing ( ) ) . Returns ( keyRing ) ;
651+
652+ var protector = new KeyRingBasedDataProtector (
653+ keyRingProvider : mockKeyRingProvider . Object ,
654+ logger : GetLogger ( ) ,
655+ originalPurposes : null ,
656+ newPurpose : "purpose" ) ;
657+
658+ // Act - get estimated size
659+ int estimatedSize = protector . GetProtectedSize ( plaintext ) ;
660+
661+ // verify simple protect works
662+ var protectedData = protector . Protect ( plaintext ) ;
663+
664+ // Act - allocate buffer and try protect
665+ byte [ ] destination = new byte [ estimatedSize ] ;
666+ bool success = protector . TryProtect ( plaintext , destination , out int bytesWritten ) ;
667+
668+ // Assert
669+ Assert . True ( success , $ "TryProtect should succeed with estimated buffer size for { encryptionAlgorithm } ") ;
670+ Assert . Equal ( estimatedSize , bytesWritten ) ;
671+ Assert . True ( bytesWritten > 0 , "Should write some bytes" ) ;
672+ Assert . True ( bytesWritten >= plaintext . Length , "Protected data should be at least as large as plaintext" ) ;
673+
674+ // Verify the protected data can be unprotected to get original plaintext
675+ byte [ ] actualDestination = new byte [ bytesWritten ] ;
676+ Array . Copy ( destination , actualDestination , bytesWritten ) ;
677+ byte [ ] unprotectedData = protector . Unprotect ( actualDestination ) ;
678+ Assert . Equal ( plaintext , unprotectedData ) ;
679+
680+ // Additional verification: test with regular Protect method to ensure consistency
681+ byte [ ] protectedDataRegular = protector . Protect ( plaintext ) ;
682+ Assert . Equal ( estimatedSize , protectedDataRegular . Length ) ;
683+ byte [ ] unprotectedDataRegular = protector . Unprotect ( protectedDataRegular ) ;
684+ Assert . Equal ( plaintext , unprotectedDataRegular ) ;
685+ }
686+
687+ [ Theory ]
688+ [ InlineData ( 16 ) ] // 16 bytes
689+ [ InlineData ( 32 ) ] // 32 bytes
690+ [ InlineData ( 64 ) ] // 64 bytes
691+ [ InlineData ( 128 ) ] // 128 bytes
692+ [ InlineData ( 256 ) ] // 256 bytes
693+ [ InlineData ( 512 ) ] // 512 bytes
694+ [ InlineData ( 1024 ) ] // 1 KB
695+ [ InlineData ( 4096 ) ] // 4 KB
696+ public void GetProtectedSize_TryProtect_VariousPlaintextSizes ( int plaintextSize )
697+ {
698+ // Arrange
699+ byte [ ] plaintext = new byte [ plaintextSize ] ;
700+ // Fill with a pattern to make debugging easier if needed
701+ for ( int i = 0 ; i < plaintextSize ; i ++ )
702+ {
703+ plaintext [ i ] = ( byte ) ( i % 256 ) ;
704+ }
705+
628706 var encryptorFactory = new AuthenticatedEncryptorFactory ( NullLoggerFactory . Instance ) ;
629707 Key key = new Key ( Guid . NewGuid ( ) , DateTimeOffset . Now , DateTimeOffset . Now , DateTimeOffset . Now , new AuthenticatedEncryptorConfiguration ( ) . CreateNewDescriptor ( ) , new [ ] { encryptorFactory } ) ;
630708 var keyRing = new KeyRing ( key , new [ ] { key } ) ;
@@ -645,7 +723,7 @@ public void GetProtectedSize_TryProtect_CorrectlyEstimatesDataLength()
645723 bool success = protector . TryProtect ( plaintext , destination , out int bytesWritten ) ;
646724
647725 // Assert
648- Assert . True ( success , "TryProtect should succeed with estimated buffer size" ) ;
726+ Assert . True ( success , $ "TryProtect should succeed with estimated buffer size for { plaintextSize } byte plaintext ") ;
649727 Assert . Equal ( estimatedSize , bytesWritten ) ;
650728 Assert . True ( bytesWritten > 0 , "Should write some bytes" ) ;
651729 Assert . True ( bytesWritten >= plaintext . Length , "Protected data should be at least as large as plaintext" ) ;
0 commit comments