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.hash;
020    
021    import org.apache.shiro.util.ByteSource;
022    
023    /**
024     * A {@code HashRequest} is composed of data that will be used by a {@link HashService} to compute a hash (aka
025     * 'digest').  While you can instantiate a concrete {@code HashRequest} class directly, most will find using the
026     * {@link HashRequest.Builder} more convenient.
027     *
028     * @see HashRequest.Builder
029     * @since 1.2
030     */
031    public interface HashRequest {
032    
033        /**
034         * Returns the source data that will be hashed by a {@link HashService}. For example, this might be a
035         * {@code ByteSource} representation of a password, or file, etc.
036         *
037         * @return the source data that will be hashed by a {@link HashService}.
038         */
039        ByteSource getSource();
040    
041        /**
042         * Returns a salt to be used by the {@link HashService} during hash computation, or {@code null} if no salt is
043         * provided as part of the request.
044         * <p/>
045         * Note that a {@code null} value does not necessarily mean a salt won't be used at all - it just
046         * means that the request didn't include one.  The servicing {@link HashService} is free to provide a salting
047         * strategy for a request, even if the request did not specify one.
048         *
049         * @return a salt to be used by the {@link HashService} during hash computation, or {@code null} if no salt is
050         *         provided as part of the request.
051         */
052        ByteSource getSalt();
053    
054        /**
055         * Returns the number of requested hash iterations to be performed when computing the final {@code Hash} result.
056         * A non-positive (0 or less) indicates that the {@code HashService}'s default iteration configuration should
057         * be used.  A positive value overrides the {@code HashService}'s configuration for a single request.
058         * <p/>
059         * Note that a {@code HashService} is free to ignore this number if it determines the number is not sufficient
060         * to meet a desired level of security.
061         *
062         * @return the number of requested hash iterations to be performed when computing the final {@code Hash} result.
063         */
064        int getIterations();
065    
066        /**
067         * Returns the name of the hash algorithm the {@code HashService} should use when computing the {@link Hash}, or
068         * {@code null} if the default algorithm configuration of the {@code HashService} should be used.  A non-null value
069         * overrides the {@code HashService}'s configuration for a single request.
070         * <p/>
071         * Note that a {@code HashService} is free to ignore this value if it determines that the algorithm is not
072         * sufficient to meet a desired level of security.
073         *
074         * @return the name of the hash algorithm the {@code HashService} should use when computing the {@link Hash}, or
075         *         {@code null} if the default algorithm configuration of the {@code HashService} should be used.
076         */
077        String getAlgorithmName();
078    
079        /**
080         * A Builder class representing the Builder design pattern for constructing {@link HashRequest} instances.
081         *
082         * @see SimpleHashRequest
083         * @since 1.2
084         */
085        public static class Builder {
086    
087            private ByteSource source;
088            private ByteSource salt;
089            private int iterations;
090            private String algorithmName;
091    
092            /**
093             * Default no-arg constructor.
094             */
095            public Builder() {
096                this.iterations = 0;
097            }
098    
099            /**
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    }