/* * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in * compliance with the Licence. You may obtain a copy of the Licence at: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * * Unless required by applicable law or agreed to in writing, software distributed under the Licence * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the Licence for the specific language governing permissions and limitations under * the Licence. * * This product combines work with different licenses. See the "NOTICE" text file for details on the * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative * works that you distribute must include a readable copy of the "NOTICE" text file. */ package at.gv.egiz.eaaf.core.impl.utils; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.eaaf.core.impl.idp.process.support.SecureRandomHolder; /** * Random number generator used to generate ID's. * * @author Paul Ivancsics * @version $Id$ */ public class Random { private static final Logger log = LoggerFactory.getLogger(Random.class); private static final char[] allowedPreFix = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; /** random number generator used. */ private static SecureRandom random; // private static SeedGenerator seedgenerator; static { try { random = SecureRandom.getInstance("SHA256PRNG-FIPS186"); } catch (final NoSuchAlgorithmException e) { log.warn( "Can NOT initialize SecureRandom with: 'SHA256PRNG-FIPS186'. Use 'StrongSecureRandom' as backup"); random = SecureRandomHolder.getInstance(); } // random = iaik.security.random.SHA256FIPS186Random.getDefault(); } /** * Generate a unique process reference-value [160bit], which always starts with * a letter
* This unique ID consists of single letter, a 64bit date String[yyyyddMM], and * a 88bit random value. * * @return 160bit ID, which is hex encoded */ public static String nextProcessReferenceValue() { // pre-process all three parts of a unique reference value final DateFormat dateFormater = new SimpleDateFormat("yyyyddMM"); final String now = dateFormater.format(new Date()); // 8 bytes = 64bit final byte[] randValue = nextByteRandom(11); final char preFix = allowedPreFix[Math.abs(random.nextInt() % allowedPreFix.length)]; // generate ID String returnValue; try { returnValue = preFix + new String(Hex.encodeHex(ArrayUtils.addAll(now.getBytes("UTF-8"), randValue))); // 20 bytes = 160 bits if (returnValue.length() > 40) { return returnValue.substring(0, 40); } else { return returnValue; } } catch (final UnsupportedEncodingException e) { throw new RuntimeException(e); } } /** * Creates a new random number [256bit], and encode it as hex value. * * @return random hex encoded value [256bit] */ public static String nextHexRandom32() { return new String(Hex.encodeHex(nextByteRandom(32))); // 32 bytes = 256 bits } /** * Creates a new random number [128bit], and encode it as hex value. * * @return random hex encoded value [128bit] */ public static String nextHexRandom16() { return new String(Hex.encodeHex(nextByteRandom(16))); // 16 bytes = 128 bits } /** * Creates a new random number [64bit], to be used as an ID. * * @return random long as a String [64bit] */ public static String nextLongRandom() { return "".concat(String.valueOf(Math.abs(generateLongRandom(32)))); // 32 bytes = 256 bits } /** * Creates a new random number, to be used as an ID. * * @return random long as a String [64bit] */ @Deprecated public static String nextRandom() { final long l = ByteBuffer.wrap(nextByteRandom(32)).getLong(); // 32 bytes = 256 bits return "" + Math.abs(l); } /** * Creates a new random byte[]. * * @param size Size of random number in byte * @return */ public static byte[] nextBytes(final int size) { return nextByteRandom(size); } /** * initialize random-number generator. */ public static void seedRandom() { // TODO: implement reflection on IAIK Seed generator // seedgenerator = iaik.security.random.AutoSeedGenerator.getDefault(); // if (seedgenerator.seedAvailable()) // random.setSeed(seedgenerator.getSeed()); random.setSeed(System.nanoTime()); } private static long generateLongRandom(final int size) { return ByteBuffer.wrap(nextByteRandom(size)).getLong(); } /** * Generate a new random number. * * @param size Size of random number in byte * @return */ private static synchronized byte[] nextByteRandom(final int size) { final byte[] b = new byte[size]; random.nextBytes(b); return b; } }