//* Licensed Materials - Property of *
//* IBM *
//* Miracle A/S *
//* Alexandra Instituttet A/S *
//* *
//* eu.abc4trust.pabce.1.34 *
//* *
//* (C) Copyright IBM Corp. 2014. All Rights Reserved. *
//* (C) Copyright Miracle A/S, Denmark. 2014. All Rights Reserved. *
//* (C) Copyright Alexandra Instituttet A/S, Denmark. 2014. All *
//* Rights Reserved. *
//* US Government Users Restricted Rights - Use, duplication or *
//* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
//* *
//* This file is licensed under the Apache License, Version 2.0 (the *
//* "License"); you may not use this file except in compliance with *
//* the License. You may obtain a copy of the License at: *
//* http://www.apache.org/licenses/LICENSE-2.0 *
//* Unless required by applicable law or agreed to in writing, *
//* software distributed under the License is distributed on an *
//* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
//* KIND, either express or implied. See the License for the *
//* specific language governing permissions and limitations *
//* under the License. *
//*/**/****************************************************************
package eu.abc4trust.util;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import eu.abc4trust.util.Constants.OperationType;
import eu.abc4trust.util.attributeEncoding.MyAttributeEncodingFactory;
import eu.abc4trust.util.attributeTypes.EnumAllowedValues;
import eu.abc4trust.util.attributeTypes.MyAttributeValue;
import eu.abc4trust.util.attributeTypes.MyAttributeValueFactory;
import eu.abc4trust.xml.AttributeDescription;
import eu.abc4trust.xml.AttributeInToken;
import eu.abc4trust.xml.AttributePredicate;
import eu.abc4trust.xml.AttributePredicate.Attribute;
import eu.abc4trust.xml.CredentialInToken;
import eu.abc4trust.xml.CredentialSpecification;
import eu.abc4trust.xml.FriendlyDescription;
import eu.abc4trust.xml.Message;
import eu.abc4trust.xml.ObjectFactory;
import eu.abc4trust.xml.PresentationTokenDescription;
import eu.abc4trust.xml.util.XmlUtils;
/**
* Policy parser, helper for Identity Mixer integration.
*/
public final class PolicyTranslator{
//TODO: add null checks!!!
private final Map<String, CredentialSpecification> credentialSpecList;
private final PresentationTokenDescription ptd;
private final String messageToSign;
private final Map<String, List<MyAttributeReference>> credentialAttrsList;
private final Map<String, MyAttributeReference> attrRefsCache;
private final Map<MyAttributeReference, MyAttributeValue> allAttrsAndValues;
private final List<MyAttributeReference> allDisclosedAttrs;
private final Map<MyAttributeReference, MyAttributeValue> allDisclosedAttrsAndValues;
private final List<MyAttributeReference> explicitlyDisclosedAttrs;
private final List<MyAttributeReference> inspectableAttrs;
private final Map<MyAttributeReference, BigInteger> inspectableAttrValues;
private final Set<Set<MyAttributeReference>> attrRefEqivClasses;
private final Set<Set<MyAttributeReference>> revealedAttrRefEqivClasses;
private final Map<MyAttributeReference, URI> attrRefToInspectorKey;
private List<MyPredicate> myPredicates;
private final Map<MyPredicate, List<CredentialInToken>> predicateCredInToken;
private final HashMap<String,CredentialInToken> aliasCredInTokenList;
private List<MyAttributeReference> oneOfAttrs = null;
//Friednly descriptions
private final Map<String, List<FriendlyDescription>> credAliasFriedlyDescrList;
private Map<MyAttributeReference, List<FriendlyDescription>> attrRefFriedlyDescrList;
public PolicyTranslator(PresentationTokenDescription ptd,
Map<String, CredentialSpecification> aliasCredSpecs) {
this.ptd = ptd;
this.oneOfAttrs = new ArrayList<MyAttributeReference>();
this.myPredicates = new ArrayList<MyPredicate>();
this.allDisclosedAttrs = new ArrayList<MyAttributeReference>();
this.explicitlyDisclosedAttrs = new ArrayList<MyAttributeReference>();
this.allAttrsAndValues = new HashMap<MyAttributeReference, MyAttributeValue>();
this.attrRefEqivClasses = new HashSet<Set<MyAttributeReference>>();
this.revealedAttrRefEqivClasses = new HashSet<Set<MyAttributeReference>>();
this.predicateCredInToken = new LinkedHashMap<MyPredicate,List<CredentialInToken>>();
// this.predicateCredInTokenWithCommitments = new HashMap<MyPredicate,List<CredentialInTokenWithCommitments>>();
this.credentialAttrsList = new HashMap<String, List<MyAttributeReference>>();
this.attrRefToInspectorKey = new HashMap<MyAttributeReference, URI>();
this.inspectableAttrValues = new HashMap<MyAttributeReference, BigInteger>();
this.messageToSign = this.parseMsgToSign();
this.attrRefsCache = new HashMap<String,MyAttributeReference>();
this.credentialSpecList = aliasCredSpecs;
this.aliasCredInTokenList = new LinkedHashMap<String, CredentialInToken>();
// this.aliasCredInTokenWithCommitmentsList = new HashMap<String, CredentialInTokenWithCommitments>();
this.inspectableAttrs = new ArrayList<MyAttributeReference>();
this.allDisclosedAttrsAndValues = new HashMap<MyAttributeReference, MyAttributeValue>();
//parse attributes that are revealed explicitly and under inspector pk
this.parseAllExplicitlyDisclosedAndInspectableAttributes();
//parse all predicates to use them for creating idemix proof spec
this.parseAllPredicates();
//figure out all implicitly revealed attributes from equality predicates
try {
this.createEquivalenceClassesForRevealedAndOneOfAttributes();
} catch (Exception e) {
e.printStackTrace();
}
//build a list of all (impl and expl) disclosed attributes and their values
this.setAllDisclosedAttributes();
this.completeCredentialDeclarations(); //generate all other attribute references to use in Idemix proof spec generator
this.updateAllPredicates();
//get friendly credential names, map them to credential aliases and attribute references
this.credAliasFriedlyDescrList = this.composeCredAliasFriendlyDescrList(aliasCredSpecs);
this.attrRefFriedlyDescrList = this.composeAttrRefsFriendlyDescrList(aliasCredSpecs, credentialAttrsList);
};
/**
* Prepares a string to sign
* @return
*/
private String parseMsgToSign() {
StringBuilder sb = new StringBuilder();
if (this.ptd.getMessage()!=null){
Message msgFromToken = this.ptd.getMessage();
if (msgFromToken.getNonce()!=null){
BigInteger nonce = new BigInteger(msgFromToken.getNonce());
sb.append("Nonce: " + nonce+"\n");
}
if (msgFromToken.getFriendlyPolicyName()!=null){
for (FriendlyDescription fd: msgFromToken.getFriendlyPolicyName()){
sb.append(fd.getLang() +": ");
sb.append(fd.getValue() +"\n");
}
}
if (msgFromToken.getFriendlyPolicyDescription()!=null){
for (FriendlyDescription fd: msgFromToken.getFriendlyPolicyDescription()){
sb.append(fd.getLang()+": ");
sb.append(fd.getValue()+"\n");
}
}
if (msgFromToken.getApplicationData()!=null){
ObjectFactory of = new ObjectFactory();
String xml;
try {
xml = XmlUtils.toNormalizedXML(of.createApplicationData(msgFromToken.getApplicationData()));
} catch (Exception e) {
String errorMessage = "Could not serialize Application data: " + e.getMessage();
e.printStackTrace();
throw new RuntimeException(errorMessage);
}
sb.append(xml);
}
}
// System.out.println(sb.toString());
if (!sb.toString().equals("null")){
return sb.toString();
} else {
return null;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The Identity Mixer implementation does not support proofs over attributes that are revealed. Therefore, all the
// arguments with attribute references whose value is disclosed are substituted with their disclosed values.
// The attribute reference is changed to Constant
private void updateAllPredicates() {
List<CredentialInToken> credsInPredicate = new ArrayList<CredentialInToken>();
List<MyPredicate> newPredicateList = new ArrayList<MyPredicate>();
for(MyPredicate predicate: this.myPredicates){
for (MyAttributeReference attrRefInPredicate: predicate.getArgumentReferences()){
if (this.allDisclosedAttrsAndValues.keySet().contains(attrRefInPredicate)){
MyAttributeValue value = this.allDisclosedAttrsAndValues.get(attrRefInPredicate);
predicate.addArgumentVal(attrRefInPredicate, value);
} else if ((!attrRefInPredicate.getAttributeReference().equals(Constants.CONSTANT))&&
(!credsInPredicate.contains(this.aliasCredInTokenList.get(attrRefInPredicate.getCredentialAlias())))){
credsInPredicate.add(this.aliasCredInTokenList.get(attrRefInPredicate.getCredentialAlias()));
}
}
newPredicateList.add(predicate);
this.predicateCredInToken.put(predicate, credsInPredicate);
}
this.myPredicates = newPredicateList;
}
/**
* Finalizes the Map<CredentialAlias, List<MyCredentialReferences>>
* Helper for creating Idemix Proof Spec
*/
private void completeCredentialDeclarations(){
for(String credAlias: this.credentialSpecList.keySet()){ //contains a cred spec for a credential that will be issued in the case if credTemplate is not null
List<MyAttributeReference> oldRefsList = this.credentialAttrsList.get(credAlias);
CredentialSpecification currentCredSpec = this.credentialSpecList.get(credAlias);
List<AttributeDescription> allAttributesInCred = currentCredSpec.getAttributeDescriptions().getAttributeDescription();
if ((oldRefsList==null)||((oldRefsList!=null)&&(oldRefsList.size()!=allAttributesInCred.size()))){
for(AttributeDescription ad: allAttributesInCred){
if (!this.attrRefsCache.containsKey(credAlias+ad.getType().toString())){
MyAttributeReference newref = new MyAttributeReference(URI.create(credAlias), ad.getType());
this.attrRefsCache.put(credAlias+ad.getType().toString(), newref);
this.addAttributeRefToCredentialAlias(credAlias, newref);
}
}
}
}
}
/**
* Adds specified attribute reference to a list of attribute references for given credential, specifies by alias
* @param credentialAlias
* @param myAttributeRef
*/
private void addAttributeRefToCredentialAlias(String credentialAlias, MyAttributeReference myAttributeRef){
List<MyAttributeReference> currentRefs = new ArrayList<MyAttributeReference>();
if (this.credentialAttrsList.get(credentialAlias)!=null){
currentRefs = this.credentialAttrsList.get(credentialAlias);
}
currentRefs.add(myAttributeRef);
this.credentialAttrsList.put(credentialAlias, currentRefs);
this.attrRefsCache.put(myAttributeRef.getAttributeReference(), myAttributeRef);
}
/**
* Parses all predicates from XML-based object to MyPredicate to use for creating Idemix ProofSpec
*/
private void parseAllPredicates(){
List<AttributePredicate> attrPredicates = this.ptd.getAttributePredicate();
for (AttributePredicate attrPredicate: attrPredicates){
MyPredicate myPredicate = this.parsePredicate(attrPredicate);
this.myPredicates.add(myPredicate);
}
}
/**
* Parses a predicate from XML-based object to MyPredicate to use for creating Idemix ProofSpec
*/
private MyPredicate parsePredicate(AttributePredicate attrPredicate){
MyPredicate myPredicate = new MyPredicate();
for (Object param : attrPredicate.getAttributeOrConstantValue()) { //parse arguments first
if (param instanceof Attribute) { // if it is an attribute
AttributePredicate.Attribute attParam = (AttributePredicate.Attribute) param;
URI credentialAlias = attParam.getCredentialAlias(); //get cred alias of the attributes in the predicate
MyAttributeReference myAttributeRef = null;
URI attributeType = attParam.getAttributeType();
String key = credentialAlias.toString()+attributeType.toString();
if (!this.attrRefsCache.containsKey(key)){
myAttributeRef = new MyAttributeReference(credentialAlias, attributeType);
this.attrRefsCache.put(key, myAttributeRef);
//add new ref to a map <CredAlias, List<MyAttrReference>>
this.addAttributeRefToCredentialAlias(credentialAlias.toString(), myAttributeRef);
} else {
myAttributeRef = this.attrRefsCache.get(key);
}
myPredicate.addArgument(myAttributeRef,null);
URI encoding = this.getAttributeEncoding(credentialAlias, attributeType);
myPredicate.setEncoding(encoding);
} else { // if not an attribute - extract a constant as a BigInteger!
MyAttributeValue constantValue =
MyAttributeValueFactory.parseValueFromFunction(attrPredicate.getFunction(), param);
MyAttributeReference myAttributeRef = null;
try {
myAttributeRef = new MyAttributeReference(new URI(""), new URI(Constants.CONSTANT));
} catch (URISyntaxException e) {
e.printStackTrace();
}
myPredicate.addArgument(myAttributeRef, constantValue);
}
}
String type = MyAttributeValueFactory.returnTypeOfFunction(attrPredicate.getFunction());
OperationType mode = MyAttributeValueFactory.operationTypeOfFunction(attrPredicate.getFunction());
myPredicate.setTypeOfFunction(type);
myPredicate.setModeOfOperation(mode);
return myPredicate;
}
private URI getAttributeEncoding(URI credentialAlias, URI attributeType) {
CredentialSpecification credSpec = this.credentialSpecList.get(credentialAlias.toString());
URI encoding = null;
for(AttributeDescription ad: credSpec.getAttributeDescriptions().getAttributeDescription()){
if(ad.getType().equals(attributeType)){
encoding = ad.getEncoding();
}
}
return encoding;
}
/**
* Determines in which of the given equivalence classes the given attribute reference is contained in and returns this class.<br/>
* In case the reference is not contained in a class yet, a new class containing the given reference is created and returned.
*
* @param attrRef
* @param equivalenceClasses
* @return
*/
private static Set<MyAttributeReference> getEquivalenceClass(final MyAttributeReference attrRef, Set<Set<MyAttributeReference>> equivalenceClasses) {
for (Set<MyAttributeReference> equivClass : equivalenceClasses) {
if (equivClass.contains(attrRef)) {
return equivClass;
}
}
// No class found, thus, attrRef is not contained in a class yet.
// Create a new class and add attrRef to this new class.
Set<MyAttributeReference> newClass = new HashSet<MyAttributeReference>();
newClass.add(attrRef);
// Add the new class to the set of classes and return the newly created class.
equivalenceClasses.add(newClass);
return newClass;
}
/**
* Merges the two equivalence classes of the two given attribute references.<br/>
* First, determines the classes for the individual references and then merges them in case they are different.<br/>
* <br/>
* @param attrRef1 The first attribute reference.
* @param attrRef2 The second attribute reference.
* @param equivalenceClasses The set of all equivalence classes.
*/
private static void mergeEquivalenceClasses(final MyAttributeReference attrRef1, final MyAttributeReference attrRef2, Set<Set<MyAttributeReference>> equivalenceClasses) {
Set<MyAttributeReference> equivClassLeft = getEquivalenceClass(attrRef1, equivalenceClasses);
Set<MyAttributeReference> equivClassRight = getEquivalenceClass(attrRef2, equivalenceClasses);
if (equivClassLeft != equivClassRight) {
// Remove both classes and re-add the merged class. Note: do not merge the classes into one and
// remove the other class: this leads to unspecified behavior because members of a Java Set must
// not be changed in a manner that affects equals comparisons while the object is an element in
// the set (see JavaDoc of Set).
equivalenceClasses.remove(equivClassLeft);
equivalenceClasses.remove(equivClassRight);
equivClassLeft.addAll(equivClassRight);
equivalenceClasses.add(equivClassLeft);
}
}
/**
* Builds sets of attributes that are in direct or indirect equality relationship (==) with another attribute,
* and all attributes that are disclosed.
* Here it does not matter whether the attribute is disclosed explicitly (via the given disclosedAttributes mapping) or
* implicitly (via transitive equality relations in the given predicates).<br/>
* The map entries for these attributes point to identifiers that have proof mode {@link ProofMode#REVEALED}.
* <br/>
* To determine above entries, the method creates equivalence classes of attribute references where all attribute references
* that are contained in the same class are equal according to the given predicates. Note that also transitive equality is considered.<br/>
* Then, equivalence classes are marked as 'revealed' if at least one of the attribute references contained in the class is revealed.<br/>
* <br/>
*/
private final void createEquivalenceClassesForRevealedAndOneOfAttributes() throws Exception {
for (MyPredicate predicate : this.myPredicates) {
//get arguments from the predicate, define their type (const/attr)
//first we consider ONEOF predicate - multiple arguments
if (predicate.getFunction().equals(Constants.OperationType.EQUALONEOF)){
MyAttributeReference l = predicate.getLeftRef();
this.oneOfAttrs.add(l);
} else {
//consider only predicates with 2 arguments
MyAttributeReference l = predicate.getLeftRef();
MyAttributeReference r = predicate.getRightRef();
boolean lIsConstant = l.isConstant();
boolean rIsConstant = r.isConstant();
//first we check equality predicates:
if (predicate.getFunction().equals(Constants.OperationType.EQUAL)){
if (!lIsConstant && !rIsConstant) {
//////////////////////////////////////////////////////////////////////////////////////////////
// PS(a.b == c.d) => to make a.b and c.d refer to the same identifiers in the proof specification
//////////////////////////////////////////////////////////////////////////////////////////////
mergeEquivalenceClasses(l, r, this.attrRefEqivClasses);
} else if (!lIsConstant && rIsConstant) {
//////////////////////////////////////////////////////////////////////////////////////////////
// PS(a.b == constExp) => reveal a.b
//////////////////////////////////////////////////////////////////////////////////////////////
this.revealedAttrRefEqivClasses.add(getEquivalenceClass(l, this.attrRefEqivClasses));
MyAttributeValue objValue = MyAttributeEncodingFactory.parseValueFromEncoding(predicate.getEncoding(), predicate.getRightVal().getValueAsObject(), predicate.getRightVal().getAllowedValues());
this.allAttrsAndValues.put(l, objValue);
} else if (lIsConstant && !rIsConstant) {
//////////////////////////////////////////////////////////////////////////////////////////////
// PS(constExp == a.b) => reveal a.b
//////////////////////////////////////////////////////////////////////////////////////////////
this.revealedAttrRefEqivClasses.add(getEquivalenceClass(r, this.attrRefEqivClasses));
MyAttributeValue objValue = MyAttributeEncodingFactory.parseValueFromEncoding(predicate.getEncoding(), predicate.getLeftVal().getValueAsObject(), predicate.getLeftVal().getAllowedValues());
this.allAttrsAndValues.put(r, objValue);
} else if (lIsConstant && rIsConstant) {
//////////////////////////////////////////////////////////////////////////////////////////////
// PS(constExp == constExp) => Nothing to prove for Idemix.
//////////////////////////////////////////////////////////////////////////////////////////////
} else {
//////////////////////////////////////////////////////////////////////////////////////////////
// PS(constNonAttrExp == nonConstNonAttrExp) => Not supported.
// PS(nonConstNonAttrExp == constNonAttrExp) => Not supported.
// PS(nonConstNonAttrExp == nonConstNonAttrExp) => Not supported.
//////////////////////////////////////////////////////////////////////////////////////////////
throw new Exception("Generation of an Idemix Proof Specification for expression '"+predicate.getPredicateAsString()+"' is currently not supported.");
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Mark those classes as 'revealed' that contain attributes that are revealed by the claim.
for (MyAttributeReference attRef : this.explicitlyDisclosedAttrs) {
this.revealedAttrRefEqivClasses.add(getEquivalenceClass(attRef, this.attrRefEqivClasses));
}
}//end for mypredicates
}
/**
* This method builds a list of all implicitly and explicitly disclosed attributes
* and their values used.
*/
private void setAllDisclosedAttributes(){
for(Set<MyAttributeReference> eqClass: this.revealedAttrRefEqivClasses){
for(MyAttributeReference atRef: eqClass){
this.allDisclosedAttrs.add(atRef);
MyAttributeValue myAttributeValue = this.allAttrsAndValues.get(atRef);
this.allDisclosedAttrsAndValues.put(atRef, myAttributeValue);
}
}
}
/**
* This method extracts all explicitly disclosed and inspectable attributes from the token description
* @param ptd
* @param aliasCreds
* @return Map matching alias of the credential with the type of the disclosed attribute
*/
private void parseAllExplicitlyDisclosedAndInspectableAttributes(){
List<CredentialInToken> credsintok = null;
int count = 0;
credsintok = this.ptd.getCredential();
count = credsintok.size();
for (int i = 0; i< count; i++){
CredentialInToken credintok = null;
CredentialSpecification credSpec = null;
List<AttributeInToken> attrsintok = null;
credintok = credsintok.get(i);
credSpec = this.credentialSpecList.get(credintok.getAlias().toString());
attrsintok = credintok.getDisclosedAttribute();
List<AttributeDescription> attrDescriptions = credSpec.getAttributeDescriptions().getAttributeDescription();
for (AttributeInToken attrintok : attrsintok){
MyAttributeValue objValue = null;
MyAttributeReference ref = null;
if(credintok != null) {
ref = new MyAttributeReference(credintok.getAlias(),
attrintok.getAttributeType());
}
if (attrintok.getInspectorPublicKeyUID()!=null){
this.inspectableAttrs.add(ref);
this.attrRefsCache.put(credintok.getAlias().toString()+attrintok.getAttributeType().toString(), ref);
MyAttributeReference attrRef = new MyAttributeReference(credintok.getAlias(), attrintok.getAttributeType());
this.attrRefToInspectorKey.put(attrRef, attrintok.getInspectorPublicKeyUID());
this.inspectableAttrValues.put(attrRef, null);
}else{
this.explicitlyDisclosedAttrs.add(ref);
this.allDisclosedAttrs.add(ref);
Object val = attrintok.getAttributeValue();
for (AttributeDescription ad: attrDescriptions){
if (ad.getType().equals(attrintok.getAttributeType())){
objValue = MyAttributeEncodingFactory.parseValueFromEncoding(ad.getEncoding(), val, new EnumAllowedValues(ad));
}
this.allDisclosedAttrsAndValues.put(ref, objValue);
}
}
this.allAttrsAndValues.put(ref, objValue);
this.attrRefsCache.put(credintok.getAlias().toString()+attrintok.getAttributeType().toString(), ref);
this.addAttributeRefToCredentialAlias(credintok.getAlias().toString(), ref);
}
List<URI> credUIDs = new ArrayList<URI>();
credUIDs.add(credintok.getCredentialSpecUID());
credUIDs.add(credintok.getIssuerParametersUID());
this.aliasCredInTokenList.put(credintok.getAlias().toString(), credintok);
}
}
public final void createListOfEqualOneOfAttributes(){
}
private Map<String,List<FriendlyDescription>> composeCredAliasFriendlyDescrList
(Map<String, CredentialSpecification> aliasCredSpecs){
Map<String,List<FriendlyDescription>> ret = new HashMap<String, List<FriendlyDescription>>();
for (String alias: aliasCredSpecs.keySet()){
ret.put(alias, aliasCredSpecs.get(alias).getFriendlyCredentialName());
}
return ret;
}
private Map<MyAttributeReference,List<FriendlyDescription>> composeAttrRefsFriendlyDescrList
(Map<String, CredentialSpecification> aliasCredSpecs, Map<String,List<MyAttributeReference>> credAliasAttributeRefList){
Map<MyAttributeReference, List<FriendlyDescription>> ret = new HashMap<MyAttributeReference, List<FriendlyDescription>>();
for (String alias: aliasCredSpecs.keySet()){
CredentialSpecification credSpec = aliasCredSpecs.get(alias);
for (AttributeDescription ad: credSpec.getAttributeDescriptions().getAttributeDescription()){
ret.put(attrRefsCache.get(alias+ad.getType().toString()), ad.getFriendlyAttributeName());
}
}
return ret;
}
//Return stuff
/**
* @return the credAliasFriedlyDescrList
*/
public Map<String, List<FriendlyDescription>> getCredAliasFriedlyDescrList() {
return credAliasFriedlyDescrList;
}
public Map<MyAttributeReference, List<FriendlyDescription>> getAttrRefFriedlyDescrList() {
return attrRefFriedlyDescrList;
}
public List<MyPredicate> getAllPredicates(){
return this.myPredicates;
}
public Map<MyAttributeReference, MyAttributeValue> getAllDisclosedAttributesAndValues() {
return this.allDisclosedAttrsAndValues;
}
public Map<String, CredentialSpecification> getCredSpecList() {
return this.credentialSpecList;
}
public String getMessageToSign(){
return this.messageToSign;
}
}