//* Licensed Materials - Property of * //* IBM * //* Miracle 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. * //* 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.cryptoEngine.user; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URI; import java.util.Map; import com.ibm.zurich.idmix.abc4trust.facades.PseudonymCryptoFacade; import eu.abc4trust.abce.internal.user.credentialManager.CredentialManagerImpl; import eu.abc4trust.smartcard.BasicSmartcard; import eu.abc4trust.smartcard.CardStorage; import eu.abc4trust.smartcard.SecretBasedSmartcard; import eu.abc4trust.smartcard.Smartcard; import eu.abc4trust.xml.CryptoParams; import eu.abc4trust.xml.FriendlyDescription; import eu.abc4trust.xml.Metadata; import eu.abc4trust.xml.ObjectFactory; import eu.abc4trust.xml.Pseudonym; import eu.abc4trust.xml.PseudonymMetadata; import eu.abc4trust.xml.PseudonymWithMetadata; public abstract class AbstractPseudonymSerializer implements PseudonymSerializer{ public static final String ENCODING = "UTF-8"; public abstract CardStorage getCardStorage(); public byte[] serializeExclusivePseudonym(PseudonymWithMetadata pwm){ Pseudonym pseudonym = pwm.getPseudonym(); if(!pseudonym.isExclusive()){ throw new RuntimeException("Pseudonym not exclusive"); } try{ ByteArrayOutputStream out = new ByteArrayOutputStream(); String scope = pseudonym.getScope(); byte[] scope_bytes = scope.getBytes(ENCODING); if (scope_bytes.length > 255) { throw new RuntimeException("Scope is too long. Cannot serialize pseudonym."); } out.write(magicHeaderForScopeExclusive()); out.write(scope_bytes.length); out.write(scope_bytes); byte[] secretReference = pseudonym.getSecretReference().toString().getBytes(ENCODING); if (secretReference.length > 255) { throw new RuntimeException("Secret Reference is too long. Cannot serialize pseudonym."); } out.write(secretReference.length); out.write(secretReference); byte[] pseudonymUID = pseudonym.getPseudonymUID().toString().getBytes(ENCODING); if (pseudonymUID.length > 255) { throw new RuntimeException("pseudonym UID is too long. Cannot serialize pseudonym."); } out.write(pseudonymUID.length); out.write(pseudonymUID); return out.toByteArray(); }catch(IOException e){ throw new RuntimeException(e); } } public PseudonymWithMetadata unserializeExclusivePseudonym(byte[] data, URI pseudonymUID){ URI scopeFromStream; URI secretReferenceFromStream; URI pseudonymUIDFromStream; try { ByteArrayInputStream in = new ByteArrayInputStream(data); int header = in.read(); if(header != magicHeaderForScopeExclusive()) { return null; } scopeFromStream = URI.create(getNextString(in)); secretReferenceFromStream = URI.create(getNextString(in)); pseudonymUIDFromStream = URI.create(getNextString(in)); } catch (IOException e) { return null; } ObjectFactory of = new ObjectFactory(); Pseudonym pseudonym = of.createPseudonym(); Smartcard sc = (Smartcard)this.getCardStorage().getSmartcard(this.getSmartcardUri()); int pin = this.getCardStorage().getPin(this.getSmartcardUri()); URI secretReference = sc.getDeviceURI(pin); if(!secretReference.equals(secretReferenceFromStream)){ throw new RuntimeException("Secret refenreces don't match: " + pseudonym.getSecretReference()+" vs. "+ secretReferenceFromStream); } URI prefixedPseudonymUID = URI.create(CredentialManagerImpl.PSEUDONYM_PREFIX+pseudonymUIDFromStream.toASCIIString().replaceAll(":", "_")); if(!pseudonymUID.equals(prefixedPseudonymUID)){ // TODO: how shuld test be done... if(pseudonymUID.equals(pseudonymUIDFromStream)) { //throw new RuntimeException("PseudonymUIDs is not prefixed with " + CredentialManagerImpl.PSEUDONYM_PREFIX); } else { throw new RuntimeException("PseudonymUIDs don't match prefixed card UID : "+pseudonymUID +" vs. "+prefixedPseudonymUID); } } pseudonym.setSecretReference(secretReference); pseudonym.setExclusive(true); pseudonym.setPseudonymUID(pseudonymUIDFromStream); BigInteger pseudonymValue = sc.computeScopeExclusivePseudonym(pin, scopeFromStream); pseudonym.setPseudonymValue(pseudonymValue.toByteArray()); pseudonym.setScope(scopeFromStream.toString()); Metadata md = of.createMetadata(); PseudonymMetadata pmd = of.createPseudonymMetadata(); pmd.getFriendlyPseudonymDescription().add(generateFriendlyDescription(pseudonym.getScope())); pmd.setMetadata(md); PseudonymWithMetadata pwm = of.createPseudonymWithMetadata(); pwm.setPseudonym(pseudonym); pwm.setPseudonymMetadata(pmd); CryptoParams cryptoEvidence = of.createCryptoParams(); URI groupParameterId = URI.create("http://www.zurich.ibm.com/security/idmx/v2/gp.xml"); URI secretUID = sc.getDeviceURI(pin); PseudonymCryptoFacade pcf = new PseudonymCryptoFacade(); pcf.setScopeExclusivePseudonym(scopeFromStream, secretUID, pseudonym.getPseudonymValue()); pwm.setCryptoParams(pcf.getCryptoParams()); return pwm; } private String getNextString(ByteArrayInputStream in) throws IOException{ int size = in.read(); byte[] bytes = new byte[size]; int read = in.read(bytes); if(size != read){ throw new IOException("Amount of bytes read is not the expected amount"); } return new String(bytes, ENCODING); } private URI getSmartcardUri(){ Map<URI, BasicSmartcard> scs = this.getCardStorage().getSmartcards(); for(URI uri : scs.keySet()){ if(!(scs.get(uri) instanceof SecretBasedSmartcard)){ return uri; } } return null; } /** * Generate a friendly description heuristically from the given pseudonym scope. * The friendly description will have language "en" (English). * The scope will be divided into tokens according to the colon character ":". * We take the last of these tokens, do a URL-decoding (in the UTF-8 character set), * and put the result as the value of the friendly description. On error, the whole * scope is put as value of the friendly description. * @param scope * @return */ public static FriendlyDescription generateFriendlyDescription(String scope) { FriendlyDescription fd = new FriendlyDescription(); fd.setLang("en"); String[] tokens = scope.split(":"); String lastToken = tokens[tokens.length-1]; try { String decoded = java.net.URLDecoder.decode(lastToken, "UTF-8"); fd.setValue(decoded); } catch (Exception e) { fd.setValue(scope); } return fd; } public int magicHeaderForScopeExclusive() { return 70; } }