Path: blob/master/test/jdk/java/security/SecureRandom/MultiThreadTest.java
41149 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.math.BigInteger;24import java.security.NoSuchAlgorithmException;25import java.security.SecureRandom;26import java.security.Security;27import java.util.concurrent.Callable;28import java.util.concurrent.CompletionService;29import java.util.concurrent.CountDownLatch;30import java.util.concurrent.ExecutionException;31import java.util.concurrent.ExecutorCompletionService;32import java.util.concurrent.ExecutorService;33import java.util.concurrent.Executors;34import java.util.concurrent.ThreadFactory;35import static java.lang.Math.*;3637/*38* @test39* @bug 814103940* @library /lib/testlibrary41* @summary Test behavior of a shared SecureRandom object when it is operated42* by multiple threads concurrently.43* @run main/othervm -Djava.security.egd=file:/dev/urandom MultiThreadTest44*/45public class MultiThreadTest {4647private static final byte[] GEN_RND_BYTES = {1};48private static final String DRBG_CONFIG = "securerandom.drbg.config";49private static final String DRBG_CONFIG_VALUE50= Security.getProperty(DRBG_CONFIG);5152private enum SEED {5354NONE, RESEED, SETSEED55}5657public static void main(String[] args) {5859boolean success = true;60for (int byteLen : GEN_RND_BYTES) {61for (SEED reSeed : SEED.values()) {62for (String mech : new String[]{63"SHA1PRNG", "Hash_DRBG", "HMAC_DRBG", "CTR_DRBG"}) {64try {65forEachMech(mech, byteLen, reSeed);66} catch (Exception e) {67success = false;68e.printStackTrace(System.out);69} finally {70Security.setProperty(DRBG_CONFIG, DRBG_CONFIG_VALUE);71}72}73}74}7576if (!success) {77throw new RuntimeException("At least one test failed.");78}79}8081/**82* Generate a number of threads to fetch random numbers of certain bits83* generated through a shared SecureRandom instance.84* @param mech Mechanism name85* @param byteLen Number of bytes of random number to produce86* @param reSeed Call reseed() before generating random numbers87* @throws NoSuchAlgorithmException88* @throws InterruptedException89* @throws ExecutionException90*/91private static void forEachMech(String mech, int byteLen, SEED reSeed)92throws NoSuchAlgorithmException, InterruptedException,93ExecutionException {9495if ("SHA1PRNG".equals(mech) && SEED.RESEED.equals(reSeed)) {96System.out.printf(97"%nreseed() api is not supported for '%s'", mech);98return;99}100System.out.printf("%nTest SecureRandom mechanism: '%s' with support of"101+ " reseed: '%s'", mech, reSeed);102int threadCount = (int) pow(2, 8 * byteLen);103System.out.printf("%nCreating %s number of threads to generate secure "104+ "random numbers concurrently.", threadCount);105106ExecutorService executor107= Executors.newCachedThreadPool(new ThreadFactory() {108@Override109public Thread newThread(Runnable r) {110Thread t = Executors.defaultThreadFactory()111.newThread(r);112t.setDaemon(true);113return t;114}115});116CompletionService<Integer> completionService117= new ExecutorCompletionService<Integer>(executor);118119CountDownLatch latch = new CountDownLatch(1);120SecureRandom rnd = null;121if (!mech.contains("_DRBG")) {122rnd = SecureRandom.getInstance(mech);123} else {124Security.setProperty(DRBG_CONFIG, mech);125rnd = SecureRandom.getInstance("DRBG");126}127try {128for (int i = 0; i < threadCount; i++) {129completionService.submit(new Task(rnd, latch, byteLen, reSeed));130}131latch.countDown();132133for (int i = 0; i < threadCount; i++) {134completionService.take();135}136} finally {137executor.shutdown();138}139System.out.printf("%nCompleted Test for algorithm '%s' with thread "140+ "counts to '%s' using reseeding '%s'",141mech, threadCount, reSeed);142143}144145/**146* Define a Task to be executed by multiple thread to produce random numbers147* from a shared SecureRandom instance.148*/149private static class Task implements Callable<Integer> {150151private final SecureRandom random;152private final CountDownLatch latch;153private final SEED reSeed;154private final int byteSize;155156public Task(SecureRandom random, CountDownLatch latch, int byteSize,157SEED reSeed) {158this.random = random;159this.latch = latch;160this.byteSize = byteSize;161this.reSeed = reSeed;162}163164@Override165public Integer call() throws Exception {166latch.await();167switch (this.reSeed) {168case RESEED:169this.random.reseed();170break;171case SETSEED:172this.random.setSeed(1l);173break;174}175byte[] bytes = new byte[byteSize];176random.nextBytes(bytes);177return new BigInteger(bytes).intValue();178}179}180181}182183184