From 39c29b912ce326dbf7ecc3b67a7be8962520a017 Mon Sep 17 00:00:00 2001 From: hawkbee <49282360+hawkbee1@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:43:56 +0200 Subject: [PATCH] October (#2906) * feat: Add switch to control notification #2869 * feat: Fix notification issue and make chat only custom * Update notification room #2875 * feat: Move notification menu to differnt place #2869 * refactor: Update notification switch location #2869 * Issue with name.firstname, cf slack #2880 * feat: Consider more constrainsts for presentation #2882 * feat: Consider more constrainsts for presentation #2882 * version update: 2.12.6+511 * Fix: All constraints considered #2882 and organise cred list alphabatically #2782 * feat: Improve vc details #2894 * refactor: Remove specified data #2894 * feat: Improve VC for SD-JWT with key binding data #2756 * feat: Remove jwt from json display in dev mode #2894 * feat: Add display log parameter #2895 * feat: Update wording for EBSI v3 #2896 * feat: Add new profile ebsi 4.0 #2897 * version update: 2.13.1+514 --------- Co-authored-by: Bibash Shrestha --- lib/app/shared/constants/parameters.dart | 1 + lib/app/shared/enum/type/oidc4vc_type.dart | 4 +- .../enum/type/profile/did_key_type.dart | 6 + .../enum/type/profile/profile_type.dart | 6 +- .../helper_functions/helper_functions.dart | 33 ++-- lib/app/shared/widget/wallet_logo.dart | 1 + .../widget/did_key_type_widget.dart | 1 + .../detail/widgets/developer_details.dart | 178 ++++++++++++++---- .../view/oid4c4vc_credential_pick_page.dart | 16 +- .../get_credentials_from_filter_list.dart | 27 ++- .../profile/cubit/profile_cubit.dart | 36 ++++ lib/dashboard/profile/models/profile.dart | 74 ++++++++ .../profile/models/profile_setting.dart | 5 + .../cubit/qr_code_scan_cubit.dart | 34 ++-- lib/l10n/arb/app_en.arb | 8 +- lib/l10n/untranslated.json | 24 ++- .../get_authorization_uri_for_issuer.dart | 4 +- lib/oidc4vc/get_credential.dart | 6 +- .../initiate_oidv4vc_credential_issuance.dart | 10 +- pubspec.yaml | 2 +- .../shared/enum/type/oidc4vc_type_test.dart | 2 +- .../helper_functions_test.dart | 14 +- 22 files changed, 387 insertions(+), 105 deletions(-) diff --git a/lib/app/shared/constants/parameters.dart b/lib/app/shared/constants/parameters.dart index 20a6eba73..219d25122 100644 --- a/lib/app/shared/constants/parameters.dart +++ b/lib/app/shared/constants/parameters.dart @@ -102,6 +102,7 @@ class Parameters { static const String walletName = 'altme_wallet'; static const DidKeyType didKeyTypeForEbsiV3 = DidKeyType.ebsiv3; + static const DidKeyType didKeyTypeForEbsiV4 = DidKeyType.ebsiv4; static const DidKeyType didKeyTypeForDefault = DidKeyType.edDSA; static const DidKeyType didKeyTypeForDutch = DidKeyType.jwkP256; static const DidKeyType didKeyTypeForOwfBaselineProfile = DidKeyType.jwkP256; diff --git a/lib/app/shared/enum/type/oidc4vc_type.dart b/lib/app/shared/enum/type/oidc4vc_type.dart index 5a1092b4d..f2bd80ab4 100644 --- a/lib/app/shared/enum/type/oidc4vc_type.dart +++ b/lib/app/shared/enum/type/oidc4vc_type.dart @@ -14,7 +14,7 @@ enum OIDC4VCType { presentationPrefix: 'openid-hedera://', ), - EBSIV3( + EBSI( offerPrefix: 'openid-credential-offer://', presentationPrefix: 'openid-vc://', ), @@ -44,7 +44,7 @@ extension OIDC4VCTypeX on OIDC4VCType { case OIDC4VCType.DEFAULT: case OIDC4VCType.GAIAX: case OIDC4VCType.GREENCYPHER: - case OIDC4VCType.EBSIV3: + case OIDC4VCType.EBSI: case OIDC4VCType.HAIP: return true; case OIDC4VCType.JWTVC: diff --git a/lib/app/shared/enum/type/profile/did_key_type.dart b/lib/app/shared/enum/type/profile/did_key_type.dart index 3502e31a9..91caedd7b 100644 --- a/lib/app/shared/enum/type/profile/did_key_type.dart +++ b/lib/app/shared/enum/type/profile/did_key_type.dart @@ -10,6 +10,7 @@ enum DidKeyType { p256, @JsonValue('did:key:ebsi') ebsiv3, + ebsiv4, @JsonValue('did:jwk:p-256') jwkP256, @JsonValue( @@ -29,6 +30,8 @@ extension DidKeyTypeX on DidKeyType { return 'did:key P-256'; case DidKeyType.ebsiv3: return 'did:key EBSI-V3'; + case DidKeyType.ebsiv4: + return 'did:key EBSI-V4'; case DidKeyType.jwkP256: return 'did:jwk P-256'; case DidKeyType.jwtClientAttestation: @@ -46,6 +49,8 @@ extension DidKeyTypeX on DidKeyType { return l10n.keyDecentralizedIDP256; case DidKeyType.ebsiv3: return l10n.ebsiV3DecentralizedId; + case DidKeyType.ebsiv4: + return l10n.ebsiV4DecentralizedId; case DidKeyType.jwkP256: return l10n.jwkDecentralizedIDP256; case DidKeyType.jwtClientAttestation: @@ -62,6 +67,7 @@ extension DidKeyTypeX on DidKeyType { case DidKeyType.edDSA: return true; case DidKeyType.ebsiv3: + case DidKeyType.ebsiv4: return false; } } diff --git a/lib/app/shared/enum/type/profile/profile_type.dart b/lib/app/shared/enum/type/profile/profile_type.dart index 21f239a49..0edf79370 100644 --- a/lib/app/shared/enum/type/profile/profile_type.dart +++ b/lib/app/shared/enum/type/profile/profile_type.dart @@ -1,6 +1,7 @@ enum ProfileType { defaultOne, ebsiV3, + ebsiV4, diipv2point1, diipv3, custom, @@ -13,7 +14,9 @@ extension ProfileTypeX on ProfileType { case ProfileType.custom: return 'Custom'; case ProfileType.ebsiV3: - return 'European Blockchain Services Infrastructure'; + return 'European Blockchain Services Infrastructure (EBSI v3.x)'; + case ProfileType.ebsiV4: + return 'European Blockchain Services Infrastructure (EBSI v4.x)'; case ProfileType.diipv2point1: return 'Decentralized Identity Interop Profile (DIIP v2.1)'; case ProfileType.enterprise: @@ -32,6 +35,7 @@ extension ProfileTypeX on ProfileType { case ProfileType.diipv2point1: return false; case ProfileType.ebsiV3: + case ProfileType.ebsiV4: case ProfileType.enterprise: case ProfileType.diipv3: return true; diff --git a/lib/app/shared/helper_functions/helper_functions.dart b/lib/app/shared/helper_functions/helper_functions.dart index 1678ffcdc..4c5be8900 100644 --- a/lib/app/shared/helper_functions/helper_functions.dart +++ b/lib/app/shared/helper_functions/helper_functions.dart @@ -234,12 +234,12 @@ String getDateTimeWithoutSpace({DateTime? dateTime}) { } int getIndexValue({ - required bool isEBSIV3, + required bool isEBSI, required DidKeyType didKeyType, }) { switch (didKeyType) { case DidKeyType.secp256k1: - if (isEBSIV3) { + if (isEBSI) { return 3; } else { return 1; @@ -250,7 +250,8 @@ int getIndexValue({ return 5; case DidKeyType.jwkP256: return 6; - + case DidKeyType.ebsiv4: + return 7; case DidKeyType.edDSA: case DidKeyType.jwtClientAttestation: return 0; // it is not needed, just assigned @@ -282,7 +283,7 @@ Future getPrivateKey({ case DidKeyType.secp256k1: final index = getIndexValue( - isEBSIV3: true, + isEBSI: true, didKeyType: didKeyType, ); final key = profileCubit.oidc4vc.privateKeyFromMnemonic( @@ -293,9 +294,10 @@ Future getPrivateKey({ case DidKeyType.p256: case DidKeyType.ebsiv3: + case DidKeyType.ebsiv4: case DidKeyType.jwkP256: final indexValue = getIndexValue( - isEBSIV3: false, + isEBSI: false, didKeyType: didKeyType, ); @@ -398,9 +400,9 @@ DidKeyType? getDidKeyFromString(String? didKeyTypeString) { Future fetchPrivateKey({ required ProfileCubit profileCubit, required DidKeyType didKeyType, - bool? isEBSIV3, + bool? isEBSI, }) async { - if (isEBSIV3 != null && isEBSIV3) { + if (isEBSI != null && isEBSI) { final privateKey = await getPrivateKey( profileCubit: profileCubit, didKeyType: DidKeyType.ebsiv3, @@ -533,6 +535,7 @@ Future<(String, String)> getDidAndKid({ switch (didKeyType) { case DidKeyType.ebsiv3: + case DidKeyType.ebsiv4: //b'\xd1\xd6\x03' in python final List prefixByteList = [0xd1, 0xd6, 0x03]; @@ -592,11 +595,11 @@ Future<(String, String)> getDidAndKid({ Future<(String, String)> fetchDidAndKid({ required String privateKey, - bool? isEBSIV3, + bool? isEBSI, required ProfileCubit profileCubit, required DidKeyType didKeyType, }) async { - if (isEBSIV3 != null && isEBSIV3) { + if (isEBSI != null && isEBSI) { final (did, kid) = await getDidAndKid( didKeyType: DidKeyType.ebsiv3, privateKey: privateKey, @@ -785,7 +788,7 @@ Future< for (final oidc4vcType in OIDC4VCType.values) { if (oidc4vcType.isEnabled && url.startsWith(oidc4vcType.offerPrefix)) { if (oidc4vcType == OIDC4VCType.DEFAULT || - oidc4vcType == OIDC4VCType.EBSIV3) { + oidc4vcType == OIDC4VCType.EBSI) { if (credSupported?.trustFramework != null && credSupported == credSupported?.trustFramework) { return ( @@ -801,7 +804,7 @@ Future< if (credSupported?.trustFramework?.name != null && credSupported?.trustFramework?.name == 'ebsi') { return ( - OIDC4VCType.EBSIV3, + OIDC4VCType.EBSI, openIdConfiguration, authorizationServerConfiguration, credentialOfferJson, @@ -997,7 +1000,7 @@ Future?> getClientMetada({ } } -Future isEBSIV3ForVerifiers({ +Future isEBSIForVerifiers({ required Uri uri, required OIDC4VC oidc4vc, required OIDC4VCIDraftType oidc4vciDraftType, @@ -1595,7 +1598,7 @@ bool supportCryptoCredential(ProfileModel profileModel) { // oAuthClientAttestationPop Future<(String?, String?, String?, String?, String?)> getClientDetails({ required ProfileCubit profileCubit, - required bool isEBSIV3, + required bool isEBSI, required String issuer, }) async { try { @@ -1612,13 +1615,13 @@ Future<(String?, String?, String?, String?, String?)> getClientDetails({ final String privateKey = await fetchPrivateKey( profileCubit: profileCubit, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, didKeyType: didKeyType, ); final (did, _) = await fetchDidAndKid( privateKey: privateKey, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, profileCubit: profileCubit, didKeyType: didKeyType, ); diff --git a/lib/app/shared/widget/wallet_logo.dart b/lib/app/shared/widget/wallet_logo.dart index 0b5f4dbbe..58a429f2f 100644 --- a/lib/app/shared/widget/wallet_logo.dart +++ b/lib/app/shared/widget/wallet_logo.dart @@ -33,6 +33,7 @@ class WalletLogo extends StatelessWidget { ? ImageStrings.appLogoStage : ImageStrings.appLogo; case ProfileType.ebsiV3: + case ProfileType.ebsiV4: image = ImageStrings.ebsiLogo; case ProfileType.enterprise: final isLightTheme = diff --git a/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart index 5c2012174..1b453c4df 100644 --- a/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart +++ b/lib/dashboard/drawer/ssi/oidc4vc_settngs/widget/did_key_type_widget.dart @@ -40,6 +40,7 @@ class DidKeyTypeWidget extends StatelessWidget { VCFormatType.ldpVc; final isUnmatchedDid = didKeyType == DidKeyType.ebsiv3 || + didKeyType == DidKeyType.ebsiv4 || didKeyType == DidKeyType.jwkP256; if (isldpVc && isUnmatchedDid) { diff --git a/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart b/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart index 6c054deb2..ba634e3c3 100644 --- a/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart +++ b/lib/dashboard/home/tab_bar/credentials/detail/widgets/developer_details.dart @@ -1,7 +1,12 @@ +import 'dart:convert'; + import 'package:altme/app/app.dart'; import 'package:altme/dashboard/dashboard.dart'; import 'package:altme/l10n/l10n.dart'; +import 'package:altme/selective_disclosure/selective_disclosure.dart'; import 'package:flutter/material.dart'; +import 'package:jwt_decode/jwt_decode.dart'; +import 'package:oidc4vc/oidc4vc.dart'; class DeveloperDetails extends StatelessWidget { const DeveloperDetails({ @@ -21,14 +26,74 @@ class DeveloperDetails extends StatelessWidget { Widget build(BuildContext context) { final l10n = context.l10n; - final String issuerDid = credentialModel.credentialPreview.issuer; - final String subjectDid = - credentialModel.credentialPreview.credentialSubjectModel.id ?? ''; - final String type = credentialModel.credentialPreview.type.toString(); + // final String issuerDid = credentialModel.credentialPreview.issuer; + // final String subjectDid = + // credentialModel.credentialPreview.credentialSubjectModel.id ?? ''; + // final String type = credentialModel.credentialPreview.type.toString(); final titleColor = Theme.of(context).colorScheme.onSurface; final valueColor = Theme.of(context).colorScheme.onSurface; + final jwtDecode = JWTDecode(); + + String? header; + String? payload; + String? data; + + String? kbHeader; + String? kbPayload; + + if (credentialModel.jwt != null) { + final jsonheader = decodeHeader( + jwtDecode: jwtDecode, + token: credentialModel.jwt!, + ); + header = const JsonEncoder.withIndent(' ').convert(jsonheader); + final jsonPayload = decodePayload( + jwtDecode: jwtDecode, + token: credentialModel.jwt!, + ); + payload = const JsonEncoder.withIndent(' ').convert( + Map.of(jsonPayload)..removeWhere((key, value) => key == 'jwt'), + ); + + if (credentialModel.getFormat == VCFormatType.vcSdJWT.vcValue) { + final selectiveDisclosure = SelectiveDisclosure(credentialModel); + + final data = createJsonByDecryptingSDValues( + encryptedJson: credentialModel.data, + selectiveDisclosure: selectiveDisclosure, + ); + + payload = const JsonEncoder.withIndent(' ') + .convert(Map.of(data)..removeWhere((key, value) => key == 'jwt')); + + final probableJwt = credentialModel.jwt?.split('~').last; + kbHeader = 'None'; + kbPayload = 'None'; + + if (probableJwt != null && + probableJwt.isNotEmpty && + probableJwt.startsWith('e')) { + try { + final header = jwtDecode.parseJwtHeader(probableJwt); + kbHeader = const JsonEncoder.withIndent(' ').convert(header); + } catch (e) { + kbHeader = 'None'; + } + + try { + final payload = jwtDecode.parseJwt(probableJwt); + kbPayload = const JsonEncoder.withIndent(' ').convert(payload); + } catch (e) { + kbPayload = 'None'; + } + } + } + } else { + data = const JsonEncoder.withIndent(' ').convert(credentialModel.data); + } + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -40,53 +105,96 @@ class DeveloperDetails extends StatelessWidget { valueColor: valueColor, showVertically: showVertically, ), - CredentialField( - padding: const EdgeInsets.only(top: 10), - title: l10n.issuerDID, - value: issuerDid, - titleColor: titleColor, - valueColor: valueColor, - showVertically: showVertically, - ), - if (credentialModel.credentialPreview.credentialSubjectModel - is! WalletCredentialModel && - subjectDid.isNotEmpty) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.issuerDID, + // value: issuerDid, + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: showVertically, + // ), + // if (credentialModel.credentialPreview.credentialSubjectModel + // is! WalletCredentialModel && + // subjectDid.isNotEmpty) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.subjectDID, + // value: subjectDid, + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: showVertically, + // ), + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.type, + // value: type, + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: showVertically, + // ), + // if (statusListUri != null) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.statusList, + // value: statusListUri.toString(), + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: false, + // ), + // if (statusListIndex != null) + // CredentialField( + // padding: const EdgeInsets.only(top: 10), + // title: l10n.statusListIndex, + // value: statusListIndex.toString(), + // titleColor: titleColor, + // valueColor: valueColor, + // showVertically: false, + // ), + if (header != null) CredentialField( padding: const EdgeInsets.only(top: 10), - title: l10n.subjectDID, - value: subjectDid, + title: l10n.header, + value: header, titleColor: titleColor, valueColor: valueColor, showVertically: showVertically, ), - CredentialField( - padding: const EdgeInsets.only(top: 10), - title: l10n.type, - value: type, - titleColor: titleColor, - valueColor: valueColor, - showVertically: showVertically, - ), - if (statusListUri != null) ...[ + if (payload != null) + CredentialField( + padding: const EdgeInsets.only(top: 10), + title: l10n.payload, + value: payload, + titleColor: titleColor, + valueColor: valueColor, + showVertically: showVertically, + ), + if (data != null) CredentialField( padding: const EdgeInsets.only(top: 10), - title: l10n.statusList, - value: statusListUri.toString(), + title: l10n.data, + value: data, titleColor: titleColor, valueColor: valueColor, - showVertically: false, + showVertically: showVertically, ), - ], - if (statusListIndex != null) ...[ + if (kbHeader != null) CredentialField( padding: const EdgeInsets.only(top: 10), - title: l10n.statusListIndex, - value: statusListIndex.toString(), + title: l10n.keyBindingHeader, + value: kbHeader, titleColor: titleColor, valueColor: valueColor, - showVertically: false, + showVertically: showVertically, + ), + if (kbPayload != null) + CredentialField( + padding: const EdgeInsets.only(top: 10), + title: l10n.keyBindingPayload, + value: kbPayload, + titleColor: titleColor, + valueColor: valueColor, + showVertically: showVertically, ), - ], ], ); } diff --git a/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart b/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart index 63685d8ca..1aba69219 100644 --- a/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart +++ b/lib/dashboard/home/tab_bar/credentials/oid4c4vc_pick/oid4c4vc_credential_pick/view/oid4c4vc_credential_pick_page.dart @@ -13,7 +13,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { required this.userPin, required this.preAuthorizedCode, required this.issuer, - required this.isEBSIV3, + required this.isEBSI, required this.credentialOfferJson, required this.openIdConfiguration, }); @@ -22,7 +22,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { final String? userPin; final String? preAuthorizedCode; final String issuer; - final bool isEBSIV3; + final bool isEBSI; final dynamic credentialOfferJson; final OpenIdConfiguration openIdConfiguration; @@ -31,7 +31,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { required String? userPin, required String? preAuthorizedCode, required String issuer, - required bool isEBSIV3, + required bool isEBSI, required dynamic credentialOfferJson, required OpenIdConfiguration openIdConfiguration, }) => @@ -41,7 +41,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ), @@ -57,7 +57,7 @@ class Oidc4vcCredentialPickPage extends StatelessWidget { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ), @@ -72,7 +72,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { required this.userPin, required this.preAuthorizedCode, required this.issuer, - required this.isEBSIV3, + required this.isEBSI, required this.credentialOfferJson, required this.openIdConfiguration, }); @@ -81,7 +81,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { final String? userPin; final String? preAuthorizedCode; final String issuer; - final bool isEBSIV3; + final bool isEBSI; final dynamic credentialOfferJson; final OpenIdConfiguration openIdConfiguration; @@ -198,7 +198,7 @@ class Oidc4vcCredentialPickView extends StatelessWidget { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, qrCodeScanCubit: context.read(), diff --git a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart index 95cafaac7..e1649273f 100644 --- a/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart +++ b/lib/dashboard/home/tab_bar/credentials/present/pick/credential_manifest/helpers/get_credentials_from_filter_list.dart @@ -13,8 +13,10 @@ List getCredentialsFromFilterList({ /// remove ldp_vp if jwt_vp is required final selectedCredential = []; - for (final field in filterList) { - for (final credential in credentialList) { + + for (final credential in credentialList) { + fieldLoop: + for (final field in filterList) { for (final path in field.path) { final credentialData = createJsonByDecryptingSDValues( encryptedJson: credential.data, @@ -63,12 +65,29 @@ List getCredentialsFromFilterList({ if (searchList.isNotEmpty) { selectedCredential.add(credential); } else { - break; + break fieldLoop; } } } } - return selectedCredential.toSet().toList(); + + final credentials = selectedCredential.toSet().toList(); + + credentials.sort( + (a, b) { + final firstCredName = a.display?.name ?? + a.credentialPreview.credentialSubjectModel.credentialSubjectType + .name; + final secondCredName = b.display?.name ?? + b.credentialPreview.credentialSubjectModel.credentialSubjectType + .name; + + return firstCredName.compareTo(secondCredName); + }, + ); + + return credentials; } + return credentialList; } diff --git a/lib/dashboard/profile/cubit/profile_cubit.dart b/lib/dashboard/profile/cubit/profile_cubit.dart index 048ee8332..d0452efe8 100644 --- a/lib/dashboard/profile/cubit/profile_cubit.dart +++ b/lib/dashboard/profile/cubit/profile_cubit.dart @@ -237,6 +237,28 @@ class ProfileCubit extends Cubit { enterpriseWalletName: enterpriseWalletName, ); + case ProfileType.ebsiV4: + final privateKey = await getPrivateKey( + didKeyType: Parameters.didKeyTypeForEbsiV4, + profileCubit: this, + ); + + final (did, _) = await getDidAndKid( + didKeyType: Parameters.didKeyTypeForEbsiV4, + privateKey: privateKey, + profileCubit: this, + ); + + profileModel = ProfileModel.ebsiV4( + polygonIdNetwork: polygonIdNetwork, + walletType: walletType, + walletProtectionType: walletProtectionType, + isDeveloperMode: isDeveloperMode, + clientId: did, + clientSecret: randomString(12), + enterpriseWalletName: enterpriseWalletName, + ); + case ProfileType.diipv2point1: final privateKey = await getPrivateKey( didKeyType: Parameters.didKeyTypeForDutch, @@ -599,6 +621,20 @@ class ProfileCubit extends Cubit { .selfSovereignIdentityOptions.customOidc4vcProfile.clientSecret, ), ); + case ProfileType.ebsiV4: + await update( + ProfileModel.ebsiV4( + polygonIdNetwork: state.model.polygonIdNetwork, + walletProtectionType: state.model.walletProtectionType, + isDeveloperMode: state.model.isDeveloperMode, + walletType: state.model.walletType, + enterpriseWalletName: state.model.enterpriseWalletName, + clientId: state.model.profileSetting.selfSovereignIdentityOptions + .customOidc4vcProfile.clientId, + clientSecret: state.model.profileSetting + .selfSovereignIdentityOptions.customOidc4vcProfile.clientSecret, + ), + ); case ProfileType.defaultOne: await update( ProfileModel.defaultOne( diff --git a/lib/dashboard/profile/models/profile.dart b/lib/dashboard/profile/models/profile.dart index deeb2ccff..f31c5309a 100644 --- a/lib/dashboard/profile/models/profile.dart +++ b/lib/dashboard/profile/models/profile.dart @@ -104,6 +104,80 @@ class ProfileModel extends Equatable { ), ); + factory ProfileModel.ebsiV4({ + required PolygonIdNetwork polygonIdNetwork, + required WalletType walletType, + required WalletProtectionType walletProtectionType, + required bool isDeveloperMode, + required String? clientId, + required String? clientSecret, + String? enterpriseWalletName, + }) => + ProfileModel( + enterpriseWalletName: enterpriseWalletName, + polygonIdNetwork: polygonIdNetwork, + walletType: walletType, + walletProtectionType: walletProtectionType, + isDeveloperMode: isDeveloperMode, + profileType: ProfileType.ebsiV4, + profileSetting: ProfileSetting( + blockchainOptions: BlockchainOptions.initial(), + generalOptions: GeneralOptions.empty(), + helpCenterOptions: HelpCenterOptions.initial(), + discoverCardsOptions: const DiscoverCardsOptions( + displayDefi: false, + displayHumanity: false, + displayHumanityJwt: false, + displayOver13: false, + displayOver15: false, + displayOver18: false, + displayOver18Jwt: false, + displayOver21: false, + displayOver50: false, + displayChainborn: false, + displayTezotopia: false, + displayVerifiableId: false, + displayVerifiableIdJwt: true, + displayOver65: false, + displayEmailPass: false, + displayEmailPassJwt: false, + displayPhonePass: false, + displayPhonePassJwt: false, + displayAgeRange: false, + displayGender: false, + displayExternalIssuer: [], + ), + selfSovereignIdentityOptions: SelfSovereignIdentityOptions( + displayManageDecentralizedId: true, + customOidc4vcProfile: CustomOidc4VcProfile( + clientAuthentication: ClientAuthentication.clientId, + credentialManifestSupport: false, + cryptoHolderBinding: true, + defaultDid: Parameters.didKeyTypeForEbsiV3, + oidc4vciDraft: OIDC4VCIDraftType.draft13, + oidc4vpDraft: OIDC4VPDraftType.draft10, + scope: false, + securityLevel: true, + proofHeader: ProofHeaderType.kid, + siopv2Draft: SIOPV2DraftType.draft12, + clientType: ClientType.did, + clientId: clientId, + clientSecret: clientSecret, + vcFormatType: VCFormatType.auto, + proofType: ProofType.jwt, + ), + ), + settingsMenu: SettingsMenu.initial(), + version: '', + walletSecurityOptions: const WalletSecurityOptions( + confirmSecurityVerifierAccess: true, + displaySecurityAdvancedSettings: true, + secureSecurityAuthenticationWithPinCode: true, + verifySecurityIssuerWebsiteIdentity: true, + ), + ), + ); + factory ProfileModel.defaultOne({ required PolygonIdNetwork polygonIdNetwork, required WalletType walletType, diff --git a/lib/dashboard/profile/models/profile_setting.dart b/lib/dashboard/profile/models/profile_setting.dart index 5cf6b002c..7f6812f88 100644 --- a/lib/dashboard/profile/models/profile_setting.dart +++ b/lib/dashboard/profile/models/profile_setting.dart @@ -739,6 +739,7 @@ class SettingsMenu extends Equatable { required this.displayHelpCenter, required this.displayProfile, this.displaySelfSovereignIdentity = true, + this.displayActivityLog = false, }); factory SettingsMenu.fromJson(Map json) => @@ -754,6 +755,7 @@ class SettingsMenu extends Equatable { final bool displayHelpCenter; final bool displayProfile; final bool displaySelfSovereignIdentity; + final bool displayActivityLog; Map toJson() => _$SettingsMenuToJson(this); @@ -762,6 +764,7 @@ class SettingsMenu extends Equatable { bool? displayHelpCenter, bool? displayProfile, bool? displaySelfSovereignIdentity, + bool? displayActivityLog, }) => SettingsMenu( displayDeveloperMode: displayDeveloperMode ?? this.displayDeveloperMode, @@ -769,6 +772,7 @@ class SettingsMenu extends Equatable { displayProfile: displayProfile ?? this.displayProfile, displaySelfSovereignIdentity: displaySelfSovereignIdentity ?? this.displaySelfSovereignIdentity, + displayActivityLog: displayActivityLog ?? this.displayActivityLog, ); @override @@ -777,6 +781,7 @@ class SettingsMenu extends Equatable { displayHelpCenter, displayProfile, displaySelfSovereignIdentity, + displayActivityLog, ]; } diff --git a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart index 4634e0b96..fd2ebd1de 100644 --- a/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart +++ b/lib/dashboard/qr_code/qr_code_scan/cubit/qr_code_scan_cubit.dart @@ -246,7 +246,7 @@ class QRCodeScanCubit extends Cubit { await startOIDC4VCCredentialIssuance( scannedResponse: uri.toString(), - isEBSIV3: oidcType == OIDC4VCType.EBSIV3, + isEBSI: oidcType == OIDC4VCType.EBSI, qrCodeScanCubit: qrCodeScanCubit, oidc4vciDraftType: customOidc4vcProfile.oidc4vciDraft, credentialOfferJson: credentialOfferJson, @@ -456,7 +456,7 @@ class QRCodeScanCubit extends Cubit { Future startOIDC4VCCredentialIssuance({ required String scannedResponse, - required bool isEBSIV3, + required bool isEBSI, required QRCodeScanCubit qrCodeScanCubit, required OIDC4VCIDraftType oidc4vciDraftType, required dynamic credentialOfferJson, @@ -533,7 +533,7 @@ class QRCodeScanCubit extends Cubit { dioClient: client, userPin: userPin, oidc4vc: oidc4vc, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, cryptoHolderBinding: customOidc4vcProfile.cryptoHolderBinding, @@ -562,7 +562,7 @@ class QRCodeScanCubit extends Cubit { dioClient: client, userPin: null, credentialOfferJson: credentialOfferJson, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, cryptoHolderBinding: customOidc4vcProfile.cryptoHolderBinding, oidc4vciDraftType: oidc4vciDraftType, profileCubit: profileCubit, @@ -890,7 +890,7 @@ class QRCodeScanCubit extends Cubit { required String? userPin, required String? preAuthorizedCode, required String issuer, - required bool isEBSIV3, + required bool isEBSI, required dynamic credentialOfferJson, required OpenIdConfiguration openIdConfiguration, }) { @@ -902,7 +902,7 @@ class QRCodeScanCubit extends Cubit { userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ), @@ -1189,8 +1189,8 @@ class QRCodeScanCubit extends Cubit { final nonce = state.uri?.queryParameters['nonce']; final stateValue = state.uri?.queryParameters['state']; - // final bool? isEBSIV3 = - // await isEBSIV3ForVerifier(client: client, uri: state.uri!); + // final bool? isEBSI = + // await isEBSIForVerifier(client: client, uri: state.uri!); final didKeyType = profileCubit.state.model.profileSetting .selfSovereignIdentityOptions.customOidc4vcProfile.defaultDid; @@ -1257,7 +1257,7 @@ class QRCodeScanCubit extends Cubit { Future processSelectedCredentials({ required List selectedCredentials, - required bool isEBSIV3, + required bool isEBSI, required String? userPin, required String? preAuthorizedCode, required String issuer, @@ -1273,7 +1273,7 @@ class QRCodeScanCubit extends Cubit { oAuthClientAttestationPop ) = await getClientDetails( profileCubit: profileCubit, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, issuer: issuer, ); @@ -1283,7 +1283,7 @@ class QRCodeScanCubit extends Cubit { if (preAuthorizedCode != null) { await addCredentialsInLoop( selectedCredentials: selectedCredentials, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, userPin: userPin, preAuthorizedCode: preAuthorizedCode, issuer: issuer, @@ -1303,7 +1303,7 @@ class QRCodeScanCubit extends Cubit { await getAuthorizationUriForIssuer( scannedResponse: state.uri.toString(), oidc4vc: oidc4vc, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, didKitProvider: didKitProvider, selectedCredentials: selectedCredentials, credentialOfferJson: credentialOfferJson, @@ -1333,7 +1333,7 @@ class QRCodeScanCubit extends Cubit { Future addCredentialsInLoop({ required List selectedCredentials, - required bool isEBSIV3, + required bool isEBSI, required String? userPin, required String? preAuthorizedCode, required String issuer, @@ -1437,7 +1437,7 @@ class QRCodeScanCubit extends Cubit { String? deferredCredentialEndpoint, String format, ) = await getCredential( - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credential: selectedCredentials[i], issuer: issuer, cryptoHolderBinding: customOidc4vcProfile.cryptoHolderBinding, @@ -1558,7 +1558,7 @@ class QRCodeScanCubit extends Cubit { final containsAllRequiredKey = statePayload.containsKey('credentials') && statePayload.containsKey('codeVerifier') && statePayload.containsKey('issuer') && - statePayload.containsKey('isEBSIV3'); + statePayload.containsKey('isEBSI'); if (!containsAllRequiredKey) { throw ResponseMessage( @@ -1572,7 +1572,7 @@ class QRCodeScanCubit extends Cubit { final selectedCredentials = statePayload['credentials'] as List; final String codeVerifier = statePayload['codeVerifier'].toString(); final String issuer = statePayload['issuer'].toString(); - final bool isEBSIV3 = statePayload['isEBSIV3'] as bool; + final bool isEBSI = statePayload['isEBSI'] as bool; final String? authorization = statePayload['authorization'] as String?; final String? clientId = statePayload['client_id'] as String?; final String? clientSecret = statePayload['client_secret'] as String?; @@ -1586,7 +1586,7 @@ class QRCodeScanCubit extends Cubit { userPin: null, issuer: issuer, preAuthorizedCode: null, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, codeForAuthorisedFlow: codeForAuthorisedFlow, codeVerifier: codeVerifier, authorization: authorization, diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index b65902088..1c2c0348b 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -1068,5 +1068,11 @@ "notificationTitle": "Welcome to the Notifications!\nStay informed with important updates.", "chatRoom": "Chat room", "notificationRoom": "Notification room", - "notificationSubtitle": "Enable to get the notification" + "notificationSubtitle": "Enable to get the notification", + "header": "Header", + "payload": "Payload", + "data": "Data", + "keyBindingHeader": "Key Binding Header", + "keyBindingPayload": "Key Binding Payload", + "ebsiV4DecentralizedId": "did:key EBSI V4 P-256" } diff --git a/lib/l10n/untranslated.json b/lib/l10n/untranslated.json index 1c5340d34..8784f590f 100644 --- a/lib/l10n/untranslated.json +++ b/lib/l10n/untranslated.json @@ -38,7 +38,13 @@ "notificationTitle", "chatRoom", "notificationRoom", - "notificationSubtitle" + "notificationSubtitle", + "header", + "payload", + "data", + "keyBindingHeader", + "keyBindingPayload", + "ebsiV4DecentralizedId" ], "es": [ @@ -80,7 +86,13 @@ "notificationTitle", "chatRoom", "notificationRoom", - "notificationSubtitle" + "notificationSubtitle", + "header", + "payload", + "data", + "keyBindingHeader", + "keyBindingPayload", + "ebsiV4DecentralizedId" ], "fr": [ @@ -127,6 +139,12 @@ "notificationTitle", "chatRoom", "notificationRoom", - "notificationSubtitle" + "notificationSubtitle", + "header", + "payload", + "data", + "keyBindingHeader", + "keyBindingPayload", + "ebsiV4DecentralizedId" ] } diff --git a/lib/oidc4vc/get_authorization_uri_for_issuer.dart b/lib/oidc4vc/get_authorization_uri_for_issuer.dart index 5f96a54d2..53cc33ccf 100644 --- a/lib/oidc4vc/get_authorization_uri_for_issuer.dart +++ b/lib/oidc4vc/get_authorization_uri_for_issuer.dart @@ -11,7 +11,7 @@ import 'package:uuid/uuid.dart'; Future getAuthorizationUriForIssuer({ required String scannedResponse, required OIDC4VC oidc4vc, - required bool isEBSIV3, + required bool isEBSI, required DIDKitProvider didKitProvider, required List selectedCredentials, required String issuer, @@ -49,7 +49,7 @@ Future getAuthorizationUriForIssuer({ 'codeVerifier': pkcePair.codeVerifier, 'credentials': selectedCredentials, 'issuer': issuer, - 'isEBSIV3': isEBSIV3, + 'isEBSI': isEBSI, }; switch (clientAuthentication) { diff --git a/lib/oidc4vc/get_credential.dart b/lib/oidc4vc/get_credential.dart index cdb0dbb1f..921577078 100644 --- a/lib/oidc4vc/get_credential.dart +++ b/lib/oidc4vc/get_credential.dart @@ -12,7 +12,7 @@ Future< String?, String, )> getCredential({ - required bool isEBSIV3, + required bool isEBSI, required dynamic credential, required ProfileCubit profileCubit, required String issuer, @@ -26,13 +26,13 @@ Future< required List? authorizationDetails, }) async { final privateKey = await fetchPrivateKey( - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, didKeyType: didKeyType, profileCubit: profileCubit, ); final (did, kid) = await fetchDidAndKid( - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, privateKey: privateKey, didKeyType: didKeyType, profileCubit: profileCubit, diff --git a/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart b/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart index aa62d62ac..724703770 100644 --- a/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart +++ b/lib/oidc4vc/initiate_oidv4vc_credential_issuance.dart @@ -11,7 +11,7 @@ import 'package:secure_storage/secure_storage.dart'; Future initiateOIDC4VCCredentialIssuance({ required String scannedResponse, required OIDC4VC oidc4vc, - required bool isEBSIV3, + required bool isEBSI, required QRCodeScanCubit qrCodeScanCubit, required DIDKitProvider didKitProvider, required CredentialsCubit credentialsCubit, @@ -88,7 +88,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ); @@ -100,7 +100,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, openIdConfiguration: openIdConfiguration, ); @@ -131,7 +131,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: null, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, codeForAuthorisedFlow: codeForAuthorisedFlow, codeVerifier: codeVerifier, authorization: authorization, @@ -149,7 +149,7 @@ Future initiateOIDC4VCCredentialIssuance({ userPin: userPin, issuer: issuer, preAuthorizedCode: preAuthorizedCode, - isEBSIV3: isEBSIV3, + isEBSI: isEBSI, credentialOfferJson: credentialOfferJson, selectedCredentials: [credentials], qrCodeScanCubit: qrCodeScanCubit, diff --git a/pubspec.yaml b/pubspec.yaml index 80b2053b2..f61e163f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: altme description: AltMe Flutter App -version: 2.13.0+513 +version: 2.13.1+514 publish_to: "none" # Remove this line if you wish to publish to pub.dev environment: diff --git a/test/app/shared/enum/type/oidc4vc_type_test.dart b/test/app/shared/enum/type/oidc4vc_type_test.dart index 0cde1154c..d27977282 100644 --- a/test/app/shared/enum/type/oidc4vc_type_test.dart +++ b/test/app/shared/enum/type/oidc4vc_type_test.dart @@ -7,7 +7,7 @@ void main() { expect(OIDC4VCType.DEFAULT.isEnabled, equals(true)); expect(OIDC4VCType.GAIAX.isEnabled, equals(true)); expect(OIDC4VCType.GREENCYPHER.isEnabled, equals(true)); - expect(OIDC4VCType.EBSIV3.isEnabled, equals(true)); + expect(OIDC4VCType.EBSI.isEnabled, equals(true)); expect(OIDC4VCType.JWTVC.isEnabled, equals(false)); expect(OIDC4VCType.HAIP.isEnabled, equals(true)); }); diff --git a/test/app/shared/helper_functions/helper_functions_test.dart b/test/app/shared/helper_functions/helper_functions_test.dart index 89bed8bd4..fd1933e03 100644 --- a/test/app/shared/helper_functions/helper_functions_test.dart +++ b/test/app/shared/helper_functions/helper_functions_test.dart @@ -232,21 +232,21 @@ void main() { test('getIndexValue returns correct index for each DidKeyType', () { expect( - getIndexValue(isEBSIV3: true, didKeyType: DidKeyType.secp256k1), + getIndexValue(isEBSI: true, didKeyType: DidKeyType.secp256k1), 3, ); expect( - getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.secp256k1), + getIndexValue(isEBSI: false, didKeyType: DidKeyType.secp256k1), 1, ); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.p256), 4); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.ebsiv3), 5); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.jwkP256), 6); - expect(getIndexValue(isEBSIV3: false, didKeyType: DidKeyType.edDSA), 0); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.p256), 4); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.ebsiv3), 5); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.jwkP256), 6); + expect(getIndexValue(isEBSI: false, didKeyType: DidKeyType.edDSA), 0); expect( getIndexValue( - isEBSIV3: false, + isEBSI: false, didKeyType: DidKeyType.jwtClientAttestation, ), 0,