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 module hunt.shiro.crypto.SecureRandomNumberGenerator; 20 21 import hunt.shiro.crypto.RandomNumberGenerator; 22 import hunt.shiro.util.ByteSource; 23 import hunt.shiro.util.SimpleByteSource; 24 25 import hunt.security.SecureRandom; 26 27 import hunt.Exceptions; 28 29 /** 30 * Default implementation of the {@link RandomNumberGenerator RandomNumberGenerator} interface, backed by a 31 * {@link SecureRandom SecureRandom} instance. 32 * <p/> 33 * This class is a little easier to use than using the JDK's {@code SecureRandom} class directly. It also 34 * allows for JavaBeans-style of customization, convenient for Shiro's INI configuration or other IoC configuration 35 * mechanism. 36 * 37 * @since 1.1 38 */ 39 class SecureRandomNumberGenerator : RandomNumberGenerator { 40 41 protected enum int DEFAULT_NEXT_BYTES_SIZE = 16; //16 bytes == 128 bits (a common number in crypto) 42 43 private int defaultNextBytesSize; 44 private SecureRandom secureRandom; 45 46 /** 47 * Creates a new instance with a default backing {@link SecureRandom SecureRandom} and a 48 * {@link #getDefaultNextBytesSize() defaultNextBytesSize} of {@code 16}, which equals 128 bits, a size commonly 49 * used in cryptographic algorithms. 50 */ 51 this() { 52 this.defaultNextBytesSize = DEFAULT_NEXT_BYTES_SIZE; 53 this.secureRandom = new SecureRandom(); 54 } 55 56 /** 57 * Seeds the backing {@link SecureRandom SecureRandom} instance with additional seed data. 58 * 59 * @param bytes the seed bytes 60 * @see SecureRandom#setSeed(byte[]) 61 */ 62 void setSeed(byte[] bytes) { 63 this.secureRandom.setSeed(bytes); 64 } 65 66 /** 67 * Returns the {@link SecureRandom SecureRandom} backing this instance. 68 * 69 * @return the {@link SecureRandom SecureRandom} backing this instance. 70 */ 71 SecureRandom getSecureRandom() { 72 return secureRandom; 73 } 74 75 /** 76 * Sets the {@link SecureRandom SecureRandom} to back this instance. 77 * 78 * @param random the {@link SecureRandom SecureRandom} to back this instance. 79 * @throws NullPointerException if the method argument is null 80 */ 81 void setSecureRandom(SecureRandom random) { 82 if (random is null) { 83 throw new NullPointerException("SecureRandom argument cannot be null."); 84 } 85 this.secureRandom = random; 86 } 87 88 /** 89 * Returns the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. Defaults to 90 * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms. 91 * 92 * @return the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. 93 */ 94 int getDefaultNextBytesSize() { 95 return defaultNextBytesSize; 96 } 97 98 /** 99 * Sets the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. Defaults to 100 * {@code 16}, which equals 128 bits, a size commonly used in cryptographic algorithms. 101 * 102 * @param defaultNextBytesSize the size of the generated byte array for calls to {@link #nextBytes() nextBytes()}. 103 * @throws IllegalArgumentException if the argument is 0 or negative 104 */ 105 void setDefaultNextBytesSize(int defaultNextBytesSize) { 106 if ( defaultNextBytesSize <= 0) { 107 throw new IllegalArgumentException("size value must be a positive integer (1 or larger)"); 108 } 109 this.defaultNextBytesSize = defaultNextBytesSize; 110 } 111 112 ByteSource nextBytes() { 113 return nextBytes(getDefaultNextBytesSize()); 114 } 115 116 ByteSource nextBytes(int numBytes) { 117 if (numBytes <= 0) { 118 throw new IllegalArgumentException("numBytes argument must be a positive integer (1 or larger)"); 119 } 120 byte[] bytes = new byte[numBytes]; 121 this.secureRandom.nextBytes(bytes); 122 return ByteSourceUtil.bytes(bytes); 123 } 124 }