@@ -137,7 +137,7 @@ public void DecryptionAlgorithmNotSupported()
137137 Assert . AreEqual ( "invalid" , e . GetProperty < string > ( "algorithm" ) ) ;
138138 }
139139
140- [ TestCaseSource ( nameof ( EncryptDecryptRoundtripsData ) ) ]
140+ [ TestCaseSource ( nameof ( GetEncryptionAlgorithms ) , methodParams : new object [ ] { true } ) ]
141141 public void EncryptDecryptRoundtrips ( EncryptionAlgorithm algorithm )
142142 {
143143 // Use a 256-bit key which will be truncated based on the selected algorithm.
@@ -171,6 +171,73 @@ public void EncryptDecryptRoundtrips(EncryptionAlgorithm algorithm)
171171#endif
172172 Assert . IsNotNull ( encrypted ) ;
173173
174+ switch ( algorithm . ToString ( ) )
175+ {
176+ // TODO: Move to new test to make sure CryptoClient and LocalCryptoClient initialize a null ICM for AES-CBC(PAD).
177+ case EncryptionAlgorithm . A128CbcValue :
178+ CollectionAssert . AreEqual (
179+ new byte [ ] { 0x63 , 0x23 , 0x21 , 0xaf , 0x94 , 0xf9 , 0xe1 , 0x21 , 0xc2 , 0xbd , 0xb1 , 0x1b , 0x04 , 0x89 , 0x8c , 0x3a } ,
180+ encrypted . Ciphertext ) ;
181+ CollectionAssert . AreEqual ( iv , encrypted . Iv ) ;
182+ Assert . IsNull ( encrypted . AuthenticationTag ) ;
183+ Assert . IsNull ( encrypted . AdditionalAuthenticatedData ) ;
184+ break ;
185+
186+ case EncryptionAlgorithm . A192CbcValue :
187+ CollectionAssert . AreEqual (
188+ new byte [ ] { 0x95 , 0x9d , 0x75 , 0x91 , 0x09 , 0x8b , 0x70 , 0x0b , 0x9c , 0xfe , 0xaf , 0xcd , 0x60 , 0x1f , 0xaa , 0x79 } ,
189+ encrypted . Ciphertext ) ;
190+ CollectionAssert . AreEqual ( iv , encrypted . Iv ) ;
191+ Assert . IsNull ( encrypted . AuthenticationTag ) ;
192+ Assert . IsNull ( encrypted . AdditionalAuthenticatedData ) ;
193+ break ;
194+
195+ case EncryptionAlgorithm . A256CbcValue :
196+ CollectionAssert . AreEqual (
197+ new byte [ ] { 0xf4 , 0xe8 , 0x5a , 0xa4 , 0xa8 , 0xb3 , 0xff , 0xc3 , 0x85 , 0x89 , 0x17 , 0x9a , 0x70 , 0x09 , 0x96 , 0x7f } ,
198+ encrypted . Ciphertext ) ;
199+ CollectionAssert . AreEqual ( iv , encrypted . Iv ) ;
200+ Assert . IsNull ( encrypted . AuthenticationTag ) ;
201+ Assert . IsNull ( encrypted . AdditionalAuthenticatedData ) ;
202+ break ;
203+
204+ case EncryptionAlgorithm . A128CbcPadValue :
205+ CollectionAssert . AreEqual (
206+ new byte [ ] { 0xec , 0xb2 , 0x63 , 0x4c , 0xe0 , 0x04 , 0xe0 , 0x31 , 0x2d , 0x9a , 0x77 , 0xb2 , 0x11 , 0xe5 , 0x28 , 0x7f } ,
207+ encrypted . Ciphertext ) ;
208+ CollectionAssert . AreEqual ( iv , encrypted . Iv ) ;
209+ Assert . IsNull ( encrypted . AuthenticationTag ) ;
210+ Assert . IsNull ( encrypted . AdditionalAuthenticatedData ) ;
211+ break ;
212+
213+ case EncryptionAlgorithm . A192CbcPadValue :
214+ CollectionAssert . AreEqual (
215+ new byte [ ] { 0xc3 , 0x4e , 0x1b , 0xe7 , 0x6e , 0xa1 , 0xf1 , 0xc3 , 0x24 , 0xae , 0x05 , 0x1b , 0x0e , 0x32 , 0xac , 0xb4 } ,
216+ encrypted . Ciphertext ) ;
217+ CollectionAssert . AreEqual ( iv , encrypted . Iv ) ;
218+ Assert . IsNull ( encrypted . AuthenticationTag ) ;
219+ Assert . IsNull ( encrypted . AdditionalAuthenticatedData ) ;
220+ break ;
221+
222+ case EncryptionAlgorithm . A256CbcPadValue :
223+ CollectionAssert . AreEqual (
224+ new byte [ ] { 0x4e , 0xbd , 0x78 , 0xda , 0x90 , 0x73 , 0xc8 , 0x97 , 0x67 , 0x2b , 0xa1 , 0x0a , 0x41 , 0x67 , 0xf8 , 0x99 } ,
225+ encrypted . Ciphertext ) ;
226+ CollectionAssert . AreEqual ( iv , encrypted . Iv ) ;
227+ Assert . IsNull ( encrypted . AuthenticationTag ) ;
228+ Assert . IsNull ( encrypted . AdditionalAuthenticatedData ) ;
229+ break ;
230+
231+ case EncryptionAlgorithm . A128GcmValue :
232+ case EncryptionAlgorithm . A192GcmValue :
233+ case EncryptionAlgorithm . A256GcmValue :
234+ Assert . IsNotNull ( encrypted . Ciphertext ) ;
235+ Assert . IsNotNull ( encrypted . Iv ) ;
236+ Assert . IsNotNull ( encrypted . AuthenticationTag ) ;
237+ CollectionAssert . AreEqual ( aad , encrypted . AdditionalAuthenticatedData ) ;
238+ break ;
239+ }
240+
174241 DecryptOptions decryptOptions = algorithm . IsAesGcm ( ) ?
175242 new DecryptOptions ( algorithm , encrypted . Ciphertext , encrypted . Iv , encrypted . AuthenticationTag , encrypted . AdditionalAuthenticatedData ) :
176243 new DecryptOptions ( algorithm , encrypted . Ciphertext , encrypted . Iv ) ;
@@ -182,19 +249,52 @@ public void EncryptDecryptRoundtrips(EncryptionAlgorithm algorithm)
182249 StringAssert . StartsWith ( "plaintext" , Encoding . UTF8 . GetString ( decrypted . Plaintext ) ) ;
183250 }
184251
185- private static IEnumerable EncryptDecryptRoundtripsData => new [ ]
252+ [ TestCaseSource ( nameof ( GetEncryptionAlgorithms ) , methodParams : new object [ ] { false } ) ]
253+ public void InitializesIv ( EncryptionAlgorithm algorithm )
254+ {
255+ // Use a 256-bit key which will be truncated based on the selected algorithm.
256+ byte [ ] k = new byte [ ] { 0xe2 , 0x7e , 0xd0 , 0xc8 , 0x45 , 0x12 , 0xbb , 0xd5 , 0x5b , 0x6a , 0xf4 , 0x34 , 0xd2 , 0x37 , 0xc1 , 0x1f , 0xeb , 0xa3 , 0x11 , 0x87 , 0x0f , 0x80 , 0xf2 , 0xc2 , 0xe3 , 0x36 , 0x42 , 0x60 , 0xf3 , 0x1c , 0x82 , 0xc8 } ;
257+
258+ JsonWebKey key = new JsonWebKey ( new [ ] { KeyOperation . Encrypt , KeyOperation . Decrypt } )
259+ {
260+ K = k ,
261+ } ;
262+
263+ AesCryptographyProvider provider = new AesCryptographyProvider ( key , null ) ;
264+
265+ byte [ ] plaintext = Encoding . UTF8 . GetBytes ( "plaintext" ) ;
266+
267+ EncryptOptions encryptOptions = new EncryptOptions ( algorithm , plaintext , null , null ) ;
268+ EncryptResult encrypted = provider . Encrypt ( encryptOptions , default ) ;
269+
270+ Assert . IsNotNull ( encryptOptions . Iv ) ;
271+ CollectionAssert . AreEqual ( encryptOptions . Iv , encrypted . Iv ) ;
272+
273+ DecryptOptions decryptOptions = new DecryptOptions ( algorithm , encrypted . Ciphertext , encrypted . Iv ) ;
274+ DecryptResult decrypted = provider . Decrypt ( decryptOptions , default ) ;
275+
276+ Assert . IsNotNull ( decrypted ) ;
277+
278+ // AES-CBC will be zero-padded.
279+ StringAssert . StartsWith ( "plaintext" , Encoding . UTF8 . GetString ( decrypted . Plaintext ) ) ;
280+ }
281+
282+ private static IEnumerable GetEncryptionAlgorithms ( bool includeAesGcm )
186283 {
187- EncryptionAlgorithm . A128Cbc ,
188- EncryptionAlgorithm . A192Cbc ,
189- EncryptionAlgorithm . A256Cbc ,
190-
191- EncryptionAlgorithm . A128CbcPad ,
192- EncryptionAlgorithm . A192CbcPad ,
193- EncryptionAlgorithm . A256CbcPad ,
194-
195- EncryptionAlgorithm . A128Gcm ,
196- EncryptionAlgorithm . A192Gcm ,
197- EncryptionAlgorithm . A256Gcm ,
198- } ;
284+ yield return EncryptionAlgorithm . A128Cbc ;
285+ yield return EncryptionAlgorithm . A192Cbc ;
286+ yield return EncryptionAlgorithm . A256Cbc ;
287+
288+ yield return EncryptionAlgorithm . A128CbcPad ;
289+ yield return EncryptionAlgorithm . A192CbcPad ;
290+ yield return EncryptionAlgorithm . A256CbcPad ;
291+
292+ if ( includeAesGcm )
293+ {
294+ yield return EncryptionAlgorithm . A128Gcm ;
295+ yield return EncryptionAlgorithm . A192Gcm ;
296+ yield return EncryptionAlgorithm . A256Gcm ;
297+ }
298+ }
199299 }
200300}
0 commit comments