Fix/Update #1
							
								
								
									
										323
									
								
								packages/native_crypto/test/src/aes_cipher_test.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								packages/native_crypto/test/src/aes_cipher_test.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,323 @@ | ||||
| // Author: Hugo Pointcheval | ||||
| // Email: git@pcl.ovh | ||||
| // ----- | ||||
| // File: aes_cipher_test.dart | ||||
| // Created Date: 26/05/2022 23:20:53 | ||||
| // Last Modified: 27/05/2022 16:39:44 | ||||
| // ----- | ||||
| // Copyright (c) 2022 | ||||
| 
 | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
| import 'package:native_crypto/native_crypto.dart'; | ||||
| import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart'; | ||||
| 
 | ||||
| import '../mocks/mock_native_crypto_platform.dart'; | ||||
| 
 | ||||
| void main() { | ||||
|   final MockNativeCryptoPlatform mock = MockNativeCryptoPlatform(); | ||||
|   NativeCryptoPlatform.instance = mock; | ||||
| 
 | ||||
|   setUp(() { | ||||
|     Cipher.bytesCountPerChunk = Cipher.defaultBytesCountPerChunk; | ||||
|   }); | ||||
| 
 | ||||
|   group('Constructor', () { | ||||
|     test('throws on invalid key length', () { | ||||
|       expect( | ||||
|         () => AES(SecretKey(Uint8List(0))), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>() | ||||
|               .having( | ||||
|                 (e) => e.code, | ||||
|                 'code', | ||||
|                 'invalid_key_length', | ||||
|               ) | ||||
|               .having( | ||||
|                 (e) => e.message, | ||||
|                 'message', | ||||
|                 contains('Invalid key'), | ||||
|               ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('creates a valid instance', () { | ||||
|       expect( | ||||
|         AES( | ||||
|           SecretKey(Uint8List(16)), | ||||
|         ), | ||||
|         isA<AES>(), | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   group('encrypt', () { | ||||
|     test('returns a valid cipher text wrapper', () async { | ||||
|       mock | ||||
|         ..setEncryptExpectations( | ||||
|           data: Uint8List(16), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => Uint8List(16 + 28)); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
| 
 | ||||
|       expect( | ||||
|         await aes.encrypt(Uint8List(16)), | ||||
|         isA<CipherTextWrapper>().having((e) => e.isSingle, 'is single', isTrue), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('returns a valid cipher text with multiple chunks', () async { | ||||
|       mock | ||||
|         ..setEncryptExpectations( | ||||
|           data: Uint8List(16), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => Uint8List(16 + 28)); // Returns 1 encrypted chunk | ||||
|       Cipher.bytesCountPerChunk = 16; | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
| 
 | ||||
|       expect( | ||||
|         await aes.encrypt(Uint8List(16 * 3)), | ||||
|         isA<CipherTextWrapper>().having((e) => e.isList, 'is list', isTrue), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('handles returning empty list', () async { | ||||
|       mock | ||||
|         ..setEncryptExpectations( | ||||
|           data: Uint8List(16), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => Uint8List(0)); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
| 
 | ||||
|       await expectLater( | ||||
|         () => aes.encrypt(Uint8List(16)), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>().having( | ||||
|             (e) => e.code, | ||||
|             'code', | ||||
|             'platform_returned_empty_data', | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('handles returning null', () async { | ||||
|       mock | ||||
|         ..setEncryptExpectations( | ||||
|           data: Uint8List(16), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => null); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
| 
 | ||||
|       await expectLater( | ||||
|         () => aes.encrypt(Uint8List(16)), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>().having( | ||||
|             (e) => e.code, | ||||
|             'code', | ||||
|             'platform_returned_null', | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('handles throwing PlatformException', () async { | ||||
|       mock | ||||
|         ..setEncryptExpectations( | ||||
|           data: Uint8List(16), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse( | ||||
|           () => throw PlatformException( | ||||
|             code: 'native_crypto', | ||||
|             message: 'dummy error', | ||||
|           ), | ||||
|         ); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
| 
 | ||||
|       await expectLater( | ||||
|         () => aes.encrypt(Uint8List(16)), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>() | ||||
|               .having( | ||||
|                 (e) => e.message, | ||||
|                 'message', | ||||
|                 contains( | ||||
|                   'PlatformException(native_crypto, dummy error, null, null)', | ||||
|                 ), | ||||
|               ) | ||||
|               .having( | ||||
|                 (e) => e.code, | ||||
|                 'code', | ||||
|                 'platform_throws', | ||||
|               ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   group('decrypt', () { | ||||
|     test('returns a valid Uint8List', () async { | ||||
|       mock | ||||
|         ..setDecryptExpectations( | ||||
|           data: Uint8List(16 + 28), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => Uint8List(16)); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
|       final bytes = Uint8List(16 + 28); | ||||
|       final wrapper = CipherTextWrapper.fromBytes( | ||||
|         bytes, | ||||
|         ivLength: 12, | ||||
|         tagLength: 16, | ||||
|       ); | ||||
| 
 | ||||
|       expect( | ||||
|         await aes.decrypt(wrapper), | ||||
|         isA<Uint8List>().having((e) => e.length, 'length', 16), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('returns a valid Uint8List on decrypting multiple chunks', () async { | ||||
|       const int chunkSize = 8; | ||||
|       mock | ||||
|         ..setDecryptExpectations( | ||||
|           data: Uint8List(chunkSize + 28), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => Uint8List(chunkSize)); | ||||
|       Cipher.bytesCountPerChunk = chunkSize; | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
|       final bytes = Uint8List((chunkSize + 28) * 3); | ||||
|       final wrapper = CipherTextWrapper.fromBytes( | ||||
|         bytes, | ||||
|         ivLength: 12, | ||||
|         tagLength: 16, | ||||
|       ); | ||||
| 
 | ||||
|       expect( | ||||
|         await aes.decrypt(wrapper), | ||||
|         isA<Uint8List>().having((e) => e.length, 'length', chunkSize * 3), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('handles returning empty list', () async { | ||||
|       mock | ||||
|         ..setDecryptExpectations( | ||||
|           data: Uint8List(16 + 28), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => Uint8List(0)); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
|       final bytes = Uint8List(16 + 28); | ||||
|       final wrapper = CipherTextWrapper.fromBytes( | ||||
|         bytes, | ||||
|         ivLength: 12, | ||||
|         tagLength: 16, | ||||
|       ); | ||||
| 
 | ||||
|       await expectLater( | ||||
|         () => aes.decrypt(wrapper), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>().having( | ||||
|             (e) => e.code, | ||||
|             'code', | ||||
|             'platform_returned_empty_data', | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('handles returning null', () async { | ||||
|       mock | ||||
|         ..setDecryptExpectations( | ||||
|           data: Uint8List(16 + 28), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse(() => null); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
|       final bytes = Uint8List(16 + 28); | ||||
|       final wrapper = CipherTextWrapper.fromBytes( | ||||
|         bytes, | ||||
|         ivLength: 12, | ||||
|         tagLength: 16, | ||||
|       ); | ||||
| 
 | ||||
|       await expectLater( | ||||
|         () => aes.decrypt(wrapper), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>().having( | ||||
|             (e) => e.code, | ||||
|             'code', | ||||
|             'platform_returned_null', | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     test('handles throwing PlatformException', () async { | ||||
|       mock | ||||
|         ..setDecryptExpectations( | ||||
|           data: Uint8List(16 + 28), | ||||
|           key: Uint8List(16), | ||||
|           algorithm: 'aes', | ||||
|         ) | ||||
|         ..setResponse( | ||||
|           () => throw PlatformException( | ||||
|             code: 'native_crypto', | ||||
|             message: 'dummy error', | ||||
|           ), | ||||
|         ); | ||||
| 
 | ||||
|       final aes = AES(SecretKey(Uint8List(16))); | ||||
|       final bytes = Uint8List(16 + 28); | ||||
|       final wrapper = CipherTextWrapper.fromBytes( | ||||
|         bytes, | ||||
|         ivLength: 12, | ||||
|         tagLength: 16, | ||||
|       ); | ||||
| 
 | ||||
|       await expectLater( | ||||
|         () => aes.decrypt(wrapper), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>() | ||||
|               .having( | ||||
|                 (e) => e.message, | ||||
|                 'message', | ||||
|                 contains( | ||||
|                   'PlatformException(native_crypto, dummy error, null, null)', | ||||
|                 ), | ||||
|               ) | ||||
|               .having( | ||||
|                 (e) => e.code, | ||||
|                 'code', | ||||
|                 'platform_throws', | ||||
|               ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
| @ -3,7 +3,7 @@ | ||||
| // ----- | ||||
| // File: cipher_text_wrapper_test.dart | ||||
| // Created Date: 26/05/2022 21:35:41 | ||||
| // Last Modified: 26/05/2022 22:27:31 | ||||
| // Last Modified: 27/05/2022 13:46:54 | ||||
| // ----- | ||||
| // Copyright (c) 2022 | ||||
| 
 | ||||
| @ -293,7 +293,6 @@ void main() { | ||||
|       final wrapper = CipherTextWrapper.fromBytes( | ||||
|         Uint8List.fromList([1, 2, 3]), | ||||
|         ivLength: 1, | ||||
|         messageLength: 1, | ||||
|         tagLength: 1, | ||||
|       ); | ||||
|       expect(wrapper.isSingle, isTrue); | ||||
| @ -301,11 +300,10 @@ void main() { | ||||
|     }); | ||||
| 
 | ||||
|     test('creates list from bytes when too big', () { | ||||
|       Cipher.bytesCountPerChunk = 3; | ||||
|       Cipher.bytesCountPerChunk = 1; | ||||
|       final wrapper = CipherTextWrapper.fromBytes( | ||||
|         Uint8List.fromList([1, 2, 3, 4, 5, 6]), | ||||
|         ivLength: 1, | ||||
|         messageLength: 1, | ||||
|         tagLength: 1, | ||||
|       ); | ||||
|       expect(wrapper.isList, isTrue); | ||||
| @ -317,11 +315,35 @@ void main() { | ||||
|       CipherTextWrapper.fromBytes( | ||||
|         Uint8List.fromList([1, 2, 3]), | ||||
|         ivLength: 1, | ||||
|         messageLength: 1, | ||||
|         tagLength: 1, | ||||
|         chunkSize: 3, | ||||
|       ); | ||||
|       expect(Cipher.bytesCountPerChunk, 3); | ||||
|     }); | ||||
| 
 | ||||
|     test('throws if trying to build list with bad parameters', () { | ||||
|       Cipher.bytesCountPerChunk = 1; // length of a message | ||||
| 
 | ||||
|       expect( | ||||
|         () => CipherTextWrapper.fromBytes( | ||||
|           Uint8List.fromList([1, 2, 3, 4, 5, 6]), | ||||
|           ivLength: 2, | ||||
|           tagLength: 1, | ||||
|         ), | ||||
|         throwsA( | ||||
|           isA<NativeCryptoException>() | ||||
|               .having( | ||||
|                 (e) => e.code, | ||||
|                 'code', | ||||
|                 'invalid_argument', | ||||
|               ) | ||||
|               .having( | ||||
|                 (e) => e.message, | ||||
|                 'message', | ||||
|                 contains('on chunk #'), | ||||
|               ), | ||||
|         ), | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user