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.hash; 20 21 import org.apache.shiro.util.ByteSource; 22 23 /** 24 * A {@code HashRequest} is composed of data that will be used by a {@link HashService} to compute a hash (aka 25 * 'digest'). While you can instantiate a concrete {@code HashRequest} class directly, most will find using the 26 * {@link HashRequest.Builder} more convenient. 27 * 28 * @see HashRequest.Builder 29 * @since 1.2 30 */ 31 public interface HashRequest { 32 33 /** 34 * Returns the source data that will be hashed by a {@link HashService}. For example, this might be a 35 * {@code ByteSource} representation of a password, or file, etc. 36 * 37 * @return the source data that will be hashed by a {@link HashService}. 38 */ 39 ByteSource getSource(); 40 41 /** 42 * Returns a salt to be used by the {@link HashService} during hash computation, or {@code null} if no salt is 43 * provided as part of the request. 44 * <p/> 45 * Note that a {@code null} value does not necessarily mean a salt won't be used at all - it just 46 * means that the request didn't include one. The servicing {@link HashService} is free to provide a salting 47 * strategy for a request, even if the request did not specify one. 48 * 49 * @return a salt to be used by the {@link HashService} during hash computation, or {@code null} if no salt is 50 * provided as part of the request. 51 */ 52 ByteSource getSalt(); 53 54 /** 55 * Returns the number of requested hash iterations to be performed when computing the final {@code Hash} result. 56 * A non-positive (0 or less) indicates that the {@code HashService}'s default iteration configuration should 57 * be used. A positive value overrides the {@code HashService}'s configuration for a single request. 58 * <p/> 59 * Note that a {@code HashService} is free to ignore this number if it determines the number is not sufficient 60 * to meet a desired level of security. 61 * 62 * @return the number of requested hash iterations to be performed when computing the final {@code Hash} result. 63 */ 64 int getIterations(); 65 66 /** 67 * Returns the name of the hash algorithm the {@code HashService} should use when computing the {@link Hash}, or 68 * {@code null} if the default algorithm configuration of the {@code HashService} should be used. A non-null value 69 * overrides the {@code HashService}'s configuration for a single request. 70 * <p/> 71 * Note that a {@code HashService} is free to ignore this value if it determines that the algorithm is not 72 * sufficient to meet a desired level of security. 73 * 74 * @return the name of the hash algorithm the {@code HashService} should use when computing the {@link Hash}, or 75 * {@code null} if the default algorithm configuration of the {@code HashService} should be used. 76 */ 77 String getAlgorithmName(); 78 79 /** 80 * A Builder class representing the Builder design pattern for constructing {@link HashRequest} instances. 81 * 82 * @see SimpleHashRequest 83 * @since 1.2 84 */ 85 public static class Builder { 86 87 private ByteSource source; 88 private ByteSource salt; 89 private int iterations; 90 private String algorithmName; 91 92 /** 93 * Default no-arg constructor. 94 */ 95 public Builder() { 96 this.iterations = 0; 97 } 98 99 /** 100 * Sets the source data that will be hashed by a {@link HashService}. For example, this might be a 101 * {@code ByteSource} representation of a password, or file, etc. 102 * 103 * @param source the source data that will be hashed by a {@link HashService}. 104 * @return this {@code Builder} instance for method chaining. 105 * @see HashRequest#getSource() 106 * @see #setSource(Object) 107 */ 108 public Builder setSource(ByteSource source) { 109 this.source = source; 110 return this; 111 } 112 113 /** 114 * Sets the source data that will be hashed by a {@link HashService}. 115 * <p/> 116 * This is a convenience alternative to {@link #setSource(ByteSource)}: it will attempt to convert the 117 * argument into a {@link ByteSource} instance using Shiro's default conversion heuristics 118 * (as defined by {@link ByteSource.Util#isCompatible(Object) ByteSource.Util.isCompatible}. If the object 119 * cannot be heuristically converted to a {@code ByteSource}, an {@code IllegalArgumentException} will be 120 * thrown. 121 * 122 * @param source the byte-backed source data that will be hashed by a {@link HashService}. 123 * @return this {@code Builder} instance for method chaining. 124 * @throws IllegalArgumentException if the argument cannot be heuristically converted to a {@link ByteSource} 125 * instance. 126 * @see HashRequest#getSource() 127 * @see #setSource(ByteSource) 128 */ 129 public Builder setSource(Object source) throws IllegalArgumentException { 130 this.source = ByteSource.Util.bytes(source); 131 return this; 132 } 133 134 /** 135 * Sets a salt to be used by the {@link HashService} during hash computation. 136 * <p/> 137 * <b>NOTE</b>: not calling this method does not necessarily mean a salt won't be used at all - it just 138 * means that the request didn't include a salt. The servicing {@link HashService} is free to provide a salting 139 * strategy for a request, even if the request did not specify one. You can always check the result 140 * {@code Hash} {@link Hash#getSalt() getSalt()} method to see what the actual 141 * salt was (if any), which may or may not match this request salt. 142 * 143 * @param salt a salt to be used by the {@link HashService} during hash computation 144 * @return this {@code Builder} instance for method chaining. 145 * @see HashRequest#getSalt() 146 */ 147 public Builder setSalt(ByteSource salt) { 148 this.salt = salt; 149 return this; 150 } 151 152 /** 153 * Sets a salt to be used by the {@link HashService} during hash computation. 154 * <p/> 155 * This is a convenience alternative to {@link #setSalt(ByteSource)}: it will attempt to convert the 156 * argument into a {@link ByteSource} instance using Shiro's default conversion heuristics 157 * (as defined by {@link ByteSource.Util#isCompatible(Object) ByteSource.Util.isCompatible}. If the object 158 * cannot be heuristically converted to a {@code ByteSource}, an {@code IllegalArgumentException} will be 159 * thrown. 160 * 161 * @param salt a salt to be used by the {@link HashService} during hash computation. 162 * @return this {@code Builder} instance for method chaining. 163 * @throws IllegalArgumentException if the argument cannot be heuristically converted to a {@link ByteSource} 164 * instance. 165 * @see #setSalt(ByteSource) 166 * @see HashRequest#getSalt() 167 */ 168 public Builder setSalt(Object salt) throws IllegalArgumentException { 169 this.salt = ByteSource.Util.bytes(salt); 170 return this; 171 } 172 173 /** 174 * Sets the number of requested hash iterations to be performed when computing the final {@code Hash} result. 175 * Not calling this method or setting a non-positive value (0 or less) indicates that the {@code HashService}'s 176 * default iteration configuration should be used. A positive value overrides the {@code HashService}'s 177 * configuration for a single request. 178 * <p/> 179 * Note that a {@code HashService} is free to ignore this number if it determines the number is not sufficient 180 * to meet a desired level of security. You can always check the result 181 * {@code Hash} {@link Hash#getIterations() getIterations()} method to see what the actual 182 * number of iterations was, which may or may not match this request salt. 183 * 184 * @param iterations the number of requested hash iterations to be performed when computing the final 185 * {@code Hash} result. 186 * @return this {@code Builder} instance for method chaining. 187 * @see HashRequest#getIterations() 188 */ 189 public Builder setIterations(int iterations) { 190 this.iterations = iterations; 191 return this; 192 } 193 194 /** 195 * Sets the name of the hash algorithm the {@code HashService} should use when computing the {@link Hash}. 196 * Not calling this method or setting it to {@code null} indicates the the default algorithm configuration of 197 * the {@code HashService} should be used. A non-null value 198 * overrides the {@code HashService}'s configuration for a single request. 199 * <p/> 200 * Note that a {@code HashService} is free to ignore this value if it determines that the algorithm is not 201 * sufficient to meet a desired level of security. You can always check the result 202 * {@code Hash} {@link Hash#getAlgorithmName() getAlgorithmName()} method to see what the actual 203 * algorithm was, which may or may not match this request salt. 204 * 205 * @param algorithmName the name of the hash algorithm the {@code HashService} should use when computing the 206 * {@link Hash}, or {@code null} if the default algorithm configuration of the 207 * {@code HashService} should be used. 208 * @return this {@code Builder} instance for method chaining. 209 * @see HashRequest#getAlgorithmName() 210 */ 211 public Builder setAlgorithmName(String algorithmName) { 212 this.algorithmName = algorithmName; 213 return this; 214 } 215 216 /** 217 * Builds a {@link HashRequest} instance reflecting the specified configuration. 218 * 219 * @return a {@link HashRequest} instance reflecting the specified configuration. 220 */ 221 public HashRequest build() { 222 return new SimpleHashRequest(this.algorithmName, this.source, this.salt, this.iterations); 223 } 224 } 225 }