1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.apache.shiro.crypto; 20 21 import org.apache.shiro.util.ByteSource; 22 23 import java.security.SecureRandom; 24 25 /** 26 * Default implementation of the {@link RandomNumberGenerator RandomNumberGenerator} interface, backed by a 27 * {@link SecureRandom SecureRandom} instance. 28 * <p/> 29 * This class is a little easier to use than using the JDK's {@code SecureRandom} class directly. It also 30 * allows for JavaBeans-style of customization, convenient for Shiro's INI configuration or other IoC configuration 31 * mechanism. 32 * 33 * @since 1.1 34 */ 35 public class SecureRandomNumberGenerator implements RandomNumberGenerator { 36 37 protected static final int DEFAULT_NEXT_BYTES_SIZE = 16; //16 bytes == 128 bits (a common number in crypto) 38 39 private int defaultNextBytesSize; 40 private SecureRandom secureRandom; 41 42 /** 43 * Creates a new instance with a default backing {@link SecureRandom SecureRandom} and a 44 * {@link #getDefaultNextBytesSize() defaultNextBytesSize} of {@code 16}, which equals 128 bits, a size commonly 45 * used in cryptographic algorithms. 46 */ 47 public SecureRandomNumberGenerator() { 48 this.defaultNextBytesSize = DEFAULT_NEXT_BYTES_SIZE; 49 this.secureRandom = new SecureRandom(); 50 } 51 52 /** 53 * Seeds the backing {@link SecureRandom SecureRandom} instance with additional seed data. 54 * 55 * @param bytes the seed bytes 56 * @see SecureRandom#setSeed(byte[]) 57 */ 58 public void setSeed(byte[] bytes) { 59 this.secureRandom.setSeed(bytes); 60 } 61 62 /** 63 * Returns the {@link SecureRandom SecureRandom} backing this instance. 64 * 65 * @return the {@link SecureRandom SecureRandom} backing this instance. 66 */ 67 public SecureRandom getSecureRandom() { 68 return secureRandom; 69 } 70 71 /** 72 * Sets the {@link SecureRandom SecureRandom} to back this instance. 73 * 74 * @param random the {@link SecureRandom SecureRandom} to back this instance. 75 * @throws NullPointerException if the method argument is null 76 */ 77 public void setSecureRandom(SecureRandom random) throws NullPointerException { 78 if (random == null) { 79 throw new NullPointerException("SecureRandom argument cannot be null."); 80 } 81 this.secureRandom = random; 82 } 83 84 /** 85 * Returns the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. Defaults to 86 * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms. 87 * 88 * @return the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. 89 */ 90 public int getDefaultNextBytesSize() { 91 return defaultNextBytesSize; 92 } 93 94 /** 95 * Sets the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. Defaults to 96 * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms. 97 * 98 * @param defaultNextBytesSize the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. 99 * @throws IllegalArgumentException if the argument is 0 or negative 100 */ 101 public void setDefaultNextBytesSize(int defaultNextBytesSize) throws IllegalArgumentException { 102 if ( defaultNextBytesSize <= 0) { 103 throw new IllegalArgumentException("size value must be a positive integer (1 or larger)"); 104 } 105 this.defaultNextBytesSize = defaultNextBytesSize; 106 } 107 108 public ByteSource nextBytes() { 109 return nextBytes(getDefaultNextBytesSize()); 110 } 111 112 public ByteSource nextBytes(int numBytes) { 113 if (numBytes <= 0) { 114 throw new IllegalArgumentException("numBytes argument must be a positive integer (1 or larger)"); 115 } 116 byte[] bytes = new byte[numBytes]; 117 this.secureRandom.nextBytes(bytes); 118 return ByteSource.Util.bytes(bytes); 119 } 120 }