//* 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.abce.cryptoEngine.bridging;
import static eu.abc4trust.abce.internal.revocation.RevocationConstants.REVOCATION_HANDLE_STR;
import static org.junit.Assert.assertNotNull;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.xml.bind.JAXBException;
import junit.framework.Assert;
import org.junit.Test;
import org.xml.sax.SAXException;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.ibm.zurich.idmx.interfaces.util.Pair;
import eu.abc4trust.TestConfiguration;
import eu.abc4trust.abce.external.issuer.IssuerAbcEngine;
import eu.abc4trust.abce.external.revocation.RevocationAbcEngine;
import eu.abc4trust.abce.external.verifier.VerifierAbcEngine;
import eu.abc4trust.abce.integrationtests.Entities;
import eu.abc4trust.abce.integrationtests.Helper;
import eu.abc4trust.abce.testharness.IntegrationModuleFactory;
import eu.abc4trust.abce.testharness.IssuanceHelper;
import eu.abc4trust.cryptoEngine.CryptoEngineException;
import eu.abc4trust.guice.ProductionModuleFactory.CryptoEngine;
import eu.abc4trust.keyManager.KeyManager;
import eu.abc4trust.keyManager.KeyManagerException;
import eu.abc4trust.revocationProxy.revauth.RevocationProxyAuthority;
import eu.abc4trust.xml.CredentialDescription;
import eu.abc4trust.xml.CredentialInToken;
import eu.abc4trust.xml.CredentialSpecification;
import eu.abc4trust.xml.FriendlyDescription;
import eu.abc4trust.xml.IssuancePolicy;
import eu.abc4trust.xml.IssuerParameters;
import eu.abc4trust.xml.PresentationPolicyAlternatives;
import eu.abc4trust.xml.PresentationToken;
import eu.abc4trust.xml.Reference;
import eu.abc4trust.xml.RevocationAuthorityParameters;
import eu.abc4trust.xml.SystemParameters;
import eu.abc4trust.xml.VerifierParameters;
import eu.abc4trust.xml.util.XmlUtils;
public class BridgingTest {
private static final String PRESENTATION_POLICY_ALTERNATIVES_BRIDGING = "/eu/abc4trust/sampleXml/presentationPolicies/presentationPolicyAlternativesBridging.xml";
private static final String ISSUANCE_POLICY_PASSPORT = "/eu/abc4trust/sampleXml/issuance/issuancePolicyPassport.xml";
private static final String CREDENTIAL_SPECIFICATION_PASSPORT = "/eu/abc4trust/sampleXml/credspecs/credentialSpecificationPassport.xml";
private static final String ISSUANCE_POLICY_STUDENT_CARD = "/eu/abc4trust/sampleXml/issuance/issuancePolicyStudentCard.xml";
private static final String CREDENTIAL_SPECIFICATION_STUDENT_CARD = "/eu/abc4trust/sampleXml/credspecs/credentialSpecificationStudentCardForHotelBooking.xml";
private static final URI REVOCATION_UID = URI.create("revocationUID1");
private static final String USERNAME = "defaultUser";
private static final String NAME = "John";
private static final String LASTNAME = "Doe";
@Test(timeout=TestConfiguration.TEST_TIMEOUT)
public void bridgingTestUProve() throws Exception {
URI uprove_technology = Helper.getSignatureTechnologyURI("brands");
int keyLength = 1024;
Entities entities = new Entities();
entities.addEntity("UNIVERSITY", uprove_technology, false);
entities.addEntity("GOVERNMENT", uprove_technology, true);
entities.addEntity("USER");
entities.addEntity("HOTEL");
runTest(keyLength, entities);
}
@Test(timeout=TestConfiguration.TEST_TIMEOUT)
public void bridgingTestIdemix() throws Exception {
URI cl_technology = Helper.getSignatureTechnologyURI("cl");
int keyLength = 1024;
Entities entities = new Entities();
entities.addEntity("UNIVERSITY", cl_technology, false);
entities.addEntity("GOVERNMENT", cl_technology, true);
entities.addEntity("USER");
entities.addEntity("HOTEL");
runTest(keyLength, entities);
}
@Test(timeout=TestConfiguration.TEST_TIMEOUT)
public void bridgingTestDifferentIssuers() throws Exception {
URI uprove_technology = Helper.getSignatureTechnologyURI("brands");
URI cl_technology = Helper.getSignatureTechnologyURI("brands");
int keyLength = 1024;
Entities entities = new Entities();
entities.addEntity("UNIVERSITY", uprove_technology, false);
entities.addEntity("GOVERNMENT", cl_technology, true);
entities.addEntity("USER");
entities.addEntity("HOTEL");
runTest(keyLength, entities);
}
private void runTest(int keyLength, Entities entities) throws Exception {
// Setp up engines
Injector revocationInjector = Guice
.createInjector(IntegrationModuleFactory.newModule(new Random(1231),
CryptoEngine.IDEMIX));
RevocationProxyAuthority revocationProxyAuthority = revocationInjector
.getInstance(RevocationProxyAuthority.class);
KeyManager revocationKeyManager = revocationInjector
.getInstance(KeyManager.class);
Collection<Injector> injectors = createEntities(entities, revocationProxyAuthority);
SystemParameters systemParameters = Entities.setupSystemParameters(entities, keyLength);
revocationKeyManager.storeSystemParameters(systemParameters);
List<Object> parametersList = new ArrayList<Object>();
RevocationAuthorityParameters revocationAuthorityParameters = this.setupRevocationEngine(revocationInjector, REVOCATION_UID, keyLength);
// Setup issuers
URI credentialTechnologyGovernment = entities.getTechnology("GOVERNMENT");
URI issuerParametersGovernmentUID =
getIssuanceParametersUIDFromIssuancePolicy(ISSUANCE_POLICY_PASSPORT);
parametersList.add(setupIssuer(entities.getInjector("GOVERNMENT"), systemParameters,
credentialTechnologyGovernment, issuerParametersGovernmentUID, 7, REVOCATION_UID));
URI credentialTechnologyUniversity = entities.getTechnology("UNIVERSITY");
URI issuerParametersUniversityUID =
getIssuanceParametersUIDFromIssuancePolicy(ISSUANCE_POLICY_STUDENT_CARD);
parametersList.add(setupIssuer(entities.getInjector("UNIVERSITY"), systemParameters,
credentialTechnologyUniversity, issuerParametersUniversityUID, 6, null));
//Generate dummy issuer parameters for range proofs (only necessary for UProve+UProve setup
IssuerAbcEngine universityEngine = entities.getInjector("UNIVERSITY").getInstance(IssuerAbcEngine.class);
IssuerParameters dummyForRangeProof =
universityEngine.setupIssuerParameters(systemParameters, 0, URI.create("cl"),
URI.create("vp:rangeProof"), null, null);
parametersList.add(dummyForRangeProof);
// Store all issuer and inspector parameters to all key managers
entities.storePublicParametersToKeyManagers(parametersList);
// Store all credential specifications to all key managers
storeCredentialSpecificationToKeyManagers(injectors, CREDENTIAL_SPECIFICATION_PASSPORT);
storeCredentialSpecificationToKeyManagers(injectors, CREDENTIAL_SPECIFICATION_STUDENT_CARD);
addRevocationKeyManagers(entities, revocationAuthorityParameters);
VerifierAbcEngine verifierEngine = entities.getInjector("HOTEL").getInstance(VerifierAbcEngine.class);
VerifierParameters verifierParameters = verifierEngine.createVerifierParameters(systemParameters);
IssuanceHelper issuanceHelper = new IssuanceHelper();
// Step 1. Get passport.
System.out.println(">> Get passport.");
this.issueAndStorePassport(entities.getInjector("GOVERNMENT"), entities.getInjector("USER"),
issuanceHelper, verifierParameters).getCredentialUID();
// Step 2. Get student id.
System.out.println(">> Get student id.");
this.issueAndStoreStudentId(entities.getInjector("UNIVERSITY"), entities.getInjector("USER"),
issuanceHelper, verifierParameters).getCredentialUID();
// Step 4a. Book a hotel room using passport and student card.
System.out.println(">> Verify.");
@SuppressWarnings("unused")
PresentationToken pt = this.bookHotelRoom(
issuanceHelper, entities.getInjector("HOTEL"), entities.getInjector("USER"), verifierParameters);
// TODO Verifier driven revocation is currently not implemented
// Step 5. Do verifier driven revocation
// ???
// Step 4b. Booking a hotel room using passport and student card fails
// because customer is blacklisted by hotel.
//this.failBookingHotelRoom(hotelInjector,
// userInjector, issuanceHelper, verifierParameters);
}
private CredentialDescription issueAndStorePassport(Injector governmentInjector,
Injector userInjector, IssuanceHelper issuanceHelper, VerifierParameters verifierParameters)
throws Exception {
Map<String, Object> passportAtts = this.populatePassportAttributes();
return issuanceHelper.issueCredential(USERNAME, governmentInjector, userInjector,
CREDENTIAL_SPECIFICATION_PASSPORT, ISSUANCE_POLICY_PASSPORT,
passportAtts, verifierParameters);
}
private Map<String, Object> populatePassportAttributes() {
Map<String, Object> att = new HashMap<String, Object>();
att.put("Name", NAME);
att.put("LastName", LASTNAME);
att.put(REVOCATION_HANDLE_STR,
"http://admin.ch/passport/revocation/parameters");
att.put("PassportNumber", 895749);
att.put("Issued", "2010-02-06Z");
att.put("Expires", "2022-02-06Z");
att.put("IssuedBy", "admin.ch");
return att;
}
private CredentialDescription issueAndStoreStudentId(Injector univsersityInjector,
Injector userInjector, IssuanceHelper issuanceHelper, VerifierParameters verifierParameters)
throws Exception {
Map<String, Object> atts = this
.populateStudentIdIssuerAttributes();
return issuanceHelper.issueCredential(USERNAME, univsersityInjector, userInjector,
CREDENTIAL_SPECIFICATION_STUDENT_CARD,
ISSUANCE_POLICY_STUDENT_CARD, atts, verifierParameters);
}
private Map<String, Object> populateStudentIdIssuerAttributes() {
Map<String, Object> atts = new HashMap<String, Object>();
atts.put("Name", NAME);
atts.put("LastName", LASTNAME);
atts.put("StudentNumber", 345);
atts.put("Issued", "2012-02-02Z");
atts.put("Expires", "2022-02-02Z");
atts.put("IssuedBy", "ethz.ch");
return atts;
}
private PresentationToken bookHotelRoom(
IssuanceHelper issuanceHelper, Injector hotelInjector,
Injector userInjector, VerifierParameters verifierParameters) throws Exception {
return this.bookHotel(issuanceHelper, hotelInjector, userInjector, verifierParameters);
}
private PresentationToken bookHotel(IssuanceHelper issuanceHelper,
Injector hotelInjector, Injector userInjector, VerifierParameters verifierParameters)
throws Exception {
Pair<PresentationToken, PresentationPolicyAlternatives> p = issuanceHelper
.createPresentationToken(USERNAME, userInjector,
PRESENTATION_POLICY_ALTERNATIVES_BRIDGING, verifierParameters);
// Store all required cred specs in the verifier key manager.
KeyManager hotelKeyManager = hotelInjector.getInstance(KeyManager.class);
KeyManager userKeyManager = userInjector.getInstance(KeyManager.class);
PresentationToken pt = p.first;
assertNotNull(pt);
for (CredentialInToken cit: pt.getPresentationTokenDescription().getCredential()){
hotelKeyManager.storeCredentialSpecification(
cit.getCredentialSpecUID(),
userKeyManager.getCredentialSpecification(cit.getCredentialSpecUID()));
}
return issuanceHelper.verify(hotelInjector, p.second, p.first);
}
// Used for testing deactivated feature.
private void failBookingHotelRoom(
Injector hotelInjector, Injector userInjector,
IssuanceHelper issuanceHelper, VerifierParameters verifierParameters) throws Exception {
PresentationToken pt = this.bookHotel(issuanceHelper, hotelInjector, userInjector, verifierParameters);
// TODO: The user should not be able to create a presentation token as
// his passport number is on the Hotel blacklist.
Assert.assertNull(pt);
}
private Collection<Injector> createEntities(Entities entities, RevocationProxyAuthority revocationProxyAuthority) {
entities.initInjectors(revocationProxyAuthority);
return entities.getInjectors();
}
private RevocationAuthorityParameters setupRevocationEngine(Injector revocationInjector, URI revParamsUid, int keyLength) throws Exception{
RevocationAbcEngine revocationEngine = revocationInjector
.getInstance(RevocationAbcEngine.class);
Reference revocationInfoReference = new Reference();
revocationInfoReference.setReferenceType(URI.create("url"));
revocationInfoReference.getReferences().add(URI.create("https://example.org/"));
Reference nonRevocationEvidenceReference = new Reference();
nonRevocationEvidenceReference.setReferenceType(URI.create("url"));
nonRevocationEvidenceReference.getReferences().add(URI.create("https://example.org/"));
Reference nonRrevocationUpdateReference = new Reference();
nonRrevocationUpdateReference.setReferenceType(URI.create("url"));
nonRrevocationUpdateReference.getReferences().add(URI.create("https://example.org/"));
return revocationEngine.setupRevocationAuthorityParameters(keyLength,
Helper.getRevocationTechnologyURI("cl"), revParamsUid,
revocationInfoReference,
nonRevocationEvidenceReference,
nonRrevocationUpdateReference);
}
private URI getIssuanceParametersUIDFromIssuancePolicy(String pathToIssuancePolicy)
throws UnsupportedEncodingException, JAXBException, SAXException {
// Load issuance policy
IssuancePolicy issuancePolicy =
(IssuancePolicy) XmlUtils.getObjectFromXML(
this.getClass().getResourceAsStream(pathToIssuancePolicy), true);
// Get issuer parameters UID from credential template
return issuancePolicy.getCredentialTemplate().getIssuerParametersUID();
}
private IssuerParameters setupIssuer(Injector issuerInjector, SystemParameters systemParameters,
URI credentialTechnology, URI issuanceParametersUID,
int maximalNumberOfAttributes, URI revocationAuthority) throws CryptoEngineException {
// Generate issuer parameters.
IssuerAbcEngine issuerEngine = issuerInjector.getInstance(IssuerAbcEngine.class);
IssuerParameters issuerParameters =
issuerEngine.setupIssuerParameters(systemParameters,
maximalNumberOfAttributes, credentialTechnology, issuanceParametersUID, revocationAuthority, new LinkedList<FriendlyDescription>());
return issuerParameters;
}
private void storeCredentialSpecificationToKeyManagers(Collection<Injector> injectors,
String pathToCredentialSpecification) throws KeyManagerException,
UnsupportedEncodingException, JAXBException, SAXException {
// Load credential specifications.
CredentialSpecification credSpec =
(CredentialSpecification) XmlUtils.getObjectFromXML(
this.getClass().getResourceAsStream(pathToCredentialSpecification), true);
// Store credential specifications.
URI specificationUID = credSpec.getSpecificationUID();
for (Injector injector : injectors) {
KeyManager keyManager = injector.getInstance(KeyManager.class);
keyManager.storeCredentialSpecification(specificationUID, credSpec);
}
}
private void addRevocationKeyManagers(Entities entities, RevocationAuthorityParameters revAuthParams)
throws KeyManagerException{
for(Injector injector: entities.getInjectors()){
KeyManager keyManager = injector.getInstance(KeyManager.class);
keyManager.storeRevocationAuthorityParameters(revAuthParams.getParametersUID(), revAuthParams);
}
}
}