/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.shiro.crypto; import org.apache.shiro.util.ByteSource; import java.security.SecureRandom; /** * Default implementation of the {@link RandomNumberGenerator RandomNumberGenerator} interface, backed by a * {@link SecureRandom SecureRandom} instance. * <p/> * This class is a little easier to use than using the JDK's {@code SecureRandom} class directly. It also * allows for JavaBeans-style of customization, convenient for Shiro's INI configuration or other IoC configuration * mechanism. * * @since 1.1 */ public class SecureRandomNumberGenerator implements RandomNumberGenerator { protected static final int DEFAULT_NEXT_BYTES_SIZE = 16; //16 bytes == 128 bits (a common number in crypto) private int defaultNextBytesSize; private SecureRandom secureRandom; /** * Creates a new instance with a default backing {@link SecureRandom SecureRandom} and a * {@link #getDefaultNextBytesSize() defaultNextBytesSize} of {@code 16}, which equals 128 bits, a size commonly * used in cryptographic algorithms. */ public SecureRandomNumberGenerator() { this.defaultNextBytesSize = DEFAULT_NEXT_BYTES_SIZE; this.secureRandom = new SecureRandom(); } /** * Seeds the backing {@link SecureRandom SecureRandom} instance with additional seed data. * * @param bytes the seed bytes * @see SecureRandom#setSeed(byte[]) */ public void setSeed(byte[] bytes) { this.secureRandom.setSeed(bytes); } /** * Returns the {@link SecureRandom SecureRandom} backing this instance. * * @return the {@link SecureRandom SecureRandom} backing this instance. */ public SecureRandom getSecureRandom() { return secureRandom; } /** * Sets the {@link SecureRandom SecureRandom} to back this instance. * * @param random the {@link SecureRandom SecureRandom} to back this instance. * @throws NullPointerException if the method argument is null */ public void setSecureRandom(SecureRandom random) throws NullPointerException { if (random == null) { throw new NullPointerException("SecureRandom argument cannot be null."); } this.secureRandom = random; } /** * Returns the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. Defaults to * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms. * * @return the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. */ public int getDefaultNextBytesSize() { return defaultNextBytesSize; } /** * Sets the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. Defaults to * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms. * * @param defaultNextBytesSize the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. * @throws IllegalArgumentException if the argument is 0 or negative */ public void setDefaultNextBytesSize(int defaultNextBytesSize) throws IllegalArgumentException { if ( defaultNextBytesSize <= 0) { throw new IllegalArgumentException("size value must be a positive integer (1 or larger)"); } this.defaultNextBytesSize = defaultNextBytesSize; } public ByteSource nextBytes() { return nextBytes(getDefaultNextBytesSize()); } public ByteSource nextBytes(int numBytes) { if (numBytes <= 0) { throw new IllegalArgumentException("numBytes argument must be a positive integer (1 or larger)"); } byte[] bytes = new byte[numBytes]; this.secureRandom.nextBytes(bytes); return ByteSource.Util.bytes(bytes); } }