discloseValues function
Discloses all values in valuesToDisclose
of plaintextCredential
.
valuesToDisclose
contains the keys of the attributes, that should be disclosed.
Keys in nested object should be separated with . (point) from the parent-key, like here:
Imagine your plaintext Credential look like this:
{
"@context": [
"https://bccm-ssi.hs-mittweida.de/credentials"
],
"type": "ImmatrikulationCredential",
"issuanceDate": {
"value": "2021-03-09",
"salt": "0830fac0-ae9e-4097-85b0-03ddb3557eb6",
"hash": "0x9e51f7c66036d0eb2fcc3c1c5d9da18f96ae880681a676dcc92a3be22e4d7523"
},
"student": {
"type": "Student",
"givenName": {
"value": "Max",
"salt": "b36a876c-2029-417a-93fb-b4daf75ed959",
"hash": "0x30aa2b081c358aafdbbeb9436a167ee9e5bb003a8bd892ef33d50ba78ce1834e"
},
"familyName": {
"value": "Mustermann",
"salt": "2f55f35d-72a9-4986-8986-93d4e4d6f3bf",
"hash": "0x6be6118a83dd2b1c5a050da46ea301fe5512245d9cfb9966b88219b1ee54e8ba"
},
"address": {
"type": "PostalAddress",
"addressLocality": {
"value": "Mittweida",
"salt": "40f1403a-984f-41ed-8821-b987fe556a36",
"hash": "0x97144b9ff02df331935d394cd790a1ab76bf9c6a5b0747c3f03db931103cdf56"
},
"postalCode": {
"value": "09648",
"salt": "83cd01c2-0a30-4907-b8cd-0bd5808a217e",
"hash": "0x254cfac1490b2f8330925374de8a40b8c6d5efe41b3f80e0fe67c3c8cf783b8f"
},
"streetAddress": {
"value": "Am Schwanenteich 8",
"salt": "6fd7baf8-f798-4fde-86e2-d19203d9caf6",
"hash": "0x4b2e396e631e5a391cf6415bd3110fa420fc7167509ef15407ee48b6f827be9c"
}
}
}
}
and you only want to show your familyName and the postalCode of your living place, a working call of this function would be :
discloseValues(
plaintextCredential,
[issuanceDate,
student.givenName,
student.address.addressLocality,
student.address.streetAddress
])
If there is an array in the plaintext-Credential the array elements that should be disclosed, could be given as follows: arrayKey.arrayIndex e.g. friends.1. ArrayIndex starts with 0.
Implementation
String discloseValues(
dynamic plaintextCredential, List<String> valuesToDisclose) {
Map<String, dynamic> plaintextMap = credentialToMap(plaintextCredential);
Map<String, dynamic> result = {};
plaintextMap.forEach((key, value) {
result[key] = value;
if (!(key == '@context' ||
key == 'type' ||
key == '@type' ||
key == 'id' ||
key == 'hashAlg')) {
// if key is in map it should be a single string
if (_hashedAttributeSchemaStrict.validate(value).isValid) {
// check if key should be disclosed
if (valuesToDisclose.contains(key)) {
result.remove(key);
}
}
// new Object found
else if (_mapOfHashedAttributesSchema.validate(value).isValid) {
List<String> valuesSeen = [];
List<String> valuesToDiscloseNew = [];
//search in valuesToDisclose if sth. starts with key
for (var element in valuesToDisclose) {
if (valuesSeen.contains(element)) {
}
//key of Object is in List
else if (element == key) {
Map<String, dynamic> valueMap = value as Map<String, dynamic>;
valuesToDiscloseNew = valueMap.keys.toList();
}
// subkeys of Object are in List
else if (element.split('.').first == key) {
valuesToDiscloseNew.add(element.substring(key.length + 1));
valuesSeen.add(element);
}
}
var newValue = jsonDecode(discloseValues(value, valuesToDiscloseNew));
result[key] = newValue;
}
// array found
else if (value is List) {
result[key] = value;
int removed = 0;
List<String> valuesSeen = [];
for (var element in valuesToDisclose) {
if (valuesSeen.contains(element)) {
}
//whole Array should be disclosed
else if (element == key) {
List<String> valuesToDiscloseNew = [];
for (var i = 0; i < value.length; i++) {
valuesToDiscloseNew.add('$key.$i');
}
result[key] = jsonDecode(
discloseValues({key: value}, valuesToDiscloseNew))[key];
}
//elementwise disclosing
else if (element.split('.').first == key) {
int arrayIndex = int.parse(element.split('.')[1]);
if (_hashedAttributeSchemaStrict
.validate(value[arrayIndex - removed])
.isValid) {
result[key].removeAt(arrayIndex - removed);
removed++;
}
//Object in Array
else if (_mapOfHashedAttributesSchema
.validate(value[arrayIndex])
.isValid) {
//search in given keys, if sth. else should be disclosed
List<String> valuesToDiscloseNew = [];
for (var element in valuesToDisclose) {
if (element.split('.')[0] == key &&
int.parse(element.split('.')[1]) == arrayIndex) {
if (element.split('.').length > 2) {
valuesSeen.add(element);
valuesToDiscloseNew.add(element.substring(
key.length + 1 + arrayIndex.toString().length + 1));
} else {
valuesToDiscloseNew =
(value[arrayIndex] as Map<String, dynamic>)
.keys
.toList();
}
}
}
result[key][arrayIndex] = jsonDecode(
discloseValues(value[arrayIndex], valuesToDiscloseNew));
} else {
throw Exception(
'Malformed array element in array with key $key at index $arrayIndex');
}
}
}
} else {
throw Exception('Unknown data type at key $key');
}
}
});
return jsonEncode(result);
}