test: add cipher tests
This commit is contained in:
parent
ebdcf00c15
commit
cefa73ec3d
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
|
// File: cipher_text_wrapper_test.dart
|
||||||
// Created Date: 26/05/2022 21:35:41
|
// 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
|
// Copyright (c) 2022
|
||||||
|
|
||||||
@ -293,7 +293,6 @@ void main() {
|
|||||||
final wrapper = CipherTextWrapper.fromBytes(
|
final wrapper = CipherTextWrapper.fromBytes(
|
||||||
Uint8List.fromList([1, 2, 3]),
|
Uint8List.fromList([1, 2, 3]),
|
||||||
ivLength: 1,
|
ivLength: 1,
|
||||||
messageLength: 1,
|
|
||||||
tagLength: 1,
|
tagLength: 1,
|
||||||
);
|
);
|
||||||
expect(wrapper.isSingle, isTrue);
|
expect(wrapper.isSingle, isTrue);
|
||||||
@ -301,11 +300,10 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('creates list from bytes when too big', () {
|
test('creates list from bytes when too big', () {
|
||||||
Cipher.bytesCountPerChunk = 3;
|
Cipher.bytesCountPerChunk = 1;
|
||||||
final wrapper = CipherTextWrapper.fromBytes(
|
final wrapper = CipherTextWrapper.fromBytes(
|
||||||
Uint8List.fromList([1, 2, 3, 4, 5, 6]),
|
Uint8List.fromList([1, 2, 3, 4, 5, 6]),
|
||||||
ivLength: 1,
|
ivLength: 1,
|
||||||
messageLength: 1,
|
|
||||||
tagLength: 1,
|
tagLength: 1,
|
||||||
);
|
);
|
||||||
expect(wrapper.isList, isTrue);
|
expect(wrapper.isList, isTrue);
|
||||||
@ -317,11 +315,35 @@ void main() {
|
|||||||
CipherTextWrapper.fromBytes(
|
CipherTextWrapper.fromBytes(
|
||||||
Uint8List.fromList([1, 2, 3]),
|
Uint8List.fromList([1, 2, 3]),
|
||||||
ivLength: 1,
|
ivLength: 1,
|
||||||
messageLength: 1,
|
|
||||||
tagLength: 1,
|
tagLength: 1,
|
||||||
chunkSize: 3,
|
chunkSize: 3,
|
||||||
);
|
);
|
||||||
expect(Cipher.bytesCountPerChunk, 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