001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.crypto;
020    
021    import org.apache.shiro.util.ByteSource;
022    
023    import java.security.SecureRandom;
024    
025    /**
026     * Default implementation of the {@link RandomNumberGenerator RandomNumberGenerator} interface, backed by a
027     * {@link SecureRandom SecureRandom} instance.
028     * <p/>
029     * This class is a little easier to use than using the JDK's {@code SecureRandom} class directly.  It also
030     * allows for JavaBeans-style of customization, convenient for Shiro's INI configuration or other IoC configuration
031     * mechanism.
032     *
033     * @since 1.1
034     */
035    public class SecureRandomNumberGenerator implements RandomNumberGenerator {
036    
037        protected static final int DEFAULT_NEXT_BYTES_SIZE = 16; //16 bytes == 128 bits (a common number in crypto)
038    
039        private int defaultNextBytesSize;
040        private SecureRandom secureRandom;
041    
042        /**
043         * Creates a new instance with a default backing {@link SecureRandom SecureRandom} and a
044         * {@link #getDefaultNextBytesSize() defaultNextBytesSize} of {@code 16}, which equals 128 bits, a size commonly
045         * used in cryptographic algorithms.
046         */
047        public SecureRandomNumberGenerator() {
048            this.defaultNextBytesSize = DEFAULT_NEXT_BYTES_SIZE;
049            this.secureRandom = new SecureRandom();
050        }
051    
052        /**
053         * Seeds the backing {@link SecureRandom SecureRandom} instance with additional seed data.
054         *
055         * @param bytes the seed bytes
056         * @see SecureRandom#setSeed(byte[])
057         */
058        public void setSeed(byte[] bytes) {
059            this.secureRandom.setSeed(bytes);
060        }
061    
062        /**
063         * Returns the {@link SecureRandom SecureRandom} backing this instance.
064         *
065         * @return the {@link SecureRandom SecureRandom} backing this instance.
066         */
067        public SecureRandom getSecureRandom() {
068            return secureRandom;
069        }
070    
071        /**
072         * Sets the {@link SecureRandom SecureRandom} to back this instance.
073         *
074         * @param random the {@link SecureRandom SecureRandom} to back this instance.
075         * @throws NullPointerException if the method argument is null
076         */
077        public void setSecureRandom(SecureRandom random) throws NullPointerException {
078            if (random == null) {
079                throw new NullPointerException("SecureRandom argument cannot be null.");
080            }
081            this.secureRandom = random;
082        }
083    
084        /**
085         * Returns the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}.  Defaults to
086         * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms.
087         *
088         * @return the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}.
089         */
090        public int getDefaultNextBytesSize() {
091            return defaultNextBytesSize;
092        }
093    
094        /**
095         * Sets the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. Defaults to
096         * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms.
097         *
098         * @param defaultNextBytesSize the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}.
099         * @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    }