View Javadoc
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 }