view test/sun/security/provider/SecureRandom/StrongSecureRandom.java @ 7341:0f93bd5cc8d7

6425477: Better support for generation of high entropy random numbers Reviewed-by: xuelei, weijun, mullan
author wetmore
date Thu, 11 Apr 2013 21:03:24 -0700
parents
children
line wrap: on
line source

/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/**
 * @test
 * @bug 6425477
 * @summary Better support for generation of high entropy random numbers
 * @run main/othervm StrongSecureRandom
 */
import java.security.*;
import java.util.*;

/**
 * This test assumes that the standard Sun providers are installed.
 */
public class StrongSecureRandom {

    private static String os = System.getProperty("os.name", "unknown");

    private static void testDefaultEgd() throws Exception {
        // No SecurityManager installed.
        String s = Security.getProperty("securerandom.source");

        System.out.println("Testing:  default EGD: " + s);
        if (!s.equals("file:/dev/random")) {
            throw new Exception("Default is not 'file:/dev/random'");
        }
    }

    private static void testSHA1PRNGImpl() throws Exception {
        SecureRandom sr;
        byte[] ba;

        String urandom = "file:/dev/urandom";

        System.out.println("Testing new SeedGenerator and EGD");

        Security.setProperty("securerandom.source", urandom);
        if (!Security.getProperty("securerandom.source").equals(urandom)) {
            throw new Exception("Couldn't set securerandom.source");
        }

        /*
         * Take out a large number of bytes in hopes of blocking.
         * Don't expect this to happen, unless something is broken on Linux
         */
        sr = SecureRandom.getInstance("SHA1PRNG");
        if (!sr.getAlgorithm().equals("SHA1PRNG")) {
            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
        }

        ba = sr.generateSeed(4096);
        sr.nextBytes(ba);
        sr.setSeed(ba);
    }

    private static void testNativePRNGImpls() throws Exception {
        SecureRandom sr;
        byte[] ba;

        System.out.println("Testing new NativePRNGImpls");

        if (os.startsWith("Windows")) {
            System.out.println("Skip windows testing.");
            return;
        }

        System.out.println("    Testing regular");
        sr = SecureRandom.getInstance("NativePRNG");
        if (!sr.getAlgorithm().equals("NativePRNG")) {
            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
        }
        ba = sr.generateSeed(1);
        sr.nextBytes(ba);
        sr.setSeed(ba);

        System.out.println("    Testing NonBlocking");
        sr = SecureRandom.getInstance("NativePRNGNonBlocking");
        if (!sr.getAlgorithm().equals("NativePRNGNonBlocking")) {
            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
        }
        ba = sr.generateSeed(1);
        sr.nextBytes(ba);
        sr.setSeed(ba);

        if (os.equals("Linux")) {
            System.out.println("Skip Linux blocking test.");
            return;
        }

        System.out.println("    Testing Blocking");
        sr = SecureRandom.getInstance("NativePRNGBlocking");
        if (!sr.getAlgorithm().equals("NativePRNGBlocking")) {
            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
        }
        ba = sr.generateSeed(1);
        sr.nextBytes(ba);
        sr.setSeed(ba);
    }

    private static void testStrongInstance(boolean expected) throws Exception {

        boolean result = (SecureRandom.getStrongSecureRandom() != null);

        if (expected != result) {
            throw new Exception("Received: " + result);
        }
    }

    /*
     * This test assumes that the standard providers are installed.
     */
    private static void testProperty(String property, boolean expected)
            throws Exception {

        System.out.println("Testing: '" + property + "' " + expected);

        Security.setProperty("securerandom.strongAlgorithms", property);
        testStrongInstance(expected);
    }

    private static void testProperties() throws Exception {
        // Sets securerandom.strongAlgorithms, and then tests various combos.
        testProperty("", false);

        testProperty("SHA1PRNG", true);
        testProperty(" SHA1PRNG", true);
        testProperty("SHA1PRNG ", true);
        testProperty(" SHA1PRNG ", true);

        // Impls are case-insenstive, providers are sensitive.
        testProperty("SHA1PRNG:SUN", true);
        testProperty("Sha1PRNG:SUN", true);
        testProperty("SHA1PRNG:Sun", false);

        testProperty(" SHA1PRNG:SUN", true);
        testProperty("SHA1PRNG:SUN ", true);
        testProperty(" SHA1PRNG:SUN ", true);

        testProperty(" SHA1PRNG:SUn", false);
        testProperty("SHA1PRNG:SUn ", false);
        testProperty(" SHA1PRNG:SUn ", false);

        testProperty(",,,SHA1PRNG", true);
        testProperty(",,, SHA1PRNG", true);
        testProperty(" , , ,SHA1PRNG ", true);

        testProperty(",,,, SHA1PRNG ,,,", true);
        testProperty(",,,, SHA1PRNG:SUN ,,,", true);
        testProperty(",,,, SHA1PRNG:SUn ,,,", false);

        testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUN", true);
        testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUN", true);
        testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUN", true);

        testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUn", false);
        testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUn", false);
        testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUn", false);

        testProperty(
                " @#%,%$#:!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUN",
                true);
        testProperty(" @#%,%$#!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUn",
                false);
    }

    /*
     * Linux tends to block, so ignore anything that reads /dev/random.
     */
    private static void handleLinuxRead(SecureRandom sr) throws Exception {
        if (os.equals("Linux")) {
            if (!sr.getAlgorithm().equalsIgnoreCase("NativePRNGBlocking")) {
                sr.nextBytes(new byte[34]);
            }
        } else {
            sr.nextBytes(new byte[34]);
            sr.generateSeed(34);
            sr.setSeed(new byte[34]);
        }
    }

    /*
     * This is duplicating stuff above, but just iterate over all impls
     * just in case we missed something.
     */
    private static void testAllImpls() throws Exception {
        System.out.print("Testing:  AllImpls:  ");

        Iterator<String> i = Security.getAlgorithms("SecureRandom").iterator();

        while (i.hasNext()) {
            String s = i.next();
            System.out.print("/" + s);
            SecureRandom sr = SecureRandom.getInstance(s);

            handleLinuxRead(sr);
            handleLinuxRead(sr);
        }
        System.out.println("/");
    }

    public static void main(String args[]) throws Exception {
        testDefaultEgd();
        testSHA1PRNGImpl();
        testNativePRNGImpls();
        testAllImpls();

        // test default.
        testStrongInstance(true);
        testProperties();
    }
}