Skip to content

Commit

Permalink
feat: Show credential list and credential index in developer mode #2593
Browse files Browse the repository at this point in the history
  • Loading branch information
bibash28 committed Apr 15, 2024
1 parent deb123d commit a06010d
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
final customOidc4vcProfile = profileCubit.state.model.profileSetting
.selfSovereignIdentityOptions.customOidc4vcProfile;

String? statusListUri;
int? statusListIndex;

if (!customOidc4vcProfile.securityLevel) {
emit(
state.copyWith(
Expand All @@ -62,6 +65,8 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
state.copyWith(
credentialStatus: CredentialStatus.active,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
return;
Expand All @@ -75,6 +80,8 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
state.copyWith(
credentialStatus: CredentialStatus.expired,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
return;
Expand Down Expand Up @@ -102,6 +109,8 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
state.copyWith(
credentialStatus: CredentialStatus.invalidSignature,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
return;
Expand All @@ -114,17 +123,19 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
if (status != null && status is Map<String, dynamic>) {
final statusList = status['status_list'];
if (statusList != null && statusList is Map<String, dynamic>) {
final uri = statusList['uri'];
statusListUri = statusList['uri']?.toString();

final idx = statusList['idx'];
statusListIndex = idx is int ? idx : null;

if (idx != null && idx is int && uri != null && uri is String) {
if (statusListUri != null && statusListIndex is int) {
final headers = {
'Content-Type': 'application/json; charset=UTF-8',
'accept': 'application/statuslist+jwt',
};

final response = await client.get(
uri,
statusListUri,
headers: headers,
isCachingEnabled: customOidc4vcProfile.statusListCache,
);
Expand All @@ -146,6 +157,8 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
credentialStatus:
CredentialStatus.statusListInvalidSignature,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
return;
Expand All @@ -156,14 +169,15 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
newStatusList is Map<String, dynamic>) {
final lst = newStatusList['lst'].toString();

final bytes = profileCubit.oidc4vc.getByte(idx);
final bytes = profileCubit.oidc4vc.getByte(statusListIndex);

// '$idx = $bytes X 8 + $posOfBit'
final decompressedBytes =
profileCubit.oidc4vc.decodeAndZlibDecompress(lst);
final byteToCheck = decompressedBytes[bytes];

final posOfBit = profileCubit.oidc4vc.getPositionOfZlibBit(idx);
final posOfBit =
profileCubit.oidc4vc.getPositionOfZlibBit(statusListIndex);
final bit = profileCubit.oidc4vc
.getBit(byte: byteToCheck, bitPosition: posOfBit);

Expand All @@ -175,6 +189,8 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
state.copyWith(
credentialStatus: CredentialStatus.invalidStatus,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
return;
Expand All @@ -185,81 +201,82 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
}
}

if (item.format == VCFormatType.jwtVc.value ||
item.format == VCFormatType.jwtVcJson.value ||
item.format == VCFormatType.ldpVc.value) {
final credentialStatus = item.credentialPreview.credentialStatus;
if (credentialStatus != null) {
if (credentialStatus is List<dynamic>) {
for (final iteratedData in credentialStatus) {
if (iteratedData is Map<String, dynamic>) {
final data = CredentialStatusField.fromJson(iteratedData);

final url = data.statusListCredential;
final headers = {
'Content-Type': 'application/json; charset=UTF-8',
'accept': 'application/statuslist+jwt',
};

final response = await client.get(
url,
headers: headers,
isCachingEnabled: customOidc4vcProfile.statusListCache,
);
final credentialStatus = item.credentialPreview.credentialStatus;
if (credentialStatus != null) {
if (credentialStatus is List<dynamic>) {
for (final iteratedData in credentialStatus) {
if (iteratedData is Map<String, dynamic>) {
final data = CredentialStatusField.fromJson(iteratedData);

final payload = jwtDecode.parseJwt(response.toString());
statusListUri = data.statusListCredential;
final headers = {
'Content-Type': 'application/json; charset=UTF-8',
'accept': 'application/statuslist+jwt',
};

// verify the signature of the VC with the kid of the JWT
final VerificationType isVerified = await verifyEncodedData(
issuer: payload['iss']?.toString() ?? item.issuer,
jwtDecode: jwtDecode,
jwt: response.toString(),
fromStatusList: true,
isCachingEnabled: customOidc4vcProfile.statusListCache,
);
final response = await client.get(
statusListUri,
headers: headers,
isCachingEnabled: customOidc4vcProfile.statusListCache,
);

if (isVerified != VerificationType.verified) {
emit(
state.copyWith(
credentialStatus:
CredentialStatus.statusListInvalidSignature,
status: AppStatus.idle,
),
);
return;
}
final payload = jwtDecode.parseJwt(response.toString());

// verify the signature of the VC with the kid of the JWT
final VerificationType isVerified = await verifyEncodedData(
issuer: payload['iss']?.toString() ?? item.issuer,
jwtDecode: jwtDecode,
jwt: response.toString(),
fromStatusList: true,
isCachingEnabled: customOidc4vcProfile.statusListCache,
);

if (isVerified != VerificationType.verified) {
emit(
state.copyWith(
credentialStatus:
CredentialStatus.statusListInvalidSignature,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
return;
}

final vc = payload['vc'];
if (vc != null && vc is Map<String, dynamic>) {
final credentialSubject = vc['credentialSubject'];
if (credentialSubject != null &&
credentialSubject is Map<String, dynamic>) {
final encodedList = credentialSubject['encodedList'];

if (encodedList != null && encodedList is String) {
final decompressedBytes = profileCubit.oidc4vc
.decodeAndGzibDecompress(encodedList);

final idx = int.parse(data.statusListIndex);
final bytes = profileCubit.oidc4vc.getByte(idx);
final byteToCheck = decompressedBytes[bytes];
final posOfBit =
profileCubit.oidc4vc.getPositionOfGZipBit(idx);
final bit = profileCubit.oidc4vc
.getBit(byte: byteToCheck, bitPosition: posOfBit);

if (bit == 0) {
// active
} else {
// revoked
emit(
state.copyWith(
credentialStatus: CredentialStatus.invalidStatus,
status: AppStatus.idle,
),
);
return;
}
final vc = payload['vc'];
if (vc != null && vc is Map<String, dynamic>) {
final credentialSubject = vc['credentialSubject'];
if (credentialSubject != null &&
credentialSubject is Map<String, dynamic>) {
final encodedList = credentialSubject['encodedList'];

if (encodedList != null && encodedList is String) {
final decompressedBytes = profileCubit.oidc4vc
.decodeAndGzibDecompress(encodedList);

statusListIndex = int.parse(data.statusListIndex);

final bytes = profileCubit.oidc4vc.getByte(statusListIndex);
final byteToCheck = decompressedBytes[bytes];
final posOfBit = profileCubit.oidc4vc
.getPositionOfGZipBit(statusListIndex);
final bit = profileCubit.oidc4vc
.getBit(byte: byteToCheck, bitPosition: posOfBit);

if (bit == 0) {
// active
} else {
// revoked
emit(
state.copyWith(
credentialStatus: CredentialStatus.invalidStatus,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
return;
}
}
}
Expand Down Expand Up @@ -298,13 +315,17 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
state.copyWith(
credentialStatus: CredentialStatus.active,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
} else {
emit(
state.copyWith(
credentialStatus: CredentialStatus.invalidSignature,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
}
Expand Down Expand Up @@ -349,6 +370,8 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
state.copyWith(
credentialStatus: credentialStatus,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
} else {
Expand All @@ -362,6 +385,8 @@ class CredentialDetailsCubit extends Cubit<CredentialDetailsState> {
state.copyWith(
credentialStatus: CredentialStatus.invalidStatus,
status: AppStatus.idle,
statusListIndex: statusListIndex,
statusListUrl: statusListUri,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class CredentialDetailsState extends Equatable {
this.message,
this.credentialStatus,
this.credentialDetailTabStatus = CredentialDetailTabStatus.informations,
this.statusListUrl,
this.statusListIndex,
});

factory CredentialDetailsState.fromJson(Map<String, dynamic> json) =>
Expand All @@ -16,44 +18,47 @@ class CredentialDetailsState extends Equatable {
final StateMessage? message;
final CredentialStatus? credentialStatus;
final CredentialDetailTabStatus credentialDetailTabStatus;
final String? statusListUrl;
final int? statusListIndex;

CredentialDetailsState loading() {
return CredentialDetailsState(
status: AppStatus.loading,
credentialStatus: credentialStatus,
credentialDetailTabStatus: credentialDetailTabStatus,
);
return copyWith(status: AppStatus.loading);
}

CredentialDetailsState error({
required StateMessage message,
}) {
return CredentialDetailsState(
status: AppStatus.error,
credentialStatus: credentialStatus,
credentialDetailTabStatus: credentialDetailTabStatus,
message: message,
);
return copyWith(status: AppStatus.error, message: message);
}

CredentialDetailsState copyWith({
AppStatus? status,
StateMessage? message,
CredentialStatus? credentialStatus,
CredentialDetailTabStatus? credentialDetailTabStatus,
String? statusListUrl,
int? statusListIndex,
}) {
return CredentialDetailsState(
status: status ?? this.status,
message: message,
credentialStatus: credentialStatus ?? this.credentialStatus,
credentialDetailTabStatus:
credentialDetailTabStatus ?? this.credentialDetailTabStatus,
statusListUrl: statusListUrl ?? this.statusListUrl,
statusListIndex: statusListIndex ?? this.statusListIndex,
);
}

Map<String, dynamic> toJson() => _$CredentialDetailsStateToJson(this);

@override
List<Object?> get props =>
[credentialStatus, message, status, credentialDetailTabStatus];
List<Object?> get props => [
credentialStatus,
message,
status,
credentialDetailTabStatus,
statusListUrl,
statusListIndex,
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ class _CredentialsDetailsViewState extends State<CredentialsDetailsView> {
DeveloperDetails(
credentialModel: widget.credentialModel,
showVertically: showVerticalDescription,
statusListIndex: state.statusListIndex,
statusListUri: state.statusListUrl,
),
],

Expand Down
Loading

0 comments on commit a06010d

Please sign in to comment.