//* Licensed Materials - Property of * //* IBM * //* * //* eu.abc4trust.pabce.1.34 * //* * //* (C) Copyright IBM Corp. 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.attributeEncoding; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigInteger; import java.net.URI; import java.util.Map; import eu.abc4trust.util.attributeTypes.EnumAllowedValues; import eu.abc4trust.util.attributeTypes.EnumAllowedValuesWithIndexer; import eu.abc4trust.util.attributeTypes.EnumIndexer; import eu.abc4trust.util.attributeTypes.MyAttributeValue; public class MyAttributeEncodingFactory { private static final Class<?> classes[] = new Class[] {MyEncodingStringSha256.class, MyEncodingStringUtf8.class, MyEncodingUriSha256.class, MyEncodingUriUtf8.class, MyEncodingDateTimeSigned.class, MyEncodingDateTimeUnsigned.class, MyEncodingDateUnsigned.class, MyEncodingDateSigned.class, MyEncodingDateSince1870.class, MyEncodingDateSince2010.class, MyEncodingTime.class, MyEncodingBoolean.class, MyEncodingIntegerUnsigned.class, MyEncodingIntegerSigned.class, MyEncodingStringPrime.class}; // 2^128 public static final BigInteger SIGNED_OFFSET = BigInteger.valueOf(2).pow(128); // 2^256 public static final BigInteger MAX_VALUE = BigInteger.valueOf(2).pow(256); public static MyAttributeValue parseValueFromEncoding(URI encoding, Object attributeValue, /*Nullable*/ EnumAllowedValues eav) { MyAttributeValue ret = parseValueFromEncodingNoCheck(encoding, attributeValue, eav); if(! encoding.equals(ret.getEncodingOrNull())) { throw new RuntimeException("Problem with encoding: " + encoding + "/" + ret.getEncodingOrNull()); } return ret; } private static MyAttributeValue parseValueFromEncodingNoCheck(URI encoding, Object attributeValue, /*Nullable*/ EnumAllowedValues eav) { try { for(Class<?> c:classes) { if(c.getField("ENCODING").get(null).equals(encoding)) { Constructor<?> cons = c.getConstructor(Object.class, EnumAllowedValues.class); return (MyAttributeValue) cons.newInstance(attributeValue, eav); } } } catch(InstantiationException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) { // Unwrap the exception if it is an unchecked exception throw (RuntimeException) e.getCause(); } throw new RuntimeException(e.getCause()); } throw new RuntimeException("Cannot parse attribute encoding: '" + encoding + "'"); } public static Map<String, BigInteger> getEncodingForEachAllowedValue(URI encoding, EnumAllowedValues eav) { try { for(Class<?> c:classes) { if(c.getField("ENCODING").get(null).equals(encoding)) { Method m = c.getMethod("getEnumIndexer"); EnumIndexer indexer = (EnumIndexer)m.invoke(null); EnumAllowedValuesWithIndexer eavwi = new EnumAllowedValuesWithIndexer(indexer, eav.getAllowedValues()); return eavwi.getEncodingForEachAllowedValue(); } } } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) { // Unwrap the exception if it is an unchecked exception throw (RuntimeException) e.getCause(); } throw new RuntimeException(e.getCause()); } throw new RuntimeException("Cannot parse attribute encoding: '" + encoding + "'"); } public static MyAttributeValue recoverValueFromBigInteger(URI encoding, BigInteger attributeValue, /*Nullable*/ EnumAllowedValues eav) { MyAttributeValue ret = recoverValueFromBigIntegerNoCheck(encoding, attributeValue, eav); if(! encoding.equals(ret.getEncodingOrNull())) { throw new RuntimeException("Problem with encoding: " + encoding + "/" + ret.getEncodingOrNull()); } else if(! attributeValue.equals(ret.getIntegerValueOrNull())) { throw new RuntimeException("Problem with recovering attribute value from integer encoding: E=" + encoding + "/V=" + attributeValue + " : " + ret.toString()); } return ret; } private static MyAttributeValue recoverValueFromBigIntegerNoCheck(URI encoding, BigInteger attributeValue, /*Nullable*/ EnumAllowedValues eav) { try { for(Class<?> c:classes) { if(c.getField("ENCODING").get(null).equals(encoding)) { Method m = c.getMethod("recoverValueFromIntegerValue", BigInteger.class, EnumAllowedValues.class); Object decoded = m.invoke(null, attributeValue, eav); Constructor<?> cons = c.getConstructor(Object.class, EnumAllowedValues.class); return (MyAttributeValue) cons.newInstance(decoded, eav); } } } catch(InstantiationException e) { throw new RuntimeException(e); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } catch (SecurityException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) { // Unwrap the exception if it is an unchecked exception throw (RuntimeException) e.getCause(); } throw new RuntimeException(e.getCause()); } throw new RuntimeException("Cannot recover value for attribute encoding: '" + encoding + "'"); } private static URI XS_STRING = URI.create("xs:string"); private static URI XS_URI = URI.create("xs:anyURI"); private static URI XS_DATETIME = URI.create("xs:dateTime"); private static URI XS_DATE = URI.create("xs:date"); private static URI XS_TIME = URI.create("xs:time"); private static URI XS_INTEGER = URI.create("xs:integer"); private static URI XS_BOOLEAN = URI.create("xs:boolean"); public static URI getDatatypeFromEncoding(URI encoding) { if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:string:sha-256"))) { return XS_STRING; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:string:utf-8"))) { return XS_STRING; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:string:prime"))) { return XS_STRING; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:anyUri:sha-256"))) { return XS_URI; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:anyUri:utf-8"))) { return XS_URI; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:dateTime:unix:signed"))) { return XS_DATETIME; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:dateTime:unix:unsigned"))) { return XS_DATETIME; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:date:unix:unsigned"))) { return XS_DATE; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:date:unix:signed"))) { return XS_DATE; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:date:since1870:unsigned"))) { return XS_DATE; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:date:since2010:unsigned"))) { return XS_DATE; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:time:sinceMidnight:unsigned"))) { return XS_TIME; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:boolean:unsigned"))) { return XS_BOOLEAN; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:integer:unsigned"))) { return XS_INTEGER; } else if (encoding.equals(URI.create("urn:abc4trust:1.0:encoding:integer:signed"))) { return XS_INTEGER; } else { return null; } } public static BigInteger byteArrayToInteger(byte[] arr) { StringBuilder sb = new StringBuilder(); for(int i=0;i<arr.length;++i) { sb.append(String.format("%02X", arr[i])); } return new BigInteger(sb.toString(), 16); } public static BigInteger byteArrayToIntegerWithLength(byte[] arr) { StringBuilder sb = new StringBuilder(); if(arr.length > 255) { throw new RuntimeException("Array too long! Size must fit in one byte."); } for(int i=0;i<arr.length;++i) { sb.append(String.format("%02X", arr[i])); } sb.append(String.format("%02X", arr.length)); return new BigInteger(sb.toString(), 16); } public static byte[] decodeByteArrayWithLength(BigInteger integerValue) { int len = integerValue.mod(BigInteger.valueOf(256)).intValue(); integerValue = integerValue.divide(BigInteger.valueOf(256)); byte[] arr = new byte[len]; for (int i=len-1;i>=0;--i) { arr[i] = integerValue.mod(BigInteger.valueOf(256)).byteValue(); integerValue = integerValue.divide(BigInteger.valueOf(256)); } return arr; } }