Skip to content

Commit

Permalink
Merge branch 'october' into EUDI
Browse files Browse the repository at this point in the history
  • Loading branch information
hawkbee1 committed May 23, 2024
2 parents 300dadd + d6a8815 commit 469c3d2
Show file tree
Hide file tree
Showing 175 changed files with 9,940 additions and 2,801 deletions.
14 changes: 0 additions & 14 deletions .github/workflows/polygonid.yaml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: key_generator
name: secure_storage

on: [ pull_request, push ]
on: [pull_request, push]

jobs:
build:
Expand All @@ -9,6 +9,6 @@ jobs:
flutter_channel: stable
flutter_version: 3.19.6
min_coverage: 30
working_directory: packages/key_generator
working_directory: packages/secure_storage
dart_sdk: 3.3.4
build_runner: false
70 changes: 29 additions & 41 deletions lib/app/shared/dio_client/dio_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,35 +55,14 @@ class DioClient {
bool isCachingEnabled = false,
}) async {
try {
final isInternetAvailable = await isConnected();
if (!isInternetAvailable) {
throw NetworkException(
message: NetworkError.NETWORK_ERROR_NO_INTERNET_CONNECTION,
);
}

final stopwatch = Stopwatch()..start();
await getSpecificHeader(uri, headers);
log.i('uri - $uri');

final cachedData = await secureStorageProvider.get(uri);
dynamic response;

if (!isCachingEnabled || cachedData == null) {
response = await dio.get<dynamic>(
uri,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
);
} else {
final cachedDataJson = jsonDecode(cachedData);
final expiry = int.parse(cachedDataJson['expiry'].toString());

final isExpired = DateTime.now().millisecondsSinceEpoch > expiry;

if (isExpired) {
if (isCachingEnabled) {
final cachedData = await secureStorageProvider.get(uri);
if (cachedData == null) {
response = await dio.get<dynamic>(
uri,
queryParameters: queryParameters,
Expand All @@ -92,18 +71,34 @@ class DioClient {
onReceiveProgress: onReceiveProgress,
);
} else {
/// directly return cached data
/// returned here to avoid the caching override everytime
final response = await cachedDataJson['data'];
log.i('Time - ${stopwatch.elapsed}');
return response;
final cachedDataJson = jsonDecode(cachedData);
final expiry = int.parse(cachedDataJson['expiry'].toString());

final isExpired = DateTime.now().millisecondsSinceEpoch > expiry;
if (isExpired) {
response = await dio.get<dynamic>(
uri,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
);
} else {
/// directly return cached data
/// returned here to avoid the caching override everytime
final response = await cachedDataJson['data'];
return response;
}
}
} else {
response = await dio.get<dynamic>(
uri,
queryParameters: queryParameters,
options: options,
cancelToken: cancelToken,
onReceiveProgress: onReceiveProgress,
);
}
final expiry =
DateTime.now().add(const Duration(days: 2)).millisecondsSinceEpoch;

final value = {'expiry': expiry, 'data': response.data};
await secureStorageProvider.set(uri, jsonEncode(value));

log.i('Time - ${stopwatch.elapsed}');
return response.data;
Expand Down Expand Up @@ -153,13 +148,6 @@ class DioClient {
},
}) async {
try {
final isInternetAvailable = await isConnected();
if (!isInternetAvailable) {
throw NetworkException(
message: NetworkError.NETWORK_ERROR_NO_INTERNET_CONNECTION,
);
}

final stopwatch = Stopwatch()..start();
await getSpecificHeader(uri, headers);
final response = await dio.post<dynamic>(
Expand Down
3 changes: 1 addition & 2 deletions lib/app/shared/enum/credential_category.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ extension CredentialCategoryX on CredentialCategory {
}
}

CredentialCategoryConfig config(BuildContext context) {
final l10n = context.l10n;
CredentialCategoryConfig config(AppLocalizations l10n) {
switch (this) {
case CredentialCategory.advantagesCards:
return CredentialCategoryConfig(
Expand Down
1 change: 1 addition & 0 deletions lib/app/shared/enum/status/status.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export 'app_status.dart';
export 'beacon_status.dart';
export 'credential_detail_tab_status.dart';
export 'credential_status.dart';
export 'credential_status_extension.dart';
export 'credentials_status.dart';
export 'home_status.dart';
export 'kyc_verification_status.dart';
Expand Down
1 change: 0 additions & 1 deletion lib/app/shared/extension/extension.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export 'bigint_extension.dart';
export 'credential_status.dart';
export 'double_extension.dart';
export 'iterable_extension.dart';
export 'string_extension.dart';
Expand Down
97 changes: 71 additions & 26 deletions lib/app/shared/helper_functions/helper_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import 'package:oidc4vc/oidc4vc.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:secure_storage/secure_storage.dart';
import 'package:x509/x509.dart' as x509;
import 'package:x509/x509.dart';

String generateDefaultAccountName(
int accountIndex,
Expand Down Expand Up @@ -74,11 +75,15 @@ KeyStoreModel getKeysFromSecretKey({required String secretKey}) {
);
}

String stringToHexPrefixedWith05({required String payload}) {
String stringToHexPrefixedWith05({
required String payload,
DateTime? dateTime,
}) {
dateTime ??= DateTime.now();
final String formattedInput = <String>[
'Tezos Signed Message:',
'altme.io',
DateTime.now().toString(),
dateTime.toString(),
payload,
].join(' ');

Expand Down Expand Up @@ -199,7 +204,7 @@ Future<bool> isCredentialAvaialble({
credential
.credentialPreview.credentialSubjectModel.credentialSubjectType;

final matchFormat = vcFormatType.value == credential.format;
final matchFormat = vcFormatType.vcValue == credential.format;
if (matchSubjectType && matchFormat) {
return true;
}
Expand Down Expand Up @@ -237,11 +242,13 @@ Future<bool> getStoragePermission() async {
return false;
}

String getDateTimeWithoutSpace() {
final dateTime = DateTime.fromMicrosecondsSinceEpoch(
DateTime.now().microsecondsSinceEpoch,
String getDateTimeWithoutSpace({DateTime? dateTime}) {
dateTime ??= DateTime.now();

final dateTimeString = DateTime.fromMicrosecondsSinceEpoch(
dateTime.microsecondsSinceEpoch,
).toString().replaceAll(' ', '-');
return dateTime;
return dateTimeString;
}

int getIndexValue({
Expand Down Expand Up @@ -272,6 +279,16 @@ Future<String> getPrivateKey({
required ProfileCubit profileCubit,
required DidKeyType didKeyType,
}) async {
final customOidc4vcProfile = profileCubit.state.model.profileSetting
.selfSovereignIdentityOptions.customOidc4vcProfile;

if (customOidc4vcProfile.clientType == ClientType.p256JWKThumprint) {
final privateKey =
await getP256KeyToGetAndPresentVC(profileCubit.secureStorageProvider);

return privateKey;
}

final mnemonic = await profileCubit.secureStorageProvider
.get(SecureStorageKeys.ssiMnemonic);

Expand Down Expand Up @@ -718,6 +735,7 @@ Future<
final OpenIdConfiguration openIdConfiguration = await oidc4vc.getOpenIdConfig(
baseUrl: issuer,
isAuthorizationServer: false,
dio: client.dio,
);

if (preAuthorizedCode == null) {
Expand All @@ -742,6 +760,7 @@ Future<
authorizationServerConfiguration = await oidc4vc.getOpenIdConfig(
baseUrl: authorizationServer,
isAuthorizationServer: true,
dio: client.dio,
);
}

Expand Down Expand Up @@ -971,7 +990,12 @@ Future<Map<String, dynamic>?> getClientMetada({
return null;
}
} catch (e) {
return null;
throw ResponseMessage(
data: {
'error': 'invalid_request',
'error_description': 'Client metaData is invalid',
},
);
}
}

Expand All @@ -992,6 +1016,7 @@ Future<bool?> isEBSIV3ForVerifiers({
await oidc4vc.getOpenIdConfig(
baseUrl: clientId,
isAuthorizationServer: false,
dio: Dio(),
);

final subjectTrustFrameworksSupported =
Expand Down Expand Up @@ -1158,7 +1183,7 @@ MessageHandler getMessageHandler(dynamic e) {
'error_description': 'Failed to extract header from jwt.',
},
);
} else if (stringException.contains('INVALID_TOKEN')) {
} else if (stringException.contains('INVALID_PAYLOAD')) {
return ResponseMessage(
data: {
'error': 'invalid_format',
Expand Down Expand Up @@ -1579,8 +1604,11 @@ Future<(String?, String?, String?, String?)> getClientDetails({

final didKeyType = customOidc4vcProfile.defaultDid;

final privateKey =
await getP256KeyToGetAndPresentVC(profileCubit.secureStorageProvider);
final String privateKey = await fetchPrivateKey(
profileCubit: profileCubit,
isEBSIV3: isEBSIV3,
didKeyType: didKeyType,
);

final (did, _) = await fetchDidAndKid(
privateKey: privateKey,
Expand All @@ -1594,7 +1622,7 @@ Future<(String?, String?, String?, String?)> getClientDetails({
did: '', // just added as it is required field
mediaType: MediaType.basic, // just added as it is required field
clientType:
ClientType.p256JWKThumprint, // just added as it is required field
customOidc4vcProfile.clientType, // just added as it is required field
proofHeaderType: customOidc4vcProfile.proofHeader,
clientId: '', // just added as it is required field
);
Expand Down Expand Up @@ -1840,10 +1868,10 @@ List<String> getStringCredentialsForToken({
}

/// create list of supported formats
if (presentLdpVc) supportingFormats.add(VCFormatType.ldpVc.value);
if (presentJwtVc) supportingFormats.add(VCFormatType.jwtVc.value);
if (presentJwtVcJson) supportingFormats.add(VCFormatType.jwtVcJson.value);
if (presentVcSdJwt) supportingFormats.add(VCFormatType.jwtVcJson.value);
if (presentLdpVc) supportingFormats.add(VCFormatType.ldpVc.vcValue);
if (presentJwtVc) supportingFormats.add(VCFormatType.jwtVc.vcValue);
if (presentJwtVcJson) supportingFormats.add(VCFormatType.jwtVcJson.vcValue);
if (presentVcSdJwt) supportingFormats.add(VCFormatType.jwtVcJson.vcValue);

/// make sure only one of all are true
if (presentLdpVc && vcFormatType == VCFormatType.ldpVc) {
Expand All @@ -1861,7 +1889,7 @@ List<String> getStringCredentialsForToken({
presentJwtVc = false;
presentJwtVcJson = true;
presentVcSdJwt = false;
} else if (presentJwtVc && vcFormatType == VCFormatType.vcSdJWT) {
} else if (presentVcSdJwt && vcFormatType == VCFormatType.vcSdJWT) {
presentLdpVc = false;
presentJwtVc = false;
presentJwtVcJson = false;
Expand Down Expand Up @@ -2013,9 +2041,9 @@ Future<Map<String, dynamic>?> checkX509({
final seq = asn1lib.ASN1Sequence.fromBytes(decoded);
final cert = x509.X509Certificate.fromAsn1(seq);

final subject = cert.tbsCertificate.subject;
final extensions = cert.tbsCertificate.extensions;

if (subject == null) {
if (extensions == null) {
throw ResponseMessage(
data: {
'error': 'invalid_format',
Expand All @@ -2024,9 +2052,11 @@ Future<Map<String, dynamic>?> checkX509({
);
}

final names = subject.names;
final extension = extensions
.where((Extension element) => element.extnId.name == 'subjectAltName')
.firstOrNull;

if (names.isEmpty) {
if (extension == null) {
throw ResponseMessage(
data: {
'error': 'invalid_format',
Expand All @@ -2035,9 +2065,9 @@ Future<Map<String, dynamic>?> checkX509({
);
}

final value = names[0].entries.map((element) => element.value).toList();
final extnValue = extension.extnValue.toString();

if (!value.contains(clientId)) {
if (!extnValue.contains(clientId)) {
throw ResponseMessage(
data: {
'error': 'invalid_format',
Expand All @@ -2056,6 +2086,18 @@ Future<Map<String, dynamic>?> checkX509({
'n': n.replaceAll('=', ''),
};
return publicKeyJwk;
} else if (publicKey is x509.EcPublicKey) {
final BigInt xModulus = BigInt.parse(publicKey.xCoordinate.toString());
final BigInt yModulus = BigInt.parse(publicKey.yCoordinate.toString());
final x = base64Encode(xModulus.toBytes);
final y = base64Encode(yModulus.toBytes);
final publicKeyJwk = {
'kty': 'EC',
'crv': 'P-256',
'x': x.replaceAll('=', ''),
'y': y.replaceAll('=', ''),
};
return publicKeyJwk;
}
}
return null;
Expand Down Expand Up @@ -2114,16 +2156,19 @@ String? getWalletAddress(CredentialSubjectModel credentialSubjectModel) {
return null;
}

Future<String> fetchRpcUrl(BlockchainNetwork blockchainNetwork) async {
Future<String> fetchRpcUrl({
required BlockchainNetwork blockchainNetwork,
required DotEnv dotEnv,
}) async {
String rpcUrl = '';

if (blockchainNetwork is BinanceNetwork ||
blockchainNetwork is FantomNetwork) {
rpcUrl = blockchainNetwork.rpcNodeUrl as String;
} else {
if (blockchainNetwork.networkname == 'Mainnet') {
await dotenv.load();
final String infuraApiKey = dotenv.get('INFURA_API_KEY');
await dotEnv.load();
final String infuraApiKey = dotEnv.get('INFURA_API_KEY');

late String prefixUrl;

Expand Down
Loading

0 comments on commit 469c3d2

Please sign in to comment.