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.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 }