//* 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.ri.servicehelper.issuer; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.FileSystemException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.logging.Logger; import javax.xml.bind.DatatypeConverter; import javax.xml.bind.JAXBException; import org.xml.sax.SAXException; import com.google.inject.Guice; import com.google.inject.Injector; import eu.abc4trust.abce.external.issuer.IssuerAbcEngine; import eu.abc4trust.abce.external.issuer.SynchronizedIssuerAbcEngineImpl; import eu.abc4trust.abce.internal.issuer.credentialManager.CredentialManager; import eu.abc4trust.abce.internal.issuer.tokenManagerIssuer.TokenStorageIssuer; import eu.abc4trust.guice.ProductionModuleFactory; import eu.abc4trust.guice.ProductionModuleFactory.CryptoEngine; import eu.abc4trust.guice.configuration.AbceConfigurationImpl; import eu.abc4trust.guice.configuration.StorageFiles; import eu.abc4trust.keyManager.KeyManager; import eu.abc4trust.keyManager.KeyManagerException; import eu.abc4trust.ri.servicehelper.AbstractHelper; import eu.abc4trust.ri.servicehelper.FileSystem; import eu.abc4trust.ri.servicehelper.SystemParametersHelper; import eu.abc4trust.xml.Attribute; import eu.abc4trust.xml.AttributeDescription; import eu.abc4trust.xml.CredentialInPolicy; import eu.abc4trust.xml.CredentialInPolicy.IssuerAlternatives; import eu.abc4trust.xml.CredentialInPolicy.IssuerAlternatives.IssuerParametersUID; import eu.abc4trust.xml.CredentialSpecification; import eu.abc4trust.xml.FriendlyDescription; import eu.abc4trust.xml.IntegerParameter; import eu.abc4trust.xml.IssuanceLogEntry; import eu.abc4trust.xml.IssuanceMessage; import eu.abc4trust.xml.IssuanceMessageAndBoolean; import eu.abc4trust.xml.IssuancePolicy; import eu.abc4trust.xml.IssuerParameters; import eu.abc4trust.xml.ObjectFactory; import eu.abc4trust.xml.Parameter; import eu.abc4trust.xml.PresentationPolicy; import eu.abc4trust.xml.PublicKey; import eu.abc4trust.xml.RevocationAuthorityParameters; import eu.abc4trust.xml.RevocationInformation; import eu.abc4trust.xml.SecretKey; import eu.abc4trust.xml.SystemParameters; import eu.abc4trust.xml.util.XmlUtils; public class IssuanceHelper extends AbstractHelper { static Logger log = Logger.getLogger(IssuanceHelper.class.getName()); private static IssuanceHelper instance; /** * @return true if IssuanceHelper has been initialized */ public static synchronized boolean isInit() { return instance != null; } /** * Only used in test - can reset static instance */ public static synchronized void resetInstance() { System.err.println("WARNING IssuanceHelper.resetInstance : " + instance); instance = null; } /** * @return initialized instance of IssuanceHelper */ public static synchronized IssuanceHelper getInstance() { log.info("IssuanceHelper.getInstance : " + instance + (instance == null ? "" : " : " + instance)); if (instance == null) { throw new IllegalStateException("getInstance not called before using IssuanceHelper!"); } return instance; } /** * Private constructor for initializing/generating SystemParameters * * @param keyLength * * @param publicResources this prefix will be prepended on public resources files generated by the * IssuerAbcEnginge * @param privateStoragePrefix this prefix will be prepended on storage files needed by the * IssuerAbcEnginge * @throws URISyntaxException * @throws FileSystemException */ private IssuanceHelper(String publicResourcesPrefix, String privateStoragePrefix) throws URISyntaxException, FileSystemException { IssuanceHelper.log.info("IssuanceHelper : create instance - for generating SystemParameters " + " - private storage : " + privateStoragePrefix + " - publicResources : " + publicResourcesPrefix); this.publicResourcesPrefix = publicResourcesPrefix; this.privateStoragePrefix = privateStoragePrefix; createFoldersIfNoneExist(publicResourcesPrefix, privateStoragePrefix); try { AbceConfigurationImpl configuration = setupStorageFilesForConfiguration(privateStoragePrefix, CryptoEngine.IDEMIX); configuration .setUProveNumberOfCredentialsToGenerate(UPROVE_ISSUER_NUMBER_OF_CREDENTIAL_TOKENS_TO_GENERATE); configuration.setUProveRetryTimeout(UPROVE_SERVICE_TIMEOUT); Injector injector = Guice.createInjector(ProductionModuleFactory .newModule(configuration, CryptoEngine.IDEMIX)); IssuerAbcEngine eng = injector.getInstance(IssuerAbcEngine.class); singleEngine = new SynchronizedIssuerAbcEngineImpl(eng); keyManager = injector.getInstance(KeyManager.class); credentialManager = injector.getInstance(CredentialManager.class); random = configuration.getPrng(); issuerTokenStorage = injector.getInstance(TokenStorageIssuer.class); } catch (Exception e) { System.err.println("Init Failed"); e.printStackTrace(); throw new IllegalStateException("Could not setup issuer !", e); } } private void checkAndGenerateSystemParameters(int keyLength) throws Exception { try { generatedSystemParameters = keyManager.getSystemParameters(); log.info("SystemParameters already exists!"); return; } catch (KeyManagerException ignore) { log.fine("SystemParameters does not exist!"); } // go on and create createSystemParameters(singleEngine, keyLength); } /** * Setup IssuanceHelper * * @param keyLength * * @param publicResources this prefix will be prepended on public resources files generated by the * IssuerAbcEnginge * @param fileStoragePrefix this prefix will be prepended on storage files needed by the * IssuerAbcEnginge * @throws Exception */ public static synchronized IssuanceHelper initInstance(int keyLength, String publicResourcesPrefix, String privateStoragePrefix, SpecAndPolicy[] specAndPolicyList, List<RevocationAuthorityParameters> revocationAuthorityParametersList) throws Exception { if (instance != null) { throw new IllegalStateException("initInstance can only be called once!"); } log.info("IssuanceHelper.initInstance(Array)"); IssuanceHelper helper = new IssuanceHelper(publicResourcesPrefix, privateStoragePrefix); helper.checkAndGenerateSystemParameters(keyLength); helper.addRevocationAuthorities(helper.keyManager, revocationAuthorityParametersList); helper.initIssuerParemeterList(specAndPolicyList, helper.credentialManager); instance = helper; return instance; } public static synchronized IssuanceHelper initInstanceWithExitingSystemPareters( SystemParameters foreignSystemParameters, List<CredentialSpecification> foreignCredSpecList, List<IssuerParameters> foreignIssuerParamList, String publicResourcesPrefix, String privateStoragePrefix, SpecAndPolicy[] specAndPolicyList, List<RevocationAuthorityParameters> revocationAuthorityParametersList) throws Exception { IssuanceHelper helper = new IssuanceHelper(publicResourcesPrefix, privateStoragePrefix); // add 'foreign' issuer' try{ helper.keyManager.getSystemParameters(); }catch(KeyManagerException e){ log.info("helper did not have system params in memory - storing the ones given: "+foreignSystemParameters); helper.keyManager.storeSystemParameters(foreignSystemParameters); } helper.addCredentialSpecifications(foreignCredSpecList); helper.addIssuerParameters(foreignIssuerParamList); helper.generatedSystemParameters = helper.keyManager.getSystemParameters(); helper.addRevocationAuthorities(helper.keyManager, revocationAuthorityParametersList); helper.initIssuerParemeterList(specAndPolicyList, helper.credentialManager); instance = helper; return instance; } public static synchronized IssuanceHelper initInstanceForService( String systemAndIssuerParamsPrefix, String fileStoragePrefix) throws Exception { if (instance != null) { throw new IllegalStateException("initInstance can only be called once!"); } log.info("IssuanceHelper.initInstanceForService(Array)"); instance = new IssuanceHelper(systemAndIssuerParamsPrefix, fileStoragePrefix, new String[0]); return instance; } public static synchronized StorageFiles verifyFiles(boolean wipe_existing_storage, String fileStoragePrefix, CryptoEngine cryptoEngine) throws Exception { String v = getFileStoragePrefix(fileStoragePrefix, cryptoEngine); return AbstractHelper.verifyFiles(wipe_existing_storage, v); } /** * TODO : Verify that SystemParams generated for service are OK... Ends up using static * 'SystemParametersHelper.getLargeSystemParameters()' * * Private constructor - used for Service * * @param privateStoragePrefix this prefix will be prepended on storage files needed by the * IssuerAbcEnginge * @throws Exception */ private IssuanceHelper(String publicResourcesPrefix, String privateStoragePrefix, String[] revocationAuthorityParametersResourcesList) throws Exception { IssuanceHelper.log.info("IssuanceHelper : create instance for issuer service " + privateStoragePrefix); this.publicResourcesPrefix = publicResourcesPrefix; this.privateStoragePrefix = privateStoragePrefix; this.createFoldersIfNoneExist(publicResourcesPrefix, privateStoragePrefix); AbceConfigurationImpl configuration = this.setupConfiguration(); Injector injector = Guice.createInjector(ProductionModuleFactory.newModule(configuration, CryptoEngine.IDEMIX)); IssuerAbcEngine engine = injector.getInstance(IssuerAbcEngine.class); this.singleEngine = new SynchronizedIssuerAbcEngineImpl(engine); this.keyManager = injector.getInstance(KeyManager.class); String systemParametersResource = this.privateStoragePrefix + SYSTEM_PARAMS_XML_NAME; SystemParameters systemParameters = SystemParametersHelper.checkAndLoadSystemParametersIfAbsent(this.keyManager, systemParametersResource); if (systemParameters == null) { IssuanceHelper.log.info("No system parameters loaded"); } this.issuerTokenStorage = injector.getInstance(TokenStorageIssuer.class); this.addRevocationAuthorities(this.keyManager, revocationAuthorityParametersResourcesList); this.random = configuration.getPrng(); // new SecureRandom(); // new Random(1985); } private void createFoldersIfNoneExist(String publicResources, String privateResources) throws FileSystemException{ File f = new File(publicResources); if(!f.exists()){ if(!f.mkdirs()){ throw new FileSystemException(publicResources); } } f = new File(privateResources); if(!f.exists()){ if(!f.mkdirs()){ throw new FileSystemException(privateResources); } } } private IssuerAbcEngine singleEngine = null; private TokenStorageIssuer issuerTokenStorage; private CredentialManager credentialManager; private final Map<String, SpecAndPolicy> specAndPolicyMap = new HashMap<String, SpecAndPolicy>(); private Random random; private final ObjectFactory of = new ObjectFactory(); private final String publicResourcesPrefix; private final String privateStoragePrefix; // private static final boolean STORE_RESOURCES_AS_SERIALIZED_JAVA_OBJECTS = false; // private final String systemParametersResource; private AbceConfigurationImpl setupConfiguration() throws Exception { AbceConfigurationImpl configuration = setupStorageFilesForConfiguration(privateStoragePrefix, CryptoEngine.IDEMIX); configuration .setUProveNumberOfCredentialsToGenerate(UPROVE_ISSUER_NUMBER_OF_CREDENTIAL_TOKENS_TO_GENERATE); configuration.setUProveRetryTimeout(UPROVE_SERVICE_TIMEOUT); return configuration; } public static String getFileStoragePrefix(String filePrefix, CryptoEngine cryptoEngine) { if ((filePrefix != null) && (filePrefix.length() > 0)) { if (filePrefix.endsWith("_")) { return filePrefix + ("" + cryptoEngine).toLowerCase() + "_"; } else { if (filePrefix.endsWith("/") || filePrefix.endsWith("\\")) { // this is a folder... return filePrefix + ("" + cryptoEngine).toLowerCase() + "_"; } else { return filePrefix + ("_" + cryptoEngine).toLowerCase() + "_"; } } } return ("" + cryptoEngine).toLowerCase(); } private SystemParameters generatedSystemParameters = null; // use from service public SystemParameters createNewSystemParametersKeylength(int keyLength) throws IOException, KeyManagerException, Exception { SystemParameters sp = singleEngine.setupSystemParameters(keyLength); keyManager.storeSystemParameters(sp); return sp; } private void createSystemParameters(IssuerAbcEngine engine, int keyLength) throws Exception { log.info("- create new system parameters with keysize: " + keyLength); // ok - we have to generate them from scratch... this.generatedSystemParameters = engine.setupSystemParameters(keyLength); storeAndPublishSystemParameters(); } private SystemParameters storeAndPublishSystemParameters() throws Exception { log.info("- store and publish generated (or imported systemparameters)"); // store in private storage folder if (STORE_RESOURCES_AS_SERIALIZED_JAVA_OBJECTS) { FileSystem.storeObjectInFile(this.generatedSystemParameters, this.privateStoragePrefix + SYSTEM_PARAMS_OBJ_NAME); } FileSystem.storeObjectAsXMLInFile( this.of.createSystemParameters(this.generatedSystemParameters), this.privateStoragePrefix, SYSTEM_PARAMS_XML_NAME); if (!this.privateStoragePrefix.equals(this.publicResourcesPrefix)) { // store in resource folder (for easier export to other ABCEs) // String systemParametersResource_resourcePrefix = // this.systemAndIssuerParamsPrefix + SYSTEM_PARAMS_NAME; FileSystem.storeObjectAsXMLInFile( this.of.createSystemParameters(this.generatedSystemParameters), this.publicResourcesPrefix, SYSTEM_PARAMS_XML_NAME); if (STORE_RESOURCES_AS_SERIALIZED_JAVA_OBJECTS) { FileSystem.storeObjectInFile(this.generatedSystemParameters, this.publicResourcesPrefix, SYSTEM_PARAMS_OBJ_NAME); } } // store in keyManager boolean success = keyManager.storeSystemParameters(this.generatedSystemParameters); if(!success){ log.info("Could not store system parameters in keymanager!"); }else{ log.info("Successfully stored system parameters in keymanager!"); } // this.storeSystemParametersAsXML(this.fileStoragePrefix, this.generatedSystemParameters, // SYSTEM_PARAMS_NAME); IssuanceHelper.log.info("- new SystemParameters."); return this.generatedSystemParameters; } // private void storeSystemParametersAsXML(String filePrefix, SystemParameters systemParameters, // String name) throws Exception { // SystemParameters serializedSystemParameters = SystemParametersUtil.serialize(systemParameters); // JAXBElement<SystemParameters> asXml = // this.of.createSystemParameters(serializedSystemParameters); // FileSystem.storeObjectAsXMLInFile(asXml, filePrefix, name); // } private void initIssuerParemeterList(SpecAndPolicy[] specAndPolicyList, CredentialManager credentialManager) throws Exception { IssuanceHelper.log.info("initIssuerParemeterList..:"); if (!keyManager.hasSystemParameters() || (this.generatedSystemParameters == null)) { throw new IllegalAccessException("initSystemParameters - should have setup SystemParameters"); } SystemParameters systemParameters = null; systemParameters = keyManager.getSystemParameters(); for (SpecAndPolicy currentSap : specAndPolicyList) { this.initIssuerParemeters(// cryptoEngine, initEngine, keyManager, this.publicResourcesPrefix, systemParameters, currentSap, credentialManager); } } private void initIssuerParemeters( // CryptoEngine cryptoEngine, // IssuerAbcEngine initEngine, KeyManager keyManager, String systemAndIssuerParamsPrefix, SystemParameters systemParameters, SpecAndPolicy currentSap, CredentialManager credentialManager) throws Exception, KeyManagerException, URISyntaxException, IOException { SpecAndPolicy sap = this.initSpecAndPolicyFromResouces(currentSap); CredentialSpecification credSpec = sap.getCredentialSpecification(); URI policyIssuerParametersUID = sap.getIssuancePolicy().getCredentialTemplate().getIssuerParametersUID(); IssuanceHelper.log.info("Check Credential Specification / Issuance Policy : " + credSpec.getSpecificationUID() + " : " + policyIssuerParametersUID); this.checkIfCredSpecIsInKeystoreAddIfAbsent(keyManager, credSpec); URI hash = new URI("urn:abc4trust:1.0:hashalgorithm:sha-256"); URI issuerParamsUid; if (sap.issuerParamsUid_URI != null) { issuerParamsUid = new URI(sap.issuerParamsUid); } else { // use default! boolean urnScheme = "urn".equals(policyIssuerParametersUID.getScheme()); issuerParamsUid = URI.create(policyIssuerParametersUID + ((urnScheme ? ":" : "/") + sap.cryptoTechnology.toString()).toLowerCase()); sap.issuerParamsUid_URI = issuerParamsUid; } if (!sap.getIssuancePolicy().getCredentialTemplate().getIssuerParametersUID() .equals(issuerParamsUid)) { log.fine("PATCH : " + issuerParamsUid + " : " + sap.getIssuancePolicy().getCredentialTemplate().getIssuerParametersUID()); sap.getIssuancePolicy().getCredentialTemplate().setIssuerParametersUID(issuerParamsUid); } URI revocationParamsUid; if (sap.revocationParamsUid != null) { revocationParamsUid = new URI(sap.revocationParamsUid); } else { revocationParamsUid = null; // new URI(credSpec.getSpecificationUID() + (urnScheme ? ":" : // "/") + "revocationUID"); } sap.revocationParamsUid_URI = revocationParamsUid; IssuanceHelper.log.info("Check Issuance Parameters : " + issuerParamsUid + " : " + revocationParamsUid); IssuerParameters issuerParameters = keyManager.getIssuerParameters(issuerParamsUid); if (issuerParameters != null) { IssuanceHelper.log.info(" - issuer params exists! " + issuerParamsUid + " - with UID : " + issuerParameters.getParametersUID() + " - and version number : " + issuerParameters.getVersion()); IssuanceHelper.log.info(" : " + issuerParameters.getSystemParametersUID()); } else { this.setupAndStoreIssuerParameters( currentSap.cryptoTechnology, // initEngine, // keyManager, // credentialManager, systemAndIssuerParamsPrefix, systemParameters, credSpec, hash, issuerParamsUid, revocationParamsUid, sap.friendlyDescriptions, currentSap.maximalNumberOfAttributes, currentSap.numberOfTokens); } // Needed ?? // sap.issuancePolicy.getCredentialTemplate().setIssuerParametersUID( // issuerParameters.getParametersUID()); // sap.getIssuancePolicy().getCredentialTemplate().setIssuerParametersUID(issuerParamsUid); // String sapKey = sap.key + "::" + cryptoEngine; // IssuanceHelper.log.info(" - add spec/policy : " + sapKey + " : " // + sap.getCredentialSpecification().getSpecificationUID()); this.specAndPolicyMap.put(sap.key, sap); } private IssuerParameters setupAndStoreIssuerParameters(CryptoTechnology cryptoTechnology, String systemAndIssuerParamsPrefix, SystemParameters systemParameters, CredentialSpecification credSpec, URI hash, URI issuerParamsUid, URI revocationParamsUid, List<FriendlyDescription> friendlyDescriptions, int maximalNumberOfAttributes, int numberOfTokens) throws Exception { IssuerParameters issuerParameters; IssuanceHelper.log.info(" - create Issuer Parameters : " + cryptoTechnology.getURI() + " : " + issuerParamsUid); issuerParameters = singleEngine.setupIssuerParameters(systemParameters, maximalNumberOfAttributes, cryptoTechnology.getURI(), issuerParamsUid, revocationParamsUid, friendlyDescriptions); IssuanceHelper.log.info(" - store Issuer Parameters! " + issuerParamsUid + " : " + issuerParameters + " - with version number : " + issuerParameters.getVersion()); if (cryptoTechnology == CryptoTechnology.UPROVE) { // set number of attributes! // PublicKey pk = // ((JAXBElement<PublicKey>) issuerParameters.getCryptoParams().getContent().get(0)).getValue(); XmlUtils.fixNestedContent(issuerParameters.getCryptoParams()); PublicKey pk = (PublicKey) issuerParameters.getCryptoParams().getContent().get(0); String uproveTokensKey = "urn:idmx:3.0.0:issuer:publicKey:uprove:tokens"; for (Parameter p : pk.getParameter()) { if (uproveTokensKey.equals(p.getName())) { IntegerParameter ip = (IntegerParameter) p; ip.setValue(numberOfTokens); break; } } } keyManager.storeIssuerParameters(issuerParamsUid, issuerParameters); IssuanceHelper.log.info(" - save in file - spec : " + credSpec.getSpecificationUID() + " - key : " + issuerParamsUid + " - filename : " + getParamsFilename("issuer_params_", ".xml", issuerParamsUid)); FileSystem.storeObjectAsXMLInFile(this.of.createIssuerParameters(issuerParameters), this.publicResourcesPrefix, getParamsFilename("issuer_params_", ".xml", issuerParamsUid)); if (STORE_RESOURCES_AS_SERIALIZED_JAVA_OBJECTS) { FileSystem.storeObjectInFile(issuerParameters, this.publicResourcesPrefix, getParamsFilename("issuer_params_", ".obj", issuerParamsUid)); } FileSystem.storeObjectAsXMLInFile(this.of.createCredentialSpecification(credSpec), this.publicResourcesPrefix, getParamsFilename("cred_spec_", ".xml", issuerParamsUid)); if (credentialManager != null) { SecretKey issuerPrivateKeyForIssuerParameters = credentialManager.getIssuerSecretKey(issuerParamsUid); if (issuerPrivateKeyForIssuerParameters != null) { FileSystem.storeObjectAsXMLInFile( this.of.createIssuerSecretKey(issuerPrivateKeyForIssuerParameters), this.privateStoragePrefix, this.getParamsFilename("issuer_private_key_", ".xml", issuerParamsUid)); if (STORE_RESOURCES_AS_SERIALIZED_JAVA_OBJECTS) { FileSystem.storeObjectInFile(issuerPrivateKeyForIssuerParameters, this.privateStoragePrefix, this.getParamsFilename("issuer_private_key_", ".obj", issuerParamsUid)); } } } IssuanceHelper.log.info(" - created issuerParameters with UID : " + issuerParameters.getParametersUID()); return issuerParameters; } private String getParamsFilename(String prefix, String suffix, URI issuerParamsUid) { boolean urnScheme = "urn".equals(issuerParamsUid.getScheme()); String issuer_params_filename = prefix; if (urnScheme) { issuer_params_filename += issuerParamsUid.toASCIIString().replaceAll(":", "_"); } else { issuer_params_filename += issuerParamsUid.getHost().replace(".", "_") + issuerParamsUid.getPath().replace("/", "_"); } return issuer_params_filename + suffix; } private String getParamsFilename(String prefix, URI issuerParamsUid, boolean urnScheme) { String issuer_params_filename = prefix; if (urnScheme) { issuer_params_filename += issuerParamsUid.toASCIIString().replaceAll(":", "_"); } else { issuer_params_filename += issuerParamsUid.getHost().replace(".", "_") + issuerParamsUid.getPath().replace("/", "_"); } return issuer_params_filename; } private String getCredSpecFilename(URI uid) { String filename = "cred_spec_"; filename += uid.toASCIIString().replaceAll(":", "_"); filename = filename.replaceAll(":", "_").replace("/", "_"); return filename; } private void checkIfCredSpecIsInKeystoreAddIfAbsent(KeyManager keyManager, CredentialSpecification credSpec) throws KeyManagerException { CredentialSpecification credSpecInKeystore = keyManager.getCredentialSpecification(credSpec.getSpecificationUID()); if (credSpecInKeystore != null) { IssuanceHelper.log.info(" - credspec already in keystore : " + credSpec.getSpecificationUID() + " : " + credSpec); try { IssuanceHelper.log .info("credSpec: " + XmlUtils.toXml(new ObjectFactory() .createCredentialSpecification(credSpecInKeystore))); } catch (Exception e) { e.printStackTrace(); } } else { IssuanceHelper.log.info(" - store credspec in keystre : "); keyManager.storeCredentialSpecification(credSpec.getSpecificationUID(), credSpec); try { IssuanceHelper.log.info("credSpec: " + XmlUtils.toXml(new ObjectFactory().createCredentialSpecification(credSpec))); } catch (Exception e) { e.printStackTrace(); } } } // called for Service.. public IssuerParameters setupIssuerParameters(CryptoEngine cryptoEngine, CredentialSpecification credSpec, SystemParameters systemParameters, URI issuerParamsUid, URI hash, URI revocationParamsUid, String systemAndIssuerParamsPrefix, List<FriendlyDescription> friendlyDescriptions) throws Exception { IssuerParameters issuerParameters = null; IssuanceHelper.log.info("cryptoEngine: " + cryptoEngine); CryptoTechnology ct; switch (cryptoEngine) { case IDEMIX: ct = CryptoTechnology.IDEMIX; break; case UPROVE: ct = CryptoTechnology.UPROVE; break; default: throw new IllegalStateException("The crypto engine: " + cryptoEngine + " is not supported use IDEMIX or UPROVE instead"); } issuerParameters = this.setupAndStoreIssuerParameters(ct, systemAndIssuerParamsPrefix, systemParameters, credSpec, hash, issuerParamsUid, revocationParamsUid, friendlyDescriptions, 20, 10); return issuerParameters; } public void registerSmartcardScopeExclusivePseudonym(BigInteger pse) throws IOException { // TODO : VERIFY : Must match the way pseudonums are created... String primaryKey = DatatypeConverter.printBase64Binary(pse.toByteArray()); if (!issuerTokenStorage.checkForPseudonym(primaryKey)) { log.info("registerSmartcardScopeExclusivePseudonym - register new pseudonym - BigInteger: " + pse + " - PseudonymPrimaryKey : " + primaryKey); issuerTokenStorage.addPseudonymPrimaryKey(primaryKey); } else { log.info("registerSmartcardScopeExclusivePseudonym - already registered"); } } /** * Creates a new instance of SpecAndPolicy * * @param credspecAndPolicyKey * @return * @throws Exception */ public SpecAndPolicy initSpecAndPolicy(String specAndPolicyKey) throws Exception { SpecAndPolicy cached = this.specAndPolicyMap.get(specAndPolicyKey); log.fine("initSpecAndPolicy - cached! \n- " + XmlUtils.toXml(this.of.createIssuancePolicy(cached.getIssuancePolicy()))); SpecAndPolicy cloned = new SpecAndPolicy(cached); return cloned; } private void modifyPA(PresentationPolicy pp) throws Exception { log.info("modifyPA - sdd RevocationInformation UIDs to Policy."); // try to make sure that RevocationInformation is only fetch once per RevAuth Map<URI, RevocationInformation> revocationInformationMap = new HashMap<URI, RevocationInformation>(); // REVOCATION! for (CredentialInPolicy cred : pp.getCredential()) { List<URI> credSpecURIList = cred.getCredentialSpecAlternatives().getCredentialSpecUID(); boolean containsRevoceableCredential = false; CredentialSpecification credSpec = null; for (URI uri : credSpecURIList) { try { credSpec = this.keyManager.getCredentialSpecification(uri); if (credSpec.isRevocable()) { containsRevoceableCredential = true; break; } } catch (KeyManagerException ignore) {} } if (containsRevoceableCredential) { IssuerAlternatives ia = cred.getIssuerAlternatives(); log.fine("WE HAVE REVOCEABLE CREDENTIAL : " + ia); for (IssuerParametersUID ipUid : ia.getIssuerParametersUID()) { IssuerParameters ip = this.keyManager.getIssuerParameters(ipUid.getValue()); if ((ip != null) && (ip.getRevocationParametersUID() != null)) { // issuer params / credspec has revocation... RevocationInformation ri = revocationInformationMap.get(ip.getRevocationParametersUID()); log.fine("RevocationInformation : " + ri); if (ri == null) { log.fine("Getting rev parameters uid information: " + ip.getRevocationParametersUID()); log.fine("Getting rev parameters uid information: " + keyManager.getRevocationAuthorityParameters(ip.getRevocationParametersUID())); ri = this.keyManager.getLatestRevocationInformation(ip.getRevocationParametersUID()); revocationInformationMap.put(ip.getRevocationParametersUID(), ri); } log.fine("RevocationInformation : " + ri.getRevocationInformationUID()); URI revInfoUid = ri.getRevocationInformationUID(); ipUid.setRevocationInformationUID(revInfoUid); } } } } log.fine(" - presentationPolicy modified to include RevocationInformation"); } private SpecAndPolicy initSpecAndPolicyFromResouces(SpecAndPolicy cloneThisSap) throws Exception { SpecAndPolicy sap = new SpecAndPolicy(cloneThisSap); IssuanceHelper.log.info("initSpecAndPolicyFromResouces : " + sap + " - " + sap.specResource + " : " + sap.policyResource + " : " + sap.issuerParamsUid); InputStream is; CredentialSpecification credSpec = this.initCredentialSpecificationFromResources(sap); is = FileSystem.getInputStream(sap.policyResource); if (is == null) { throw new IllegalStateException("Illegal resource name for IssuancePolicy : " + sap.policyResource); } IssuancePolicy issuancePolicy = (IssuancePolicy) XmlUtils.getObjectFromXML(is, true); if (!credSpec.getSpecificationUID().equals( issuancePolicy.getCredentialTemplate().getCredentialSpecUID())) { throw new IllegalStateException( "SpecificationUID must mactch for CredentialSpecification and IssuancePolicy : " + credSpec.getSpecificationUID() + " != " + issuancePolicy.getCredentialTemplate().getCredentialSpecUID()); } sap.setCredentialSpecification(credSpec); sap.setIssuancePolicy(issuancePolicy); return sap; } private CredentialSpecification initCredentialSpecificationFromResources(SpecAndPolicy sap) throws IOException, JAXBException, UnsupportedEncodingException, SAXException { InputStream is = FileSystem.getInputStream(sap.specResource); if (is == null) { throw new IllegalStateException("Illegal resource name for CredSpec : " + sap.specResource); } CredentialSpecification credSpec = (CredentialSpecification) XmlUtils.getObjectFromXML(is, true); return credSpec; } /** * Process next step of issuance on IssuanceMessager * * @param issuanceMessage IssuanceMessager as String * @return * @throws Exception */ public IssuanceMessageAndBoolean issueStep(IssuanceMessage issuanceMessage) throws Exception { IssuanceHelper.log.info("IssuanceHelper - step_jaxb - marchalled object: " + issuanceMessage); if (this.singleEngine == null) { throw new IllegalStateException( "IssuanceHelper.issueStep called without specifying CryptoEngine!"); } return this.issueStep(this.singleEngine, issuanceMessage); } private IssuanceMessageAndBoolean issueStep(IssuerAbcEngine useEngine, IssuanceMessage issuanceMessage) throws Exception { IssuanceMessageAndBoolean response; try { response = useEngine.issuanceProtocolStep(issuanceMessage); } catch (Exception e) { System.err .println("- IssuerABCE could not process Step IssuanceMessage from UserABCE : " + e); throw new Exception("Could not process next step on issuauce : ", e); } if (response.isLastMessage()) { IssuanceHelper.log.info(" - last step - on server"); } else { IssuanceHelper.log.info(" - continue steps"); } return response; } public IssuanceMessageAndBoolean reIssueStep(IssuanceMessage issuanceMessage) throws Exception { IssuanceMessageAndBoolean response; try { response = this.singleEngine.reIssuanceProtocolStep(issuanceMessage); } catch (Exception e) { System.err .println("- IssuerABCE could not process Step IssuanceMessage from UserABCE : " + e); throw new Exception("Could not process next step on issuauce : ", e); } if (response.isLastMessage()) { IssuanceHelper.log.info(" - last step - on server"); } else { IssuanceHelper.log.info(" - continue steps"); } return response; } public IssuanceMessage initReIssuance(String specAndPolicyKey) throws Exception { SpecAndPolicy specAndPolicy = this.specAndPolicyMap.get(specAndPolicyKey); if (specAndPolicy == null) { IssuanceHelper.log.info("IssuanceHelper - initReIssuance : " + specAndPolicyKey + " : " + this.specAndPolicyMap); throw new IllegalStateException("Unknown Spec And Policy Key " + specAndPolicyKey); } IssuanceMessageAndBoolean initReIssuanceProtocol = this.singleEngine.initReIssuanceProtocol(specAndPolicy.cloneIssuancePolicy()); return initReIssuanceProtocol.getIssuanceMessage(); } /** * Performs first step of issuance * * @param credspecAndPolicyKey key identifying SpecAndPolicy * @param attributeValueMap attribute values defined by issuer * @return * @throws Exception */ public IssuanceMessage initIssuance(String credspecAndPolicyKey, Map<String, Object> attributeValueMap) throws Exception { IssuanceHelper.log.info("IssuanceHelper - initIssuance : " + credspecAndPolicyKey + " : " + specAndPolicyMap.keySet()); if (this.singleEngine == null) { throw new IllegalStateException( "IssuanceHelper.initIssuance called without specifying CryptoEngine!"); } SpecAndPolicy specAndPolicy = this.specAndPolicyMap.get(credspecAndPolicyKey); if (specAndPolicy == null) { IssuanceHelper.log.info("IssuanceHelper - initIssuance : " + credspecAndPolicyKey + " : " + this.specAndPolicyMap); throw new IllegalStateException("Unknown Spec And Policy Key " + credspecAndPolicyKey); } return this.initIssuance(this.singleEngine, specAndPolicy, attributeValueMap); } /** * Performs first step of issuance * * @param specAndPolicy * @param attributeValueMap attribute values defined by issuer * @return * @throws Exception */ public IssuanceMessage initIssuance(SpecAndPolicy specAndPolicy, Map<String, Object> attributeValueMap) throws Exception { if (this.singleEngine == null) { throw new IllegalStateException( "IssuanceHelper.initIssuance called without specifying CryptoEngine!"); } return this.initIssuance(this.singleEngine, specAndPolicy, attributeValueMap); } private IssuanceMessage initIssuance(IssuerAbcEngine useEngine, SpecAndPolicy specAndPolicy, Map<String, Object> attributeValueMap) throws Exception { List<Attribute> issuerAtts = new ArrayList<Attribute>(); this.populateIssuerAttributes(specAndPolicy, issuerAtts, attributeValueMap); IssuancePolicy clonedIssuancePolicy = specAndPolicy.cloneIssuancePolicy(); URI policyIssuerParametersUID = specAndPolicy.issuerParamsUid_URI; modifyPA(clonedIssuancePolicy.getPresentationPolicy()); return this.initIssuanceProtocol(useEngine, issuerAtts, clonedIssuancePolicy, policyIssuerParametersUID).getIssuanceMessage(); } private IssuanceMessageAndBoolean initIssuanceProtocol(IssuerAbcEngine useEngine, List<Attribute> issuerAtts, IssuancePolicy clonedIssuancePolicy, URI policyIssuerParametersUID) throws Exception { IssuanceMessageAndBoolean response = null; try { IssuanceHelper.log.info(" - call ABCE - policy : " + clonedIssuancePolicy + " : " + policyIssuerParametersUID + " - attributes : " + issuerAtts); response = useEngine.initIssuanceProtocol(clonedIssuancePolicy, issuerAtts); } catch (Exception e) { System.err.println("- got Exception from ABCE Engine - try to create sample XML"); e.printStackTrace(); throw new Exception("Failed to initIsuanceProtocol", e); } if (response.isLastMessage()) { // cannot be last message throw new IllegalStateException( "Internal error in IssuerABCEngine - lastmessage returned from initIssuanceProtocol"); } return response; } private void populateIssuerAttributes(SpecAndPolicy specAndPolicy, List<Attribute> issuerAtts, Map<String, Object> attributeValueMap) { CredentialSpecification credSpec = specAndPolicy.getCredentialSpecification(); // TODO - to make proper check - also check 'unknown' from IssuancePolicy // eg findUnknownAttributtes(ip); // and check that all attribues in credspecs are matched.. if (credSpec.getAttributeDescriptions().getAttributeDescription().size() < attributeValueMap .size()) { throw new IllegalStateException("Wrong number of attributes ? - in credspec : " + credSpec.getAttributeDescriptions().getAttributeDescription().size() + " - in map " + attributeValueMap.size()); } Map<String, AttributeDescription> adMap = new HashMap<String, AttributeDescription>(); for (AttributeDescription ad : credSpec.getAttributeDescriptions().getAttributeDescription()) { adMap.put(ad.getType().toString(), ad); } Set<String> definedAttributes = attributeValueMap.keySet(); for (String key : definedAttributes) { AttributeDescription ad = adMap.get(key); if (ad == null) { throw new IllegalStateException("No Attribute in Credspec with type : " + key); } Object value = attributeValueMap.get(key); Attribute attribute = this.of.createAttribute(); // TODO : Howto create vaules ?? attribute.setAttributeUID(URI.create("" + this.random.nextLong())); Object xmlValue = new AttributeValueConverter().convertValue(ad.getDataType().toString(), value); // this.log.info("- xml Value : " + xmlValue); attribute.setAttributeValue(xmlValue); attribute.setAttributeDescription(this.of.createAttributeDescription()); attribute.getAttributeDescription().setDataType(URI.create(ad.getDataType().toString())); attribute.getAttributeDescription().setEncoding(URI.create(ad.getEncoding().toString())); attribute.getAttributeDescription().setType(URI.create(ad.getType().toString())); // TODO:SETTING Friendly's should be handled inside User Engine!!! attribute.getAttributeDescription().getFriendlyAttributeName() .addAll(ad.getFriendlyAttributeName()); // issuerAtts.add(attribute); } } // for service public IssuanceMessageAndBoolean initIssuanceProtocol(IssuancePolicy issuancePolicy, List<Attribute> attributes) throws Exception { IssuanceMessageAndBoolean issuanceMessageAndBoolean = null; URI issuerPolicyParametersUid = issuancePolicy.getCredentialTemplate().getIssuerParametersUID(); issuanceMessageAndBoolean = this.initIssuanceProtocol(singleEngine, attributes, issuancePolicy, issuerPolicyParametersUid); return issuanceMessageAndBoolean; } @Override public void addCredentialSpecifications(String[] credSpecResourceList) { super.addCredentialSpecifications(credSpecResourceList); } @Override public void addIssuerParameters(String[] issuerParametersResourceList) { super.addIssuerParameters(issuerParametersResourceList); } public IssuanceLogEntry getIssuanceLogEntry(URI issuanceEntryUid) throws Exception { return this.singleEngine.getIssuanceLogEntry(issuanceEntryUid); } }