/* * Copyright (C) 2013-2017 NTT DATA Corporation * * 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 org.terasoluna.gfw.web.token; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.concurrent.atomic.AtomicLong; /** * Class to generate the random string that can be used as value part of {@code TransactionToken} */ public class TokenStringGenerator { public static final String DEFAULT_ALGORITHM = "MD5"; private final AtomicLong counter = new AtomicLong(); private final String internalSeed; private final String algorithm; /** * Constructor. * <p> * Uses MD5 as default Algorithm. * </p> */ public TokenStringGenerator() { this(DEFAULT_ALGORITHM); } /** * Constructor. Algorithm to be used for generating the token value can be passed as an argument <br> * @param algorithm Algorithm to be used for generating the token value (must not be null) * @throws IllegalArgumentException algorithm is null or invalid */ public TokenStringGenerator(final String algorithm) { if (algorithm == null) { throw new IllegalArgumentException("algorithm must not be null"); } try { MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException("The given algorithm is invalid. algorithm=" + algorithm, e); } this.algorithm = algorithm; this.internalSeed = Long.toHexString(new SecureRandom().nextLong()); } /** * Generates random token string<br> * <p> * Uses {@code MD5} as default algorithm if not externally specified. A seed is to be passed as parameter which will be used * as a base to generate the random token string value. * </p> * @param seed any value to use as base to generate token string value (must not be null) * @return token string * @throws IllegalArgumentException seed is null */ public String generate(final String seed) { if (seed == null) { throw new IllegalArgumentException("seed must not be null"); } long time = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(1000); sb.append(internalSeed).append(seed).append(time).append( counter.getAndIncrement()); MessageDigest md = createMessageDigest(); md.update(sb.toString().getBytes()); byte[] bytes = md.digest(); return toHexString(bytes); } MessageDigest createMessageDigest() { try { return MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException(e); } } protected static String toHexString(final byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { String s = Integer.toHexString(b & 0xff); if (s.length() == 1) { sb.append("0"); } sb.append(s); } return sb.toString(); } }