feat(interface)!: add pigeon + add hmac + remove useless decryption method

This commit is contained in:
Hugo Pointcheval 2023-02-22 17:27:58 +01:00
parent ff981b2361
commit 0a040d2971
Signed by: hugo
GPG Key ID: 3AAC487E131E00BC
19 changed files with 2187 additions and 701 deletions

View File

@ -1 +1,6 @@
include: package:wyatt_analysis/analysis_options.flutter.yaml
include: package:wyatt_analysis/analysis_options.flutter.yaml
analyzer:
exclude:
- "**/*.pigeon.dart"
- "lib/src/pigeon/test_api.dart"

View File

@ -1,14 +1,15 @@
// Author: Hugo Pointcheval
// Email: git@pcl.ovh
// -----
// File: native_crypto_platform_interface.dart
// Created Date: 24/05/2022 19:39:11
// Last Modified: 24/05/2022 19:39:58
// -----
// Copyright (c) 2022
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
/// The interface that implementations of native_crypto must implement.
library native_crypto_platform_interface;
export 'src/method_channel/method_channel_native_crypto.dart';
export 'src/platform_interface/native_crypto_platform.dart';
export 'src/utils/exception.dart';
export 'src/core/enums/exception_code.dart';
export 'src/core/enums/methods.dart';
export 'src/core/exceptions/exception.dart';
export 'src/implementations/basic_message_channel_native_crypto.dart';
export 'src/implementations/method_channel_native_crypto.dart';
export 'src/interface/native_crypto_platform.dart';

View File

@ -0,0 +1,84 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
enum NativeCryptoExceptionCode {
/// The method is not implemented on the platform side.
platformMethodNotImplemented,
/// Platform returned invalid data.
/// Can be null, empty, or not the expected type.
platformReturnedInvalidData, // TODO(hpcl): remove this
/// The platforms returned null.
nullError,
/// The algorithm is not supported.
algorithmNotSupported,
/// The key is not valid. Like a bad length or format.
invalidKey,
/// The data is not valid.
invalidData,
/// The parameters are not valid. Like an invalid IV.
invalidParameters,
/// Authentication failed. Like a bad MAC or tag.
authenticationError,
/// An I/O error occurred.
ioError,
/// Key derivation failed.
keyDerivationError,
/// Channel error. Like a bad channel or a bad message.
channelError,
/// An unknown error occurred.
unknownError;
/// Returns code of the [NativeCryptoExceptionCode].
/// ```dart
/// print(NativeCryptoExceptionCode.platformMethodNotImplemented.code)
/// // => platform_method_not_implemented
/// ```
String get code {
switch (name.length) {
case 0:
return name;
case 1:
return name.toLowerCase();
default:
return name
.splitMapJoin(
RegExp('[A-Z]'),
onMatch: (m) => ' ${m[0]}',
onNonMatch: (n) => n,
)
.trim()
.splitMapJoin(
RegExp(r'\s+|-+|_+|\.+'),
onMatch: (m) => '_',
onNonMatch: (n) => n.toLowerCase(),
);
}
}
/// Returns the [NativeCryptoExceptionCode] from the given [code].
static NativeCryptoExceptionCode from(String code) {
for (final value in values) {
if (value.code == code) {
return value;
}
}
return unknownError;
}
@override
String toString() => code;
}

View File

@ -0,0 +1,17 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
enum NativeCryptoMethod {
hash,
hmac,
generateSecureRandom,
pbkdf2,
encrypt,
decrypt,
encryptFile,
decryptFile,
encryptWithIV
}

View File

@ -0,0 +1,100 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'package:equatable/equatable.dart';
import 'package:flutter/services.dart';
import 'package:native_crypto_platform_interface/src/core/enums/exception_code.dart';
/// An exception thrown by the native crypto plugin.
class NativeCryptoException extends Equatable implements Exception {
/// Creates a new [NativeCryptoException].
const NativeCryptoException({
required this.code,
this.message,
this.stackTrace,
});
/// Creates a new [NativeCryptoException] from a [PlatformException].
factory NativeCryptoException.fromPlatformException(
PlatformException platformException,
StackTrace stackTrace,
) {
final Map<String, String>? details = platformException.details != null
? Map<String, String>.from(
platformException.details as Map<String, String>,
)
: null;
String code = platformException.code.split('(').first;
String message = platformException.message ?? '';
if (details != null) {
code = details['code'] ?? code;
message = details['message'] ?? message;
}
return NativeCryptoException(
code: NativeCryptoExceptionCode.from(code),
message: message,
stackTrace: stackTrace,
);
}
/// The standardised error code.
final NativeCryptoExceptionCode code;
/// The long form message of the exception.
final String? message;
/// The stack trace which provides information to the user about the call
/// sequence that triggered an exception
final StackTrace? stackTrace;
static Never convertPlatformException(
Object exception,
StackTrace stackTrace,
) {
// If the exception is not a PlatformException, throw it as is.
if (exception is! Exception || exception is! PlatformException) {
Error.throwWithStackTrace(exception, stackTrace);
}
// Otherwise, throw a NativeCryptoException.
Error.throwWithStackTrace(
NativeCryptoException.fromPlatformException(exception, stackTrace),
stackTrace,
);
}
NativeCryptoException copyWith({
NativeCryptoExceptionCode? code,
String? message,
StackTrace? stackTrace,
}) =>
NativeCryptoException(
code: code ?? this.code,
message: message ?? this.message,
stackTrace: stackTrace ?? this.stackTrace,
);
@override
String toString() {
final output = StringBuffer('[NativeCrypto/$code]');
if (message != null) {
output.write(' $message');
}
if (stackTrace != null) {
output.write('\n\n$stackTrace');
}
return output.toString();
}
@override
List<Object?> get props => [code, message, stackTrace];
}

View File

@ -0,0 +1,204 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'package:flutter/foundation.dart';
import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
import 'package:native_crypto_platform_interface/src/pigeon/messages.pigeon.dart';
/// An implementation of [NativeCryptoPlatform] that uses Pigeon generated code.
class BasicMessageChannelNativeCrypto extends NativeCryptoPlatform {
/// The Pigeon API used to interact with the native platform.
@visibleForTesting
NativeCryptoAPI api = NativeCryptoAPI();
@override
Future<Uint8List?> hash(Uint8List data, {required String algorithm}) async {
try {
return api
.hash(
HashRequest(
data: data,
algorithm: algorithm,
),
)
.then((value) => value.hash);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> hmac(
Uint8List data, {
required Uint8List key,
required String algorithm,
}) async {
try {
return api
.hmac(
HmacRequest(
data: data,
key: key,
algorithm: algorithm,
),
)
.then((value) => value.hmac);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> generateSecureRandom(int length) async {
try {
return api
.generateSecureRandom(
GenerateSecureRandomRequest(
length: length,
),
)
.then((value) => value.random);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> pbkdf2({
required Uint8List password,
required Uint8List salt,
required int length,
required int iterations,
required String hashAlgorithm,
}) async {
try {
return api
.pbkdf2(
Pbkdf2Request(
password: password,
salt: salt,
length: length,
iterations: iterations,
hashAlgorithm: hashAlgorithm,
),
)
.then((value) => value.key);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> encrypt(
Uint8List plainText, {
required Uint8List key,
required String algorithm,
}) async {
try {
return api
.encrypt(
EncryptRequest(
plainText: plainText,
key: key,
algorithm: algorithm,
),
)
.then((value) => value.cipherText);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> decrypt(
Uint8List cipherText, {
required Uint8List key,
required String algorithm,
}) async {
try {
return api
.decrypt(
DecryptRequest(
cipherText: cipherText,
key: key,
algorithm: algorithm,
),
)
.then((value) => value.plainText);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<bool?> encryptFile({
required String plainTextPath,
required String cipherTextPath,
required Uint8List key,
required String algorithm,
}) async {
try {
return api
.encryptFile(
EncryptFileRequest(
plainTextPath: plainTextPath,
cipherTextPath: cipherTextPath,
key: key,
algorithm: algorithm,
),
)
.then((value) => value.success);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<bool?> decryptFile({
required String cipherTextPath,
required String plainTextPath,
required Uint8List key,
required String algorithm,
}) async {
try {
return api
.decryptFile(
DecryptFileRequest(
cipherTextPath: cipherTextPath,
plainTextPath: plainTextPath,
key: key,
algorithm: algorithm,
),
)
.then((value) => value.success);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> encryptWithIV({
required Uint8List plainText,
required Uint8List iv,
required Uint8List key,
required String algorithm,
}) async {
try {
return api
.encryptWithIV(
EncryptWithIVRequest(
plainText: plainText,
iv: iv,
key: key,
algorithm: algorithm,
),
)
.then((value) => value.cipherText);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
}

View File

@ -0,0 +1,161 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
/// An implementation of [NativeCryptoPlatform] that uses method channels.
class MethodChannelNativeCrypto extends NativeCryptoPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
MethodChannel channel = const MethodChannel('plugins.hugop.cl/native_crypto');
Future<T?> _invokeMethod<T>(
NativeCryptoMethod method, [
Map<String, dynamic>? arguments,
]) async {
try {
return await channel.invokeMethod<T>(method.name, arguments);
} on PlatformException catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> hash(Uint8List data, {required String algorithm}) =>
_invokeMethod<Uint8List>(
NativeCryptoMethod.hash,
{
'data': data,
'algorithm': algorithm,
},
);
@override
Future<Uint8List?> hmac(
Uint8List data, {
required Uint8List key,
required String algorithm,
}) =>
_invokeMethod<Uint8List>(
NativeCryptoMethod.hmac,
{
'data': data,
'key': key,
'algorithm': algorithm,
},
);
@override
Future<Uint8List?> generateSecureRandom(int length) =>
_invokeMethod<Uint8List>(
NativeCryptoMethod.generateSecureRandom,
{
'length': length,
},
);
@override
Future<Uint8List?> pbkdf2({
required Uint8List password,
required Uint8List salt,
required int length,
required int iterations,
required String hashAlgorithm,
}) =>
_invokeMethod<Uint8List>(
NativeCryptoMethod.pbkdf2,
{
'password': password,
'salt': salt,
'length': length,
'iterations': iterations,
'hashAlgorithm': hashAlgorithm,
},
);
@override
Future<Uint8List?> encrypt(
Uint8List plainText, {
required Uint8List key,
required String algorithm,
}) =>
_invokeMethod<Uint8List>(
NativeCryptoMethod.encrypt,
{
'plainText': plainText,
'key': key,
'algorithm': algorithm,
},
);
@override
Future<Uint8List?> decrypt(
Uint8List cipherText, {
required Uint8List key,
required String algorithm,
}) =>
_invokeMethod<Uint8List>(
NativeCryptoMethod.decrypt,
{
'cipherText': cipherText,
'key': key,
'algorithm': algorithm,
},
);
@override
Future<bool?> encryptFile({
required String plainTextPath,
required String cipherTextPath,
required Uint8List key,
required String algorithm,
}) =>
_invokeMethod<bool>(
NativeCryptoMethod.encryptFile,
{
'plainTextPath': plainTextPath,
'cipherTextPath': cipherTextPath,
'key': key,
'algorithm': algorithm,
},
);
@override
Future<bool?> decryptFile({
required String cipherTextPath,
required String plainTextPath,
required Uint8List key,
required String algorithm,
}) =>
_invokeMethod<bool>(
NativeCryptoMethod.decryptFile,
{
'cipherTextPath': cipherTextPath,
'plainTextPath': plainTextPath,
'key': key,
'algorithm': algorithm,
},
);
@override
Future<Uint8List?> encryptWithIV({
required Uint8List plainText,
required Uint8List iv,
required Uint8List key,
required String algorithm,
}) =>
_invokeMethod<Uint8List>(
NativeCryptoMethod.encryptWithIV,
{
'plainText': plainText,
'iv': iv,
'key': key,
'algorithm': algorithm,
},
);
}

View File

@ -0,0 +1,120 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'dart:typed_data';
import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
import 'package:native_crypto_platform_interface/src/implementations/method_channel_native_crypto.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
/// The interface that implementations of native_crypto must implement.
///
/// Platform implementations should extend this class rather than implement
/// it as `NativeCrypto` does not consider newly added methods to be
/// breaking changes. Extending this class (using `extends`) ensures
/// that the subclass will get the default implementation, while platform
/// implementations that `implements` this interface will be
/// broken by newly added [NativeCryptoPlatform] methods.
abstract class NativeCryptoPlatform extends PlatformInterface {
/// Constructs a NativeCryptoPlatform.
NativeCryptoPlatform() : super(token: _token);
static final Object _token = Object();
static NativeCryptoPlatform _instance = MethodChannelNativeCrypto();
/// The default instance of [NativeCryptoPlatform] to use.
///
/// Defaults to [MethodChannelNativeCrypto].
static NativeCryptoPlatform get instance => _instance;
/// Platform-specific plugins should set this with their own platform-specific
/// class that extends [NativeCryptoPlatform] when they register themselves.
static set instance(NativeCryptoPlatform instance) {
PlatformInterface.verify(instance, _token);
_instance = instance;
}
/// Returns the hash of the given data.
Future<Uint8List?> hash(Uint8List data, {required String algorithm}) {
throw UnimplementedError('hash is not implemented');
}
/// Returns the hmac of the given data using the given key.
Future<Uint8List?> hmac(
Uint8List data, {
required Uint8List key,
required String algorithm,
}) {
throw UnimplementedError('hmac is not implemented');
}
/// Generates a secure random of the given length in bytes.
Future<Uint8List?> generateSecureRandom(int length) {
throw UnimplementedError('generateSecureRandom is not implemented');
}
/// Derives a key from the given password and salt using pbkdf2.
Future<Uint8List?> pbkdf2({
required Uint8List password,
required Uint8List salt,
required int length,
required int iterations,
required String hashAlgorithm,
}) {
throw UnimplementedError('pbkdf2 is not implemented');
}
/// Encrypts the given data using the given key and algorithm.
Future<Uint8List?> encrypt(
Uint8List plainText, {
required Uint8List key,
required String algorithm,
}) {
throw UnimplementedError('encrypt is not implemented');
}
/// Decrypts the given data using the given key and algorithm.
Future<Uint8List?> decrypt(
Uint8List cipherText, {
required Uint8List key,
required String algorithm,
}) {
throw UnimplementedError('decrypt is not implemented');
}
/// Encrypts the given file using the given key and algorithm.
Future<bool?> encryptFile({
required String plainTextPath,
required String cipherTextPath,
required Uint8List key,
required String algorithm,
}) {
throw UnimplementedError('encryptFile is not implemented');
}
/// Decrypts the given file using the given key and algorithm.
Future<bool?> decryptFile({
required String cipherTextPath,
required String plainTextPath,
required Uint8List key,
required String algorithm,
}) {
throw UnimplementedError('decryptFile is not implemented');
}
/// Encrypts the given data using the given key, algorithm and iv.
///
/// Users should use [encrypt] instead if they don't need to specify the iv.
Future<Uint8List?> encryptWithIV({
required Uint8List plainText,
required Uint8List iv,
required Uint8List key,
required String algorithm,
}) {
throw UnimplementedError('encryptWithIV is not implemented');
}
}

View File

@ -1,154 +0,0 @@
// Author: Hugo Pointcheval
// Email: git@pcl.ovh
// -----
// File: native_crypto_method_channel.dart
// Created Date: 25/12/2021 16:58:04
// Last Modified: 25/05/2022 10:40:29
// -----
// Copyright (c) 2021
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:native_crypto_platform_interface/native_crypto_platform_interface.dart';
/// An implementation of [NativeCryptoPlatform] that uses method channels.
class MethodChannelNativeCrypto extends NativeCryptoPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
MethodChannel channel = const MethodChannel('plugins.hugop.cl/native_crypto');
@override
Future<Uint8List?> digest(Uint8List data, String algorithm) async {
try {
return await channel.invokeMethod<Uint8List>(
'digest',
<String, dynamic>{
'data': data,
'algorithm': algorithm,
},
);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> generateSecretKey(int bitsCount) async {
try {
return await channel.invokeMethod<Uint8List>(
'generateSecretKey',
<String, dynamic>{
'bitsCount': bitsCount,
},
);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> pbkdf2(
String password,
String salt,
int keyBytesCount,
int iterations,
String algorithm,
) async {
try {
return await channel.invokeMethod<Uint8List>(
'pbkdf2',
<String, dynamic>{
'password': password,
'salt': salt,
'keyBytesCount': keyBytesCount,
'iterations': iterations,
'algorithm': algorithm,
},
);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<List<Uint8List>?> encryptAsList(
Uint8List data,
Uint8List key,
String algorithm,
) async {
try {
return await channel.invokeListMethod(
'encryptAsList',
<String, dynamic>{
'data': data,
'key': key,
'algorithm': algorithm,
},
);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> decryptAsList(
List<Uint8List> data,
Uint8List key,
String algorithm,
) async {
try {
return await channel.invokeMethod<Uint8List>(
'decryptAsList',
<String, dynamic>{
'data': data,
'key': key,
'algorithm': algorithm,
},
);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> encrypt(
Uint8List data,
Uint8List key,
String algorithm,
) async {
try {
return await channel.invokeMethod<Uint8List>(
'encrypt',
<String, dynamic>{
'data': data,
'key': key,
'algorithm': algorithm,
},
);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
@override
Future<Uint8List?> decrypt(
Uint8List data,
Uint8List key,
String algorithm,
) async {
try {
return await channel.invokeMethod<Uint8List>(
'decrypt',
<String, dynamic>{
'data': data,
'key': key,
'algorithm': algorithm,
},
);
} catch (e, s) {
NativeCryptoException.convertPlatformException(e, s);
}
}
}

View File

@ -0,0 +1,829 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
// --
// Autogenerated from Pigeon (v9.0.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
class HashRequest {
HashRequest({
this.data,
this.algorithm,
});
Uint8List? data;
String? algorithm;
Object encode() {
return <Object?>[
data,
algorithm,
];
}
static HashRequest decode(Object result) {
result as List<Object?>;
return HashRequest(
data: result[0] as Uint8List?,
algorithm: result[1] as String?,
);
}
}
class HashResponse {
HashResponse({
this.hash,
});
Uint8List? hash;
Object encode() {
return <Object?>[
hash,
];
}
static HashResponse decode(Object result) {
result as List<Object?>;
return HashResponse(
hash: result[0] as Uint8List?,
);
}
}
class HmacRequest {
HmacRequest({
this.data,
this.key,
this.algorithm,
});
Uint8List? data;
Uint8List? key;
String? algorithm;
Object encode() {
return <Object?>[
data,
key,
algorithm,
];
}
static HmacRequest decode(Object result) {
result as List<Object?>;
return HmacRequest(
data: result[0] as Uint8List?,
key: result[1] as Uint8List?,
algorithm: result[2] as String?,
);
}
}
class HmacResponse {
HmacResponse({
this.hmac,
});
Uint8List? hmac;
Object encode() {
return <Object?>[
hmac,
];
}
static HmacResponse decode(Object result) {
result as List<Object?>;
return HmacResponse(
hmac: result[0] as Uint8List?,
);
}
}
class GenerateSecureRandomRequest {
GenerateSecureRandomRequest({
this.length,
});
int? length;
Object encode() {
return <Object?>[
length,
];
}
static GenerateSecureRandomRequest decode(Object result) {
result as List<Object?>;
return GenerateSecureRandomRequest(
length: result[0] as int?,
);
}
}
class GenerateSecureRandomResponse {
GenerateSecureRandomResponse({
this.random,
});
Uint8List? random;
Object encode() {
return <Object?>[
random,
];
}
static GenerateSecureRandomResponse decode(Object result) {
result as List<Object?>;
return GenerateSecureRandomResponse(
random: result[0] as Uint8List?,
);
}
}
class Pbkdf2Request {
Pbkdf2Request({
this.password,
this.salt,
this.length,
this.iterations,
this.hashAlgorithm,
});
Uint8List? password;
Uint8List? salt;
int? length;
int? iterations;
String? hashAlgorithm;
Object encode() {
return <Object?>[
password,
salt,
length,
iterations,
hashAlgorithm,
];
}
static Pbkdf2Request decode(Object result) {
result as List<Object?>;
return Pbkdf2Request(
password: result[0] as Uint8List?,
salt: result[1] as Uint8List?,
length: result[2] as int?,
iterations: result[3] as int?,
hashAlgorithm: result[4] as String?,
);
}
}
class Pbkdf2Response {
Pbkdf2Response({
this.key,
});
Uint8List? key;
Object encode() {
return <Object?>[
key,
];
}
static Pbkdf2Response decode(Object result) {
result as List<Object?>;
return Pbkdf2Response(
key: result[0] as Uint8List?,
);
}
}
class EncryptRequest {
EncryptRequest({
this.plainText,
this.key,
this.algorithm,
});
Uint8List? plainText;
Uint8List? key;
String? algorithm;
Object encode() {
return <Object?>[
plainText,
key,
algorithm,
];
}
static EncryptRequest decode(Object result) {
result as List<Object?>;
return EncryptRequest(
plainText: result[0] as Uint8List?,
key: result[1] as Uint8List?,
algorithm: result[2] as String?,
);
}
}
class EncryptResponse {
EncryptResponse({
this.cipherText,
});
Uint8List? cipherText;
Object encode() {
return <Object?>[
cipherText,
];
}
static EncryptResponse decode(Object result) {
result as List<Object?>;
return EncryptResponse(
cipherText: result[0] as Uint8List?,
);
}
}
class DecryptRequest {
DecryptRequest({
this.cipherText,
this.key,
this.algorithm,
});
Uint8List? cipherText;
Uint8List? key;
String? algorithm;
Object encode() {
return <Object?>[
cipherText,
key,
algorithm,
];
}
static DecryptRequest decode(Object result) {
result as List<Object?>;
return DecryptRequest(
cipherText: result[0] as Uint8List?,
key: result[1] as Uint8List?,
algorithm: result[2] as String?,
);
}
}
class DecryptResponse {
DecryptResponse({
this.plainText,
});
Uint8List? plainText;
Object encode() {
return <Object?>[
plainText,
];
}
static DecryptResponse decode(Object result) {
result as List<Object?>;
return DecryptResponse(
plainText: result[0] as Uint8List?,
);
}
}
class EncryptFileRequest {
EncryptFileRequest({
this.plainTextPath,
this.cipherTextPath,
this.key,
this.algorithm,
});
String? plainTextPath;
String? cipherTextPath;
Uint8List? key;
String? algorithm;
Object encode() {
return <Object?>[
plainTextPath,
cipherTextPath,
key,
algorithm,
];
}
static EncryptFileRequest decode(Object result) {
result as List<Object?>;
return EncryptFileRequest(
plainTextPath: result[0] as String?,
cipherTextPath: result[1] as String?,
key: result[2] as Uint8List?,
algorithm: result[3] as String?,
);
}
}
class EncryptFileResponse {
EncryptFileResponse({
this.success,
});
bool? success;
Object encode() {
return <Object?>[
success,
];
}
static EncryptFileResponse decode(Object result) {
result as List<Object?>;
return EncryptFileResponse(
success: result[0] as bool?,
);
}
}
class DecryptFileRequest {
DecryptFileRequest({
this.cipherTextPath,
this.plainTextPath,
this.key,
this.algorithm,
});
String? cipherTextPath;
String? plainTextPath;
Uint8List? key;
String? algorithm;
Object encode() {
return <Object?>[
cipherTextPath,
plainTextPath,
key,
algorithm,
];
}
static DecryptFileRequest decode(Object result) {
result as List<Object?>;
return DecryptFileRequest(
cipherTextPath: result[0] as String?,
plainTextPath: result[1] as String?,
key: result[2] as Uint8List?,
algorithm: result[3] as String?,
);
}
}
class DecryptFileResponse {
DecryptFileResponse({
this.success,
});
bool? success;
Object encode() {
return <Object?>[
success,
];
}
static DecryptFileResponse decode(Object result) {
result as List<Object?>;
return DecryptFileResponse(
success: result[0] as bool?,
);
}
}
class EncryptWithIVRequest {
EncryptWithIVRequest({
this.plainText,
this.iv,
this.key,
this.algorithm,
});
Uint8List? plainText;
Uint8List? iv;
Uint8List? key;
String? algorithm;
Object encode() {
return <Object?>[
plainText,
iv,
key,
algorithm,
];
}
static EncryptWithIVRequest decode(Object result) {
result as List<Object?>;
return EncryptWithIVRequest(
plainText: result[0] as Uint8List?,
iv: result[1] as Uint8List?,
key: result[2] as Uint8List?,
algorithm: result[3] as String?,
);
}
}
class _NativeCryptoAPICodec extends StandardMessageCodec {
const _NativeCryptoAPICodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is DecryptFileRequest) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else if (value is DecryptFileResponse) {
buffer.putUint8(129);
writeValue(buffer, value.encode());
} else if (value is DecryptRequest) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is DecryptResponse) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else if (value is EncryptFileRequest) {
buffer.putUint8(132);
writeValue(buffer, value.encode());
} else if (value is EncryptFileResponse) {
buffer.putUint8(133);
writeValue(buffer, value.encode());
} else if (value is EncryptRequest) {
buffer.putUint8(134);
writeValue(buffer, value.encode());
} else if (value is EncryptResponse) {
buffer.putUint8(135);
writeValue(buffer, value.encode());
} else if (value is EncryptWithIVRequest) {
buffer.putUint8(136);
writeValue(buffer, value.encode());
} else if (value is GenerateSecureRandomRequest) {
buffer.putUint8(137);
writeValue(buffer, value.encode());
} else if (value is GenerateSecureRandomResponse) {
buffer.putUint8(138);
writeValue(buffer, value.encode());
} else if (value is HashRequest) {
buffer.putUint8(139);
writeValue(buffer, value.encode());
} else if (value is HashResponse) {
buffer.putUint8(140);
writeValue(buffer, value.encode());
} else if (value is HmacRequest) {
buffer.putUint8(141);
writeValue(buffer, value.encode());
} else if (value is HmacResponse) {
buffer.putUint8(142);
writeValue(buffer, value.encode());
} else if (value is Pbkdf2Request) {
buffer.putUint8(143);
writeValue(buffer, value.encode());
} else if (value is Pbkdf2Response) {
buffer.putUint8(144);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return DecryptFileRequest.decode(readValue(buffer)!);
case 129:
return DecryptFileResponse.decode(readValue(buffer)!);
case 130:
return DecryptRequest.decode(readValue(buffer)!);
case 131:
return DecryptResponse.decode(readValue(buffer)!);
case 132:
return EncryptFileRequest.decode(readValue(buffer)!);
case 133:
return EncryptFileResponse.decode(readValue(buffer)!);
case 134:
return EncryptRequest.decode(readValue(buffer)!);
case 135:
return EncryptResponse.decode(readValue(buffer)!);
case 136:
return EncryptWithIVRequest.decode(readValue(buffer)!);
case 137:
return GenerateSecureRandomRequest.decode(readValue(buffer)!);
case 138:
return GenerateSecureRandomResponse.decode(readValue(buffer)!);
case 139:
return HashRequest.decode(readValue(buffer)!);
case 140:
return HashResponse.decode(readValue(buffer)!);
case 141:
return HmacRequest.decode(readValue(buffer)!);
case 142:
return HmacResponse.decode(readValue(buffer)!);
case 143:
return Pbkdf2Request.decode(readValue(buffer)!);
case 144:
return Pbkdf2Response.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
}
}
class NativeCryptoAPI {
/// Constructor for [NativeCryptoAPI]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
NativeCryptoAPI({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;
static const MessageCodec<Object?> codec = _NativeCryptoAPICodec();
Future<HashResponse> hash(HashRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.hash', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as HashResponse?)!;
}
}
Future<HmacResponse> hmac(HmacRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.hmac', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as HmacResponse?)!;
}
}
Future<GenerateSecureRandomResponse> generateSecureRandom(GenerateSecureRandomRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.generateSecureRandom', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as GenerateSecureRandomResponse?)!;
}
}
Future<Pbkdf2Response> pbkdf2(Pbkdf2Request arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.pbkdf2', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as Pbkdf2Response?)!;
}
}
Future<EncryptResponse> encrypt(EncryptRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.encrypt', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as EncryptResponse?)!;
}
}
Future<DecryptResponse> decrypt(DecryptRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.decrypt', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as DecryptResponse?)!;
}
}
Future<EncryptFileResponse> encryptFile(EncryptFileRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.encryptFile', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as EncryptFileResponse?)!;
}
}
Future<DecryptFileResponse> decryptFile(DecryptFileRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.decryptFile', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as DecryptFileResponse?)!;
}
}
Future<EncryptResponse> encryptWithIV(EncryptWithIVRequest arg_request) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.encryptWithIV', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_request]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as EncryptResponse?)!;
}
}
}

View File

@ -0,0 +1,316 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
// --
// Autogenerated from Pigeon (v9.0.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import
// ignore_for_file: avoid_relative_lib_imports
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'messages.pigeon.dart';
class _TestNativeCryptoAPICodec extends StandardMessageCodec {
const _TestNativeCryptoAPICodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is DecryptFileRequest) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else if (value is DecryptFileResponse) {
buffer.putUint8(129);
writeValue(buffer, value.encode());
} else if (value is DecryptRequest) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is DecryptResponse) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else if (value is EncryptFileRequest) {
buffer.putUint8(132);
writeValue(buffer, value.encode());
} else if (value is EncryptFileResponse) {
buffer.putUint8(133);
writeValue(buffer, value.encode());
} else if (value is EncryptRequest) {
buffer.putUint8(134);
writeValue(buffer, value.encode());
} else if (value is EncryptResponse) {
buffer.putUint8(135);
writeValue(buffer, value.encode());
} else if (value is EncryptWithIVRequest) {
buffer.putUint8(136);
writeValue(buffer, value.encode());
} else if (value is GenerateSecureRandomRequest) {
buffer.putUint8(137);
writeValue(buffer, value.encode());
} else if (value is GenerateSecureRandomResponse) {
buffer.putUint8(138);
writeValue(buffer, value.encode());
} else if (value is HashRequest) {
buffer.putUint8(139);
writeValue(buffer, value.encode());
} else if (value is HashResponse) {
buffer.putUint8(140);
writeValue(buffer, value.encode());
} else if (value is HmacRequest) {
buffer.putUint8(141);
writeValue(buffer, value.encode());
} else if (value is HmacResponse) {
buffer.putUint8(142);
writeValue(buffer, value.encode());
} else if (value is Pbkdf2Request) {
buffer.putUint8(143);
writeValue(buffer, value.encode());
} else if (value is Pbkdf2Response) {
buffer.putUint8(144);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return DecryptFileRequest.decode(readValue(buffer)!);
case 129:
return DecryptFileResponse.decode(readValue(buffer)!);
case 130:
return DecryptRequest.decode(readValue(buffer)!);
case 131:
return DecryptResponse.decode(readValue(buffer)!);
case 132:
return EncryptFileRequest.decode(readValue(buffer)!);
case 133:
return EncryptFileResponse.decode(readValue(buffer)!);
case 134:
return EncryptRequest.decode(readValue(buffer)!);
case 135:
return EncryptResponse.decode(readValue(buffer)!);
case 136:
return EncryptWithIVRequest.decode(readValue(buffer)!);
case 137:
return GenerateSecureRandomRequest.decode(readValue(buffer)!);
case 138:
return GenerateSecureRandomResponse.decode(readValue(buffer)!);
case 139:
return HashRequest.decode(readValue(buffer)!);
case 140:
return HashResponse.decode(readValue(buffer)!);
case 141:
return HmacRequest.decode(readValue(buffer)!);
case 142:
return HmacResponse.decode(readValue(buffer)!);
case 143:
return Pbkdf2Request.decode(readValue(buffer)!);
case 144:
return Pbkdf2Response.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
}
}
abstract class TestNativeCryptoAPI {
static const MessageCodec<Object?> codec = _TestNativeCryptoAPICodec();
HashResponse hash(HashRequest request);
HmacResponse hmac(HmacRequest request);
GenerateSecureRandomResponse generateSecureRandom(GenerateSecureRandomRequest request);
Pbkdf2Response pbkdf2(Pbkdf2Request request);
EncryptResponse encrypt(EncryptRequest request);
DecryptResponse decrypt(DecryptRequest request);
EncryptFileResponse encryptFile(EncryptFileRequest request);
DecryptFileResponse decryptFile(DecryptFileRequest request);
EncryptResponse encryptWithIV(EncryptWithIVRequest request);
static void setup(TestNativeCryptoAPI? api, {BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.hash', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.hash was null.');
final List<Object?> args = (message as List<Object?>?)!;
final HashRequest? arg_request = (args[0] as HashRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.hash was null, expected non-null HashRequest.');
final HashResponse output = api.hash(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.hmac', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.hmac was null.');
final List<Object?> args = (message as List<Object?>?)!;
final HmacRequest? arg_request = (args[0] as HmacRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.hmac was null, expected non-null HmacRequest.');
final HmacResponse output = api.hmac(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.generateSecureRandom', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.generateSecureRandom was null.');
final List<Object?> args = (message as List<Object?>?)!;
final GenerateSecureRandomRequest? arg_request = (args[0] as GenerateSecureRandomRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.generateSecureRandom was null, expected non-null GenerateSecureRandomRequest.');
final GenerateSecureRandomResponse output = api.generateSecureRandom(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.pbkdf2', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.pbkdf2 was null.');
final List<Object?> args = (message as List<Object?>?)!;
final Pbkdf2Request? arg_request = (args[0] as Pbkdf2Request?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.pbkdf2 was null, expected non-null Pbkdf2Request.');
final Pbkdf2Response output = api.pbkdf2(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.encrypt', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.encrypt was null.');
final List<Object?> args = (message as List<Object?>?)!;
final EncryptRequest? arg_request = (args[0] as EncryptRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.encrypt was null, expected non-null EncryptRequest.');
final EncryptResponse output = api.encrypt(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.decrypt', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.decrypt was null.');
final List<Object?> args = (message as List<Object?>?)!;
final DecryptRequest? arg_request = (args[0] as DecryptRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.decrypt was null, expected non-null DecryptRequest.');
final DecryptResponse output = api.decrypt(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.encryptFile', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.encryptFile was null.');
final List<Object?> args = (message as List<Object?>?)!;
final EncryptFileRequest? arg_request = (args[0] as EncryptFileRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.encryptFile was null, expected non-null EncryptFileRequest.');
final EncryptFileResponse output = api.encryptFile(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.decryptFile', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.decryptFile was null.');
final List<Object?> args = (message as List<Object?>?)!;
final DecryptFileRequest? arg_request = (args[0] as DecryptFileRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.decryptFile was null, expected non-null DecryptFileRequest.');
final DecryptFileResponse output = api.decryptFile(arg_request!);
return <Object?>[output];
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.NativeCryptoAPI.encryptWithIV', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMockMessageHandler(null);
} else {
channel.setMockMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.encryptWithIV was null.');
final List<Object?> args = (message as List<Object?>?)!;
final EncryptWithIVRequest? arg_request = (args[0] as EncryptWithIVRequest?);
assert(arg_request != null,
'Argument for dev.flutter.pigeon.NativeCryptoAPI.encryptWithIV was null, expected non-null EncryptWithIVRequest.');
final EncryptResponse output = api.encryptWithIV(arg_request!);
return <Object?>[output];
});
}
}
}
}

View File

@ -1,92 +0,0 @@
// Author: Hugo Pointcheval
// Email: git@pcl.ovh
// -----
// File: native_crypto_platform_interface.dart
// Created Date: 25/12/2021 16:43:49
// Last Modified: 25/05/2022 22:11:02
// -----
// Copyright (c) 2021
import 'dart:typed_data';
import 'package:native_crypto_platform_interface/src/method_channel/method_channel_native_crypto.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
/// The interface that implementations of path_provider must implement.
///
/// Platform implementations should extend this class rather than implement
/// it as `NativeCrypto` does not consider newly added methods to be
/// breaking changes. Extending this class (using `extends`) ensures
/// that the subclass will get the default implementation, while platform
/// implementations that `implements` this interface will be
/// broken by newly added [NativeCryptoPlatform] methods.
abstract class NativeCryptoPlatform extends PlatformInterface {
/// Constructs a NativeCryptoPlatform.
NativeCryptoPlatform() : super(token: _token);
static final Object _token = Object();
static NativeCryptoPlatform _instance = MethodChannelNativeCrypto();
/// The default instance of [NativeCryptoPlatform] to use.
///
/// Defaults to [MethodChannelNativeCrypto].
static NativeCryptoPlatform get instance => _instance;
/// Platform-specific plugins should set this with their own platform-specific
/// class that extends [NativeCryptoPlatform] when they register themselves.
static set instance(NativeCryptoPlatform instance) {
PlatformInterface.verify(instance, _token);
_instance = instance;
}
Future<Uint8List?> digest(Uint8List data, String algorithm) {
throw UnimplementedError('digest is not implemented');
}
Future<Uint8List?> generateSecretKey(int bitsCount) {
throw UnimplementedError('generateSecretKey is not implemented');
}
Future<Uint8List?> pbkdf2(
String password,
String salt,
int keyBytesCount,
int iterations,
String algorithm,
) {
throw UnimplementedError('pbkdf2 is not implemented');
}
Future<List<Uint8List>?> encryptAsList(
Uint8List data,
Uint8List key,
String algorithm,
) {
throw UnimplementedError('encryptAsList is not implemented');
}
Future<Uint8List?> decryptAsList(
List<Uint8List> data,
Uint8List key,
String algorithm,
) {
throw UnimplementedError('decryptAsList is not implemented');
}
Future<Uint8List?> encrypt(
Uint8List data,
Uint8List key,
String algorithm,
) {
throw UnimplementedError('encrypt is not implemented');
}
Future<Uint8List?> decrypt(
Uint8List data,
Uint8List key,
String algorithm,
) {
throw UnimplementedError('decrypt is not implemented');
}
}

View File

@ -1,126 +0,0 @@
// Author: Hugo Pointcheval
// Email: git@pcl.ovh
// -----
// File: exception.dart
// Created Date: 24/05/2022 18:54:48
// Last Modified: 26/05/2022 20:36:04
// -----
// Copyright (c) 2022
// ignore_for_file: constant_identifier_names
import 'dart:developer';
import 'package:flutter/services.dart';
enum NativeCryptoExceptionCode {
unknown,
not_implemented,
invalid_argument,
invalid_key,
invalid_key_length,
invalid_algorithm,
invalid_padding,
invalid_mode,
invalid_cipher,
invalid_data,
platform_not_supported,
platform_throws,
platform_returned_invalid_data,
platform_returned_empty_data,
platform_returned_null;
String get code => toString().split('.').last.toLowerCase();
}
class NativeCryptoException implements Exception {
NativeCryptoException({
this.message,
String? code,
this.stackTrace,
}) : code = code ?? NativeCryptoExceptionCode.unknown.code;
/// The long form message of the exception.
final String? message;
/// The optional code to accommodate the message.
final String code;
/// The stack trace which provides information to the user about the call
/// sequence that triggered an exception
final StackTrace? stackTrace;
@override
String toString() {
String output = '[NativeCryptoException/$code] $message';
if (stackTrace != null) {
output += '\n\n${stackTrace.toString()}';
}
return output;
}
/// Catches a [PlatformException] and returns an [Exception].
///
/// If the [Exception] is a [PlatformException],
/// a [NativeCryptoException] is returned.
static Never convertPlatformException(
Object exception,
StackTrace stackTrace,
) {
log(exception.toString());
if (exception is! Exception || exception is! PlatformException) {
Error.throwWithStackTrace(exception, stackTrace);
}
Error.throwWithStackTrace(
NativeCryptoException.fromPlatformException(exception, stackTrace),
stackTrace,
);
}
/// Converts a [PlatformException] into a [NativeCryptoException].
///
/// A [PlatformException] can only be converted to a [NativeCryptoException]
/// if the `details` of the exception exist.
factory NativeCryptoException.fromPlatformException(
PlatformException platformException,
StackTrace stackTrace,
) {
final Map<String, String>? details = platformException.details != null
? Map<String, String>.from(
platformException.details as Map<String, String>,
)
: null;
String code = NativeCryptoExceptionCode.unknown.code;
String message = platformException.message ?? '';
if (details != null) {
code = details['code'] ?? code;
message = details['message'] ?? message;
}
return NativeCryptoException(
message: message,
code: code,
stackTrace: stackTrace,
);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is NativeCryptoException &&
other.message == message &&
other.code == code &&
other.stackTrace == stackTrace;
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => message.hashCode ^ code.hashCode ^ stackTrace.hashCode;
}

View File

@ -0,0 +1,6 @@
Copyright 2019-2023 Hugo Pointcheval
Use of this source code is governed by an MIT-style
license that can be found in the LICENSE file or at
https://opensource.org/licenses/MIT.
--

View File

@ -0,0 +1,222 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'package:pigeon/pigeon.dart';
@ConfigurePigeon(
PigeonOptions(
copyrightHeader: 'pigeons/copyright_header.txt',
dartOut: 'lib/src/pigeon/messages.pigeon.dart',
// We export in the lib folder to expose the class to other packages.
dartTestOut: 'lib/src/pigeon/test_api.dart',
javaOut:
'../native_crypto_android/android/src/main/java/fr/pointcheval/native_crypto_android/GeneratedAndroidNativeCrypto.java',
javaOptions: JavaOptions(
package: 'fr.pointcheval.native_crypto_android',
className: 'GeneratedAndroidNativeCrypto',
),
objcHeaderOut: '../native_crypto_ios/ios/Classes/Public/messages.g.h',
objcSourceOut: '../native_crypto_ios/ios/Classes/messages.g.m',
),
)
class HashRequest {
const HashRequest({
this.data,
this.algorithm,
});
final Uint8List? data;
final String? algorithm;
}
class HashResponse {
const HashResponse({
this.hash,
});
final Uint8List? hash;
}
class HmacRequest {
const HmacRequest({
this.data,
this.key,
this.algorithm,
});
final Uint8List? data;
final Uint8List? key;
final String? algorithm;
}
class HmacResponse {
const HmacResponse({
this.hmac,
});
final Uint8List? hmac;
}
class GenerateSecureRandomRequest {
const GenerateSecureRandomRequest({
this.length,
});
final int? length;
}
class GenerateSecureRandomResponse {
const GenerateSecureRandomResponse({
this.random,
});
final Uint8List? random;
}
class Pbkdf2Request {
const Pbkdf2Request({
this.password,
this.salt,
this.length,
this.iterations,
this.hashAlgorithm,
});
final Uint8List? password;
final Uint8List? salt;
final int? length;
final int? iterations;
final String? hashAlgorithm;
}
class Pbkdf2Response {
const Pbkdf2Response({
this.key,
});
final Uint8List? key;
}
class EncryptRequest {
const EncryptRequest({
this.plainText,
this.key,
this.algorithm,
});
final Uint8List? plainText;
final Uint8List? key;
final String? algorithm;
}
class EncryptResponse {
const EncryptResponse({
this.cipherText,
});
final Uint8List? cipherText;
}
class DecryptRequest {
const DecryptRequest({
this.cipherText,
this.key,
this.algorithm,
});
final Uint8List? cipherText;
final Uint8List? key;
final String? algorithm;
}
class DecryptResponse {
const DecryptResponse({
this.plainText,
});
final Uint8List? plainText;
}
class EncryptFileRequest {
const EncryptFileRequest({
this.plainTextPath,
this.cipherTextPath,
this.key,
this.algorithm,
});
final String? plainTextPath;
final String? cipherTextPath;
final Uint8List? key;
final String? algorithm;
}
class EncryptFileResponse {
const EncryptFileResponse({
this.success,
});
final bool? success;
}
class DecryptFileRequest {
const DecryptFileRequest({
this.cipherTextPath,
this.plainTextPath,
this.key,
this.algorithm,
});
final String? cipherTextPath;
final String? plainTextPath;
final Uint8List? key;
final String? algorithm;
}
class DecryptFileResponse {
const DecryptFileResponse({
this.success,
});
final bool? success;
}
class EncryptWithIVRequest {
const EncryptWithIVRequest({
this.plainText,
this.iv,
this.key,
this.algorithm,
});
final Uint8List? plainText;
final Uint8List? iv;
final Uint8List? key;
final String? algorithm;
}
@HostApi(dartHostTestHandler: 'TestNativeCryptoAPI')
abstract class NativeCryptoAPI {
HashResponse hash(HashRequest request);
HmacResponse hmac(HmacRequest request);
GenerateSecureRandomResponse generateSecureRandom(
GenerateSecureRandomRequest request,
);
Pbkdf2Response pbkdf2(Pbkdf2Request request);
EncryptResponse encrypt(EncryptRequest request);
DecryptResponse decrypt(DecryptRequest request);
EncryptFileResponse encryptFile(EncryptFileRequest request);
DecryptFileResponse decryptFile(DecryptFileRequest request);
EncryptResponse encryptWithIV(EncryptWithIVRequest request);
}

View File

@ -7,19 +7,19 @@ environment:
flutter: ">=2.5.0"
dependencies:
flutter:
sdk: flutter
equatable: ^2.0.5
flutter: { sdk: flutter }
plugin_platform_interface: ^2.1.3
dev_dependencies:
flutter_test:
sdk: flutter
flutter_test: { sdk: flutter }
mockito: ^5.3.2
pigeon: ^9.0.0
wyatt_analysis:
hosted:
url: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
name: wyatt_analysis
version: 2.3.0
version: 2.4.0

View File

@ -1,175 +0,0 @@
// Author: Hugo Pointcheval
// Email: git@pcl.ovh
// -----
// File: method_channel_native_crypto_test.dart
// Created Date: 25/05/2022 22:47:41
// Last Modified: 25/05/2022 23:22:44
// -----
// Copyright (c) 2022
import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:native_crypto_platform_interface/src/method_channel/method_channel_native_crypto.dart';
void main() {
TestWidgetsFlutterBinding
.ensureInitialized(); // Required for setMockMethodCallHandler
group('$MethodChannelNativeCrypto', () {
const MethodChannel channel =
MethodChannel('plugins.hugop.cl/native_crypto');
final List<MethodCall> log = <MethodCall>[];
final MethodChannelNativeCrypto nativeCrypto = MethodChannelNativeCrypto();
TestDefaultBinaryMessengerBinding.instance?.defaultBinaryMessenger
.setMockMethodCallHandler(channel, (MethodCall call) async {
log.add(call);
return null;
});
// Run after each test.
tearDown(log.clear);
test('digest', () async {
await nativeCrypto.digest(Uint8List(0), 'sha256');
expect(
log,
<Matcher>[
isMethodCall(
'digest',
arguments: <String, dynamic>{
'data': Uint8List(0),
'algorithm': 'sha256',
},
),
],
);
});
test('generateSecretKey', () async {
await nativeCrypto.generateSecretKey(256);
expect(
log,
<Matcher>[
isMethodCall(
'generateSecretKey',
arguments: <String, dynamic>{
'bitsCount': 256,
},
),
],
);
});
test('pbkdf2', () async {
await nativeCrypto.pbkdf2(
'password',
'salt',
32,
10000,
'sha256',
);
expect(
log,
<Matcher>[
isMethodCall(
'pbkdf2',
arguments: <String, dynamic>{
'password': 'password',
'salt': 'salt',
'keyBytesCount': 32,
'iterations': 10000,
'algorithm': 'sha256',
},
),
],
);
});
test('encryptAsList', () async {
await nativeCrypto.encryptAsList(
Uint8List(0),
Uint8List(0),
'aes',
);
expect(
log,
<Matcher>[
isMethodCall(
'encryptAsList',
arguments: <String, dynamic>{
'data': Uint8List(0),
'key': Uint8List(0),
'algorithm': 'aes',
},
),
],
);
});
test('decryptAsList', () async {
await nativeCrypto.decryptAsList(
[Uint8List(0)],
Uint8List(0),
'aes',
);
expect(
log,
<Matcher>[
isMethodCall(
'decryptAsList',
arguments: <String, dynamic>{
'data': [Uint8List(0)],
'key': Uint8List(0),
'algorithm': 'aes',
},
),
],
);
});
test('encrypt', () async {
await nativeCrypto.encrypt(
Uint8List(0),
Uint8List(0),
'aes',
);
expect(
log,
<Matcher>[
isMethodCall(
'encrypt',
arguments: <String, dynamic>{
'data': Uint8List(0),
'key': Uint8List(0),
'algorithm': 'aes',
},
),
],
);
});
test('decrypt', () async {
await nativeCrypto.decrypt(
Uint8List(0),
Uint8List(0),
'aes',
);
expect(
log,
<Matcher>[
isMethodCall(
'decrypt',
arguments: <String, dynamic>{
'data': Uint8List(0),
'key': Uint8List(0),
'algorithm': 'aes',
},
),
],
);
});
});
}

View File

@ -0,0 +1,72 @@
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'package:flutter_test/flutter_test.dart';
import 'package:native_crypto_platform_interface/src/core/enums/exception_code.dart';
import 'package:native_crypto_platform_interface/src/core/exceptions/exception.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('$NativeCryptoException', () {
test('should return a formatted message with only code', () async {
const e = NativeCryptoException(
code: NativeCryptoExceptionCode.unknownError,
);
expect(e.toString(), '[NativeCrypto/unknown_error]');
});
test('should return a formatted message', () async {
const e = NativeCryptoException(
code: NativeCryptoExceptionCode.unknownError,
message: 'foo',
);
expect(e.toString(), '[NativeCrypto/unknown_error] foo');
});
test('should return a formatted message with a stack trace', () async {
const e = NativeCryptoException(
code: NativeCryptoExceptionCode.unknownError,
message: 'foo',
);
expect(e.toString(), '[NativeCrypto/unknown_error] foo');
});
test('should return a formatted message with a stack trace', () async {
final e = NativeCryptoException(
code: NativeCryptoExceptionCode.unknownError,
message: 'foo',
stackTrace: StackTrace.current,
);
// Anything with a stack trace adds 2 blanks lines following the message.
expect(e.toString(), startsWith('[NativeCrypto/unknown_error] foo\n\n'));
});
test('should override the == operator', () async {
const e1 = NativeCryptoException(
code: NativeCryptoExceptionCode.unknownError,
message: 'foo',
);
const e2 = NativeCryptoException(
code: NativeCryptoExceptionCode.unknownError,
message: 'foo',
);
const e3 = NativeCryptoException(
code: NativeCryptoExceptionCode.unknownError,
message: 'foo',
);
expect(e1 == e2, true);
expect(e1 != e3, false);
});
});
}

View File

@ -1,43 +1,42 @@
// Author: Hugo Pointcheval
// Email: git@pcl.ovh
// -----
// File: native_crypto_platform_test.dart
// Created Date: 25/05/2022 21:43:25
// Last Modified: 25/05/2022 23:26:18
// -----
// Copyright (c) 2022
// Copyright 2019-2023 Hugo Pointcheval
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'dart:typed_data';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:native_crypto_platform_interface/src/platform_interface/native_crypto_platform.dart';
import 'package:native_crypto_platform_interface/src/implementations/basic_message_channel_native_crypto.dart';
import 'package:native_crypto_platform_interface/src/implementations/method_channel_native_crypto.dart';
import 'package:native_crypto_platform_interface/src/interface/native_crypto_platform.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
class ImplementsNativeCryptoPlatform
// ignore: prefer_mixin
with Mock
implements NativeCryptoPlatform {}
class ExtendsNativeCryptoPlatform extends NativeCryptoPlatform {}
class NativeCryptoMockPlatform extends Mock
with
// ignore: prefer_mixin, plugin_platform_interface needs to migrate to use `mixin`
MockPlatformInterfaceMixin
implements
NativeCryptoPlatform {}
void main() {
late ExtendsNativeCryptoPlatform nativeCryptoPlatform;
TestWidgetsFlutterBinding.ensureInitialized();
group('$NativeCryptoPlatform', () {
setUpAll(() {
nativeCryptoPlatform = ExtendsNativeCryptoPlatform();
});
test('Constructor', () {
expect(nativeCryptoPlatform, isA<NativeCryptoPlatform>());
expect(nativeCryptoPlatform, isA<PlatformInterface>());
// should allow read of default app from native
test('$MethodChannelNativeCrypto is the default instance', () {
expect(NativeCryptoPlatform.instance, isA<MethodChannelNativeCrypto>());
});
test('get.instance', () {
expect(
NativeCryptoPlatform.instance,
isA<NativeCryptoPlatform>(),
);
});
test('set.instance', () {
test('Can be extended', () {
NativeCryptoPlatform.instance = ExtendsNativeCryptoPlatform();
expect(
NativeCryptoPlatform.instance,
isA<NativeCryptoPlatform>(),
);
});
test('Cannot be implemented with `implements`', () {
@ -45,122 +44,19 @@ void main() {
() {
NativeCryptoPlatform.instance = ImplementsNativeCryptoPlatform();
},
throwsA(isInstanceOf<AssertionError>()),
throwsA(anything),
);
});
test('Can be mocked with `implements`', () {
final MockNativeCryptoPlatform mock = MockNativeCryptoPlatform();
final NativeCryptoMockPlatform mock = NativeCryptoMockPlatform();
NativeCryptoPlatform.instance = mock;
});
test('Can be extended', () {
NativeCryptoPlatform.instance = ExtendsNativeCryptoPlatform();
});
test('throws if .digest() not implemented', () async {
await expectLater(
() => nativeCryptoPlatform.digest(Uint8List(0), 'sha256'),
throwsA(
isA<UnimplementedError>().having(
(e) => e.message,
'message',
'digest is not implemented',
),
),
);
});
test('throws if .generateSecretKey() not implemented', () async {
await expectLater(
() => nativeCryptoPlatform.generateSecretKey(256),
throwsA(
isA<UnimplementedError>().having(
(e) => e.message,
'message',
'generateSecretKey is not implemented',
),
),
);
});
test('throws if .pbkdf2() not implemented', () async {
await expectLater(
() => nativeCryptoPlatform.pbkdf2('password', 'salt', 0, 0, 'sha256'),
throwsA(
isA<UnimplementedError>().having(
(e) => e.message,
'message',
'pbkdf2 is not implemented',
),
),
);
});
test('throws if .encryptAsList() not implemented', () async {
await expectLater(
() => nativeCryptoPlatform.encryptAsList(
Uint8List(0),
Uint8List(0),
'aes',
),
throwsA(
isA<UnimplementedError>().having(
(e) => e.message,
'message',
'encryptAsList is not implemented',
),
),
);
});
test('throws if .decryptAsList() not implemented', () async {
await expectLater(
() => nativeCryptoPlatform
.decryptAsList([Uint8List(0)], Uint8List(0), 'aes'),
throwsA(
isA<UnimplementedError>().having(
(e) => e.message,
'message',
'decryptAsList is not implemented',
),
),
);
});
test('throws if .encrypt() not implemented', () async {
await expectLater(
() => nativeCryptoPlatform.encrypt(Uint8List(0), Uint8List(0), 'aes'),
throwsA(
isA<UnimplementedError>().having(
(e) => e.message,
'message',
'encrypt is not implemented',
),
),
);
});
test('throws if .decrypt() not implemented', () async {
await expectLater(
() => nativeCryptoPlatform.decrypt(Uint8List(0), Uint8List(0), 'aes'),
throwsA(
isA<UnimplementedError>().having(
(e) => e.message,
'message',
'decrypt is not implemented',
),
),
);
test('Can set with $BasicMessageChannelNativeCrypto', () {
final BasicMessageChannelNativeCrypto pigeon =
BasicMessageChannelNativeCrypto();
NativeCryptoPlatform.instance = pigeon;
});
});
}
class ExtendsNativeCryptoPlatform extends NativeCryptoPlatform {}
class ImplementsNativeCryptoPlatform extends Mock
implements NativeCryptoPlatform {}
class MockNativeCryptoPlatform extends Mock
with MockPlatformInterfaceMixin
implements NativeCryptoPlatform {}