blob: 74b8413b4aace1526ef6dd377b72abdd67278826 [file] [log] [blame]
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Source code</title>
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
</head>
<body>
<main role="main">
<div class="sourceContainer">
<pre><span class="sourceLineNo">001</span><a id="line.1">/*</a>
<span class="sourceLineNo">002</span><a id="line.2"> * Licensed to the Apache Software Foundation (ASF) under one</a>
<span class="sourceLineNo">003</span><a id="line.3"> * or more contributor license agreements. See the NOTICE file</a>
<span class="sourceLineNo">004</span><a id="line.4"> * distributed with this work for additional information</a>
<span class="sourceLineNo">005</span><a id="line.5"> * regarding copyright ownership. The ASF licenses this file</a>
<span class="sourceLineNo">006</span><a id="line.6"> * to you under the Apache License, Version 2.0 (the</a>
<span class="sourceLineNo">007</span><a id="line.7"> * "License"); you may not use this file except in compliance</a>
<span class="sourceLineNo">008</span><a id="line.8"> * with the License. You may obtain a copy of the License at</a>
<span class="sourceLineNo">009</span><a id="line.9"> *</a>
<span class="sourceLineNo">010</span><a id="line.10"> * http://www.apache.org/licenses/LICENSE-2.0</a>
<span class="sourceLineNo">011</span><a id="line.11"> *</a>
<span class="sourceLineNo">012</span><a id="line.12"> * Unless required by applicable law or agreed to in writing,</a>
<span class="sourceLineNo">013</span><a id="line.13"> * software distributed under the License is distributed on an</a>
<span class="sourceLineNo">014</span><a id="line.14"> * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</a>
<span class="sourceLineNo">015</span><a id="line.15"> * KIND, either express or implied. See the License for the</a>
<span class="sourceLineNo">016</span><a id="line.16"> * specific language governing permissions and limitations</a>
<span class="sourceLineNo">017</span><a id="line.17"> * under the License.</a>
<span class="sourceLineNo">018</span><a id="line.18"> */</a>
<span class="sourceLineNo">019</span><a id="line.19">package org.apache.shiro.crypto.hash;</a>
<span class="sourceLineNo">020</span><a id="line.20"></a>
<span class="sourceLineNo">021</span><a id="line.21">import org.apache.shiro.crypto.RandomNumberGenerator;</a>
<span class="sourceLineNo">022</span><a id="line.22">import org.apache.shiro.crypto.SecureRandomNumberGenerator;</a>
<span class="sourceLineNo">023</span><a id="line.23">import org.apache.shiro.util.ByteSource;</a>
<span class="sourceLineNo">024</span><a id="line.24"></a>
<span class="sourceLineNo">025</span><a id="line.25">/**</a>
<span class="sourceLineNo">026</span><a id="line.26"> * Default implementation of the {@link HashService} interface, supporting a customizable hash algorithm name,</a>
<span class="sourceLineNo">027</span><a id="line.27"> * secure-random salt generation, multiple hash iterations and an optional internal</a>
<span class="sourceLineNo">028</span><a id="line.28"> * {@link #setPrivateSalt(ByteSource) privateSalt}.</a>
<span class="sourceLineNo">029</span><a id="line.29"> * &lt;h2&gt;Hash Algorithm&lt;/h2&gt;</a>
<span class="sourceLineNo">030</span><a id="line.30"> * You may specify a hash algorithm via the {@link #setHashAlgorithmName(String)} property. Any algorithm name</a>
<span class="sourceLineNo">031</span><a id="line.31"> * understood by the JDK</a>
<span class="sourceLineNo">032</span><a id="line.32"> * {@link java.security.MessageDigest#getInstance(String) MessageDigest.getInstance(String algorithmName)} method</a>
<span class="sourceLineNo">033</span><a id="line.33"> * will work. The default is {@code SHA-512}.</a>
<span class="sourceLineNo">034</span><a id="line.34"> * &lt;h2&gt;Random Salts&lt;/h2&gt;</a>
<span class="sourceLineNo">035</span><a id="line.35"> * When a salt is not specified in a request, this implementation generates secure random salts via its</a>
<span class="sourceLineNo">036</span><a id="line.36"> * {@link #setRandomNumberGenerator(org.apache.shiro.crypto.RandomNumberGenerator) randomNumberGenerator} property.</a>
<span class="sourceLineNo">037</span><a id="line.37"> * Random salts (and potentially combined with the internal {@link #getPrivateSalt() privateSalt}) is a very strong</a>
<span class="sourceLineNo">038</span><a id="line.38"> * salting strategy, as salts should ideally never be based on known/guessable data. The default instance is a</a>
<span class="sourceLineNo">039</span><a id="line.39"> * {@link SecureRandomNumberGenerator}.</a>
<span class="sourceLineNo">040</span><a id="line.40"> * &lt;h2&gt;Hash Iterations&lt;/h2&gt;</a>
<span class="sourceLineNo">041</span><a id="line.41"> * Secure hashing strategies often employ multiple hash iterations to slow down the hashing process. This technique</a>
<span class="sourceLineNo">042</span><a id="line.42"> * is usually used for password hashing, since the longer it takes to compute a password hash, the longer it would</a>
<span class="sourceLineNo">043</span><a id="line.43"> * take for an attacker to compromise a password. This</a>
<span class="sourceLineNo">044</span><a id="line.44"> * &lt;a href="http://www.stormpath.com/blog/strong-password-hashing-apache-shiro"&gt;blog article&lt;/a&gt;</a>
<span class="sourceLineNo">045</span><a id="line.45"> * explains in greater detail why this is useful, as well as information on how many iterations is 'enough'.</a>
<span class="sourceLineNo">046</span><a id="line.46"> * &lt;p/&gt;</a>
<span class="sourceLineNo">047</span><a id="line.47"> * You may set the number of hash iterations via the {@link #setHashIterations(int)} property. The default is</a>
<span class="sourceLineNo">048</span><a id="line.48"> * {@code 1}, but should be increased significantly if the {@code HashService} is intended to be used for password</a>
<span class="sourceLineNo">049</span><a id="line.49"> * hashing. See the linked blog article for more info.</a>
<span class="sourceLineNo">050</span><a id="line.50"> * &lt;h2&gt;Private Salt&lt;/h2&gt;</a>
<span class="sourceLineNo">051</span><a id="line.51"> * If using this implementation as part of a password hashing strategy, it might be desirable to configure a</a>
<span class="sourceLineNo">052</span><a id="line.52"> * {@link #setPrivateSalt(ByteSource) private salt}:</a>
<span class="sourceLineNo">053</span><a id="line.53"> * &lt;p/&gt;</a>
<span class="sourceLineNo">054</span><a id="line.54"> * A hash and the salt used to compute it are often stored together. If an attacker is ever able to access</a>
<span class="sourceLineNo">055</span><a id="line.55"> * the hash (e.g. during password cracking) and it has the full salt value, the attacker has all of the input necessary</a>
<span class="sourceLineNo">056</span><a id="line.56"> * to try to brute-force crack the hash (source + complete salt).</a>
<span class="sourceLineNo">057</span><a id="line.57"> * &lt;p/&gt;</a>
<span class="sourceLineNo">058</span><a id="line.58"> * However, if part of the salt is not available to the attacker (because it is not stored with the hash), it is</a>
<span class="sourceLineNo">059</span><a id="line.59"> * &lt;em&gt;much&lt;/em&gt; harder to crack the hash value since the attacker does not have the complete inputs necessary.</a>
<span class="sourceLineNo">060</span><a id="line.60"> * &lt;p/&gt;</a>
<span class="sourceLineNo">061</span><a id="line.61"> * The {@link #getPrivateSalt() privateSalt} property exists to satisfy this private-and-not-shared part of the salt.</a>
<span class="sourceLineNo">062</span><a id="line.62"> * If you configure this attribute, you can obtain this additional very important safety feature.</a>
<span class="sourceLineNo">063</span><a id="line.63"> * &lt;p/&gt;</a>
<span class="sourceLineNo">064</span><a id="line.64"> * &lt;b&gt;*&lt;/b&gt;By default, the {@link #getPrivateSalt() privateSalt} is null, since a sensible default cannot be used that</a>
<span class="sourceLineNo">065</span><a id="line.65"> * isn't easily compromised (because Shiro is an open-source project and any default could be easily seen and used).</a>
<span class="sourceLineNo">066</span><a id="line.66"> *</a>
<span class="sourceLineNo">067</span><a id="line.67"> * @since 1.2</a>
<span class="sourceLineNo">068</span><a id="line.68"> */</a>
<span class="sourceLineNo">069</span><a id="line.69">public class DefaultHashService implements ConfigurableHashService {</a>
<span class="sourceLineNo">070</span><a id="line.70"></a>
<span class="sourceLineNo">071</span><a id="line.71"> /**</a>
<span class="sourceLineNo">072</span><a id="line.72"> * The RandomNumberGenerator to use to randomly generate the public part of the hash salt.</a>
<span class="sourceLineNo">073</span><a id="line.73"> */</a>
<span class="sourceLineNo">074</span><a id="line.74"> private RandomNumberGenerator rng;</a>
<span class="sourceLineNo">075</span><a id="line.75"></a>
<span class="sourceLineNo">076</span><a id="line.76"> /**</a>
<span class="sourceLineNo">077</span><a id="line.77"> * The MessageDigest name of the hash algorithm to use for computing hashes.</a>
<span class="sourceLineNo">078</span><a id="line.78"> */</a>
<span class="sourceLineNo">079</span><a id="line.79"> private String algorithmName;</a>
<span class="sourceLineNo">080</span><a id="line.80"></a>
<span class="sourceLineNo">081</span><a id="line.81"> /**</a>
<span class="sourceLineNo">082</span><a id="line.82"> * The 'private' part of the hash salt.</a>
<span class="sourceLineNo">083</span><a id="line.83"> */</a>
<span class="sourceLineNo">084</span><a id="line.84"> private ByteSource privateSalt;</a>
<span class="sourceLineNo">085</span><a id="line.85"></a>
<span class="sourceLineNo">086</span><a id="line.86"> /**</a>
<span class="sourceLineNo">087</span><a id="line.87"> * The number of hash iterations to perform when computing hashes.</a>
<span class="sourceLineNo">088</span><a id="line.88"> */</a>
<span class="sourceLineNo">089</span><a id="line.89"> private int iterations;</a>
<span class="sourceLineNo">090</span><a id="line.90"></a>
<span class="sourceLineNo">091</span><a id="line.91"> /**</a>
<span class="sourceLineNo">092</span><a id="line.92"> * Whether or not to generate public salts if a request does not provide one.</a>
<span class="sourceLineNo">093</span><a id="line.93"> */</a>
<span class="sourceLineNo">094</span><a id="line.94"> private boolean generatePublicSalt;</a>
<span class="sourceLineNo">095</span><a id="line.95"></a>
<span class="sourceLineNo">096</span><a id="line.96"> /**</a>
<span class="sourceLineNo">097</span><a id="line.97"> * Constructs a new {@code DefaultHashService} instance with the following defaults:</a>
<span class="sourceLineNo">098</span><a id="line.98"> * &lt;ul&gt;</a>
<span class="sourceLineNo">099</span><a id="line.99"> * &lt;li&gt;{@link #setHashAlgorithmName(String) hashAlgorithmName} = {@code SHA-512}&lt;/li&gt;</a>
<span class="sourceLineNo">100</span><a id="line.100"> * &lt;li&gt;{@link #setHashIterations(int) hashIterations} = {@code 1}&lt;/li&gt;</a>
<span class="sourceLineNo">101</span><a id="line.101"> * &lt;li&gt;{@link #setRandomNumberGenerator(org.apache.shiro.crypto.RandomNumberGenerator) randomNumberGenerator} =</a>
<span class="sourceLineNo">102</span><a id="line.102"> * new {@link SecureRandomNumberGenerator}()&lt;/li&gt;</a>
<span class="sourceLineNo">103</span><a id="line.103"> * &lt;li&gt;{@link #setGeneratePublicSalt(boolean) generatePublicSalt} = {@code false}&lt;/li&gt;</a>
<span class="sourceLineNo">104</span><a id="line.104"> * &lt;/ul&gt;</a>
<span class="sourceLineNo">105</span><a id="line.105"> * &lt;p/&gt;</a>
<span class="sourceLineNo">106</span><a id="line.106"> * If this hashService will be used for password hashing it is recommended to set the</a>
<span class="sourceLineNo">107</span><a id="line.107"> * {@link #setPrivateSalt(ByteSource) privateSalt} and significantly increase the number of</a>
<span class="sourceLineNo">108</span><a id="line.108"> * {@link #setHashIterations(int) hashIterations}. See the class-level JavaDoc for more information.</a>
<span class="sourceLineNo">109</span><a id="line.109"> */</a>
<span class="sourceLineNo">110</span><a id="line.110"> public DefaultHashService() {</a>
<span class="sourceLineNo">111</span><a id="line.111"> this.algorithmName = "SHA-512";</a>
<span class="sourceLineNo">112</span><a id="line.112"> this.iterations = 1;</a>
<span class="sourceLineNo">113</span><a id="line.113"> this.generatePublicSalt = false;</a>
<span class="sourceLineNo">114</span><a id="line.114"> this.rng = new SecureRandomNumberGenerator();</a>
<span class="sourceLineNo">115</span><a id="line.115"> }</a>
<span class="sourceLineNo">116</span><a id="line.116"></a>
<span class="sourceLineNo">117</span><a id="line.117"> /**</a>
<span class="sourceLineNo">118</span><a id="line.118"> * Computes and responds with a hash based on the specified request.</a>
<span class="sourceLineNo">119</span><a id="line.119"> * &lt;p/&gt;</a>
<span class="sourceLineNo">120</span><a id="line.120"> * This implementation functions as follows:</a>
<span class="sourceLineNo">121</span><a id="line.121"> * &lt;ul&gt;</a>
<span class="sourceLineNo">122</span><a id="line.122"> * &lt;li&gt;If the request's {@link org.apache.shiro.crypto.hash.HashRequest#getSalt() salt} is null:</a>
<span class="sourceLineNo">123</span><a id="line.123"> * &lt;p/&gt;</a>
<span class="sourceLineNo">124</span><a id="line.124"> * A salt will be generated and used to compute the hash. The salt is generated as follows:</a>
<span class="sourceLineNo">125</span><a id="line.125"> * &lt;ol&gt;</a>
<span class="sourceLineNo">126</span><a id="line.126"> * &lt;li&gt;Use the {@link #getRandomNumberGenerator() randomNumberGenerator} to generate a new random number.&lt;/li&gt;</a>
<span class="sourceLineNo">127</span><a id="line.127"> * &lt;li&gt;{@link #combine(ByteSource, ByteSource) combine} this random salt with any configured</a>
<span class="sourceLineNo">128</span><a id="line.128"> * {@link #getPrivateSalt() privateSalt}</a>
<span class="sourceLineNo">129</span><a id="line.129"> * &lt;/li&gt;</a>
<span class="sourceLineNo">130</span><a id="line.130"> * &lt;li&gt;Use the combined value as the salt used during hash computation&lt;/li&gt;</a>
<span class="sourceLineNo">131</span><a id="line.131"> * &lt;/ol&gt;</a>
<span class="sourceLineNo">132</span><a id="line.132"> * &lt;/li&gt;</a>
<span class="sourceLineNo">133</span><a id="line.133"> * &lt;li&gt;</a>
<span class="sourceLineNo">134</span><a id="line.134"> * If the request salt is not null:</a>
<span class="sourceLineNo">135</span><a id="line.135"> * &lt;p/&gt;</a>
<span class="sourceLineNo">136</span><a id="line.136"> * This indicates that the hash computation is for comparison purposes (of a</a>
<span class="sourceLineNo">137</span><a id="line.137"> * previously computed hash). The request salt will be {@link #combine(ByteSource, ByteSource) combined} with any</a>
<span class="sourceLineNo">138</span><a id="line.138"> * configured {@link #getPrivateSalt() privateSalt} and used as the complete salt during hash computation.</a>
<span class="sourceLineNo">139</span><a id="line.139"> * &lt;/li&gt;</a>
<span class="sourceLineNo">140</span><a id="line.140"> * &lt;/ul&gt;</a>
<span class="sourceLineNo">141</span><a id="line.141"> * &lt;p/&gt;</a>
<span class="sourceLineNo">142</span><a id="line.142"> * The returned {@code Hash}'s {@link Hash#getSalt() salt} property</a>
<span class="sourceLineNo">143</span><a id="line.143"> * will contain &lt;em&gt;only&lt;/em&gt; the 'public' part of the salt and &lt;em&gt;NOT&lt;/em&gt; the privateSalt. See the class-level</a>
<span class="sourceLineNo">144</span><a id="line.144"> * JavaDoc explanation for more info.</a>
<span class="sourceLineNo">145</span><a id="line.145"> *</a>
<span class="sourceLineNo">146</span><a id="line.146"> * @param request the request to process</a>
<span class="sourceLineNo">147</span><a id="line.147"> * @return the response containing the result of the hash computation, as well as any hash salt used that should be</a>
<span class="sourceLineNo">148</span><a id="line.148"> * exposed to the caller.</a>
<span class="sourceLineNo">149</span><a id="line.149"> */</a>
<span class="sourceLineNo">150</span><a id="line.150"> public Hash computeHash(HashRequest request) {</a>
<span class="sourceLineNo">151</span><a id="line.151"> if (request == null || request.getSource() == null || request.getSource().isEmpty()) {</a>
<span class="sourceLineNo">152</span><a id="line.152"> return null;</a>
<span class="sourceLineNo">153</span><a id="line.153"> }</a>
<span class="sourceLineNo">154</span><a id="line.154"></a>
<span class="sourceLineNo">155</span><a id="line.155"> String algorithmName = getAlgorithmName(request);</a>
<span class="sourceLineNo">156</span><a id="line.156"> ByteSource source = request.getSource();</a>
<span class="sourceLineNo">157</span><a id="line.157"> int iterations = getIterations(request);</a>
<span class="sourceLineNo">158</span><a id="line.158"></a>
<span class="sourceLineNo">159</span><a id="line.159"> ByteSource publicSalt = getPublicSalt(request);</a>
<span class="sourceLineNo">160</span><a id="line.160"> ByteSource privateSalt = getPrivateSalt();</a>
<span class="sourceLineNo">161</span><a id="line.161"> ByteSource salt = combine(privateSalt, publicSalt);</a>
<span class="sourceLineNo">162</span><a id="line.162"></a>
<span class="sourceLineNo">163</span><a id="line.163"> Hash computed = new SimpleHash(algorithmName, source, salt, iterations);</a>
<span class="sourceLineNo">164</span><a id="line.164"></a>
<span class="sourceLineNo">165</span><a id="line.165"> SimpleHash result = new SimpleHash(algorithmName);</a>
<span class="sourceLineNo">166</span><a id="line.166"> result.setBytes(computed.getBytes());</a>
<span class="sourceLineNo">167</span><a id="line.167"> result.setIterations(iterations);</a>
<span class="sourceLineNo">168</span><a id="line.168"> //Only expose the public salt - not the real/combined salt that might have been used:</a>
<span class="sourceLineNo">169</span><a id="line.169"> result.setSalt(publicSalt);</a>
<span class="sourceLineNo">170</span><a id="line.170"></a>
<span class="sourceLineNo">171</span><a id="line.171"> return result;</a>
<span class="sourceLineNo">172</span><a id="line.172"> }</a>
<span class="sourceLineNo">173</span><a id="line.173"></a>
<span class="sourceLineNo">174</span><a id="line.174"> protected String getAlgorithmName(HashRequest request) {</a>
<span class="sourceLineNo">175</span><a id="line.175"> String name = request.getAlgorithmName();</a>
<span class="sourceLineNo">176</span><a id="line.176"> if (name == null) {</a>
<span class="sourceLineNo">177</span><a id="line.177"> name = getHashAlgorithmName();</a>
<span class="sourceLineNo">178</span><a id="line.178"> }</a>
<span class="sourceLineNo">179</span><a id="line.179"> return name;</a>
<span class="sourceLineNo">180</span><a id="line.180"> }</a>
<span class="sourceLineNo">181</span><a id="line.181"></a>
<span class="sourceLineNo">182</span><a id="line.182"> protected int getIterations(HashRequest request) {</a>
<span class="sourceLineNo">183</span><a id="line.183"> int iterations = Math.max(0, request.getIterations());</a>
<span class="sourceLineNo">184</span><a id="line.184"> if (iterations &lt; 1) {</a>
<span class="sourceLineNo">185</span><a id="line.185"> iterations = Math.max(1, getHashIterations());</a>
<span class="sourceLineNo">186</span><a id="line.186"> }</a>
<span class="sourceLineNo">187</span><a id="line.187"> return iterations;</a>
<span class="sourceLineNo">188</span><a id="line.188"> }</a>
<span class="sourceLineNo">189</span><a id="line.189"></a>
<span class="sourceLineNo">190</span><a id="line.190"> /**</a>
<span class="sourceLineNo">191</span><a id="line.191"> * Returns the public salt that should be used to compute a hash based on the specified request or</a>
<span class="sourceLineNo">192</span><a id="line.192"> * {@code null} if no public salt should be used.</a>
<span class="sourceLineNo">193</span><a id="line.193"> * &lt;p/&gt;</a>
<span class="sourceLineNo">194</span><a id="line.194"> * This implementation functions as follows:</a>
<span class="sourceLineNo">195</span><a id="line.195"> * &lt;ol&gt;</a>
<span class="sourceLineNo">196</span><a id="line.196"> * &lt;li&gt;If the request salt is not null and non-empty, this will be used, return it.&lt;/li&gt;</a>
<span class="sourceLineNo">197</span><a id="line.197"> * &lt;li&gt;If the request salt is null or empty:</a>
<span class="sourceLineNo">198</span><a id="line.198"> * &lt;ol&gt;</a>
<span class="sourceLineNo">199</span><a id="line.199"> * &lt;li&gt;If a private salt has been set &lt;em&gt;OR&lt;/em&gt; {@link #isGeneratePublicSalt()} is {@code true},</a>
<span class="sourceLineNo">200</span><a id="line.200"> * auto generate a random public salt via the configured</a>
<span class="sourceLineNo">201</span><a id="line.201"> * {@link #getRandomNumberGenerator() randomNumberGenerator}.&lt;/li&gt;</a>
<span class="sourceLineNo">202</span><a id="line.202"> * &lt;li&gt;If a private salt has not been configured and {@link #isGeneratePublicSalt()} is {@code false},</a>
<span class="sourceLineNo">203</span><a id="line.203"> * do nothing - return {@code null} to indicate a salt should not be used during hash computation.&lt;/li&gt;</a>
<span class="sourceLineNo">204</span><a id="line.204"> * &lt;/ol&gt;</a>
<span class="sourceLineNo">205</span><a id="line.205"> * &lt;/li&gt;</a>
<span class="sourceLineNo">206</span><a id="line.206"> * &lt;/ol&gt;</a>
<span class="sourceLineNo">207</span><a id="line.207"> *</a>
<span class="sourceLineNo">208</span><a id="line.208"> * @param request request the request to process</a>
<span class="sourceLineNo">209</span><a id="line.209"> * @return the public salt that should be used to compute a hash based on the specified request or</a>
<span class="sourceLineNo">210</span><a id="line.210"> * {@code null} if no public salt should be used.</a>
<span class="sourceLineNo">211</span><a id="line.211"> */</a>
<span class="sourceLineNo">212</span><a id="line.212"> protected ByteSource getPublicSalt(HashRequest request) {</a>
<span class="sourceLineNo">213</span><a id="line.213"></a>
<span class="sourceLineNo">214</span><a id="line.214"> ByteSource publicSalt = request.getSalt();</a>
<span class="sourceLineNo">215</span><a id="line.215"></a>
<span class="sourceLineNo">216</span><a id="line.216"> if (publicSalt != null &amp;&amp; !publicSalt.isEmpty()) {</a>
<span class="sourceLineNo">217</span><a id="line.217"> //a public salt was explicitly requested to be used - go ahead and use it:</a>
<span class="sourceLineNo">218</span><a id="line.218"> return publicSalt;</a>
<span class="sourceLineNo">219</span><a id="line.219"> }</a>
<span class="sourceLineNo">220</span><a id="line.220"></a>
<span class="sourceLineNo">221</span><a id="line.221"> publicSalt = null;</a>
<span class="sourceLineNo">222</span><a id="line.222"></a>
<span class="sourceLineNo">223</span><a id="line.223"> //check to see if we need to generate one:</a>
<span class="sourceLineNo">224</span><a id="line.224"> ByteSource privateSalt = getPrivateSalt();</a>
<span class="sourceLineNo">225</span><a id="line.225"> boolean privateSaltExists = privateSalt != null &amp;&amp; !privateSalt.isEmpty();</a>
<span class="sourceLineNo">226</span><a id="line.226"></a>
<span class="sourceLineNo">227</span><a id="line.227"> //If a private salt exists, we must generate a public salt to protect the integrity of the private salt.</a>
<span class="sourceLineNo">228</span><a id="line.228"> //Or generate it if the instance is explicitly configured to do so:</a>
<span class="sourceLineNo">229</span><a id="line.229"> if (privateSaltExists || isGeneratePublicSalt()) {</a>
<span class="sourceLineNo">230</span><a id="line.230"> publicSalt = getRandomNumberGenerator().nextBytes();</a>
<span class="sourceLineNo">231</span><a id="line.231"> }</a>
<span class="sourceLineNo">232</span><a id="line.232"></a>
<span class="sourceLineNo">233</span><a id="line.233"> return publicSalt;</a>
<span class="sourceLineNo">234</span><a id="line.234"> }</a>
<span class="sourceLineNo">235</span><a id="line.235"></a>
<span class="sourceLineNo">236</span><a id="line.236"> /**</a>
<span class="sourceLineNo">237</span><a id="line.237"> * Combines the specified 'private' salt bytes with the specified additional extra bytes to use as the</a>
<span class="sourceLineNo">238</span><a id="line.238"> * total salt during hash computation. {@code privateSaltBytes} will be {@code null} }if no private salt has been</a>
<span class="sourceLineNo">239</span><a id="line.239"> * configured.</a>
<span class="sourceLineNo">240</span><a id="line.240"> *</a>
<span class="sourceLineNo">241</span><a id="line.241"> * @param privateSalt the (possibly {@code null}) 'private' salt to combine with the specified extra bytes</a>
<span class="sourceLineNo">242</span><a id="line.242"> * @param publicSalt the extra bytes to use in addition to the given private salt.</a>
<span class="sourceLineNo">243</span><a id="line.243"> * @return a combination of the specified private salt bytes and extra bytes that will be used as the total</a>
<span class="sourceLineNo">244</span><a id="line.244"> * salt during hash computation.</a>
<span class="sourceLineNo">245</span><a id="line.245"> */</a>
<span class="sourceLineNo">246</span><a id="line.246"> protected ByteSource combine(ByteSource privateSalt, ByteSource publicSalt) {</a>
<span class="sourceLineNo">247</span><a id="line.247"></a>
<span class="sourceLineNo">248</span><a id="line.248"> byte[] privateSaltBytes = privateSalt != null ? privateSalt.getBytes() : null;</a>
<span class="sourceLineNo">249</span><a id="line.249"> int privateSaltLength = privateSaltBytes != null ? privateSaltBytes.length : 0;</a>
<span class="sourceLineNo">250</span><a id="line.250"></a>
<span class="sourceLineNo">251</span><a id="line.251"> byte[] publicSaltBytes = publicSalt != null ? publicSalt.getBytes() : null;</a>
<span class="sourceLineNo">252</span><a id="line.252"> int extraBytesLength = publicSaltBytes != null ? publicSaltBytes.length : 0;</a>
<span class="sourceLineNo">253</span><a id="line.253"></a>
<span class="sourceLineNo">254</span><a id="line.254"> int length = privateSaltLength + extraBytesLength;</a>
<span class="sourceLineNo">255</span><a id="line.255"></a>
<span class="sourceLineNo">256</span><a id="line.256"> if (length &lt;= 0) {</a>
<span class="sourceLineNo">257</span><a id="line.257"> return null;</a>
<span class="sourceLineNo">258</span><a id="line.258"> }</a>
<span class="sourceLineNo">259</span><a id="line.259"></a>
<span class="sourceLineNo">260</span><a id="line.260"> byte[] combined = new byte[length];</a>
<span class="sourceLineNo">261</span><a id="line.261"></a>
<span class="sourceLineNo">262</span><a id="line.262"> int i = 0;</a>
<span class="sourceLineNo">263</span><a id="line.263"> for (int j = 0; j &lt; privateSaltLength; j++) {</a>
<span class="sourceLineNo">264</span><a id="line.264"> assert privateSaltBytes != null;</a>
<span class="sourceLineNo">265</span><a id="line.265"> combined[i++] = privateSaltBytes[j];</a>
<span class="sourceLineNo">266</span><a id="line.266"> }</a>
<span class="sourceLineNo">267</span><a id="line.267"> for (int j = 0; j &lt; extraBytesLength; j++) {</a>
<span class="sourceLineNo">268</span><a id="line.268"> assert publicSaltBytes != null;</a>
<span class="sourceLineNo">269</span><a id="line.269"> combined[i++] = publicSaltBytes[j];</a>
<span class="sourceLineNo">270</span><a id="line.270"> }</a>
<span class="sourceLineNo">271</span><a id="line.271"></a>
<span class="sourceLineNo">272</span><a id="line.272"> return ByteSource.Util.bytes(combined);</a>
<span class="sourceLineNo">273</span><a id="line.273"> }</a>
<span class="sourceLineNo">274</span><a id="line.274"></a>
<span class="sourceLineNo">275</span><a id="line.275"> public void setHashAlgorithmName(String name) {</a>
<span class="sourceLineNo">276</span><a id="line.276"> this.algorithmName = name;</a>
<span class="sourceLineNo">277</span><a id="line.277"> }</a>
<span class="sourceLineNo">278</span><a id="line.278"></a>
<span class="sourceLineNo">279</span><a id="line.279"> public String getHashAlgorithmName() {</a>
<span class="sourceLineNo">280</span><a id="line.280"> return this.algorithmName;</a>
<span class="sourceLineNo">281</span><a id="line.281"> }</a>
<span class="sourceLineNo">282</span><a id="line.282"></a>
<span class="sourceLineNo">283</span><a id="line.283"> public void setPrivateSalt(ByteSource privateSalt) {</a>
<span class="sourceLineNo">284</span><a id="line.284"> this.privateSalt = privateSalt;</a>
<span class="sourceLineNo">285</span><a id="line.285"> }</a>
<span class="sourceLineNo">286</span><a id="line.286"></a>
<span class="sourceLineNo">287</span><a id="line.287"> public ByteSource getPrivateSalt() {</a>
<span class="sourceLineNo">288</span><a id="line.288"> return this.privateSalt;</a>
<span class="sourceLineNo">289</span><a id="line.289"> }</a>
<span class="sourceLineNo">290</span><a id="line.290"></a>
<span class="sourceLineNo">291</span><a id="line.291"> public void setHashIterations(int count) {</a>
<span class="sourceLineNo">292</span><a id="line.292"> this.iterations = count;</a>
<span class="sourceLineNo">293</span><a id="line.293"> }</a>
<span class="sourceLineNo">294</span><a id="line.294"></a>
<span class="sourceLineNo">295</span><a id="line.295"> public int getHashIterations() {</a>
<span class="sourceLineNo">296</span><a id="line.296"> return this.iterations;</a>
<span class="sourceLineNo">297</span><a id="line.297"> }</a>
<span class="sourceLineNo">298</span><a id="line.298"></a>
<span class="sourceLineNo">299</span><a id="line.299"> public void setRandomNumberGenerator(RandomNumberGenerator rng) {</a>
<span class="sourceLineNo">300</span><a id="line.300"> this.rng = rng;</a>
<span class="sourceLineNo">301</span><a id="line.301"> }</a>
<span class="sourceLineNo">302</span><a id="line.302"></a>
<span class="sourceLineNo">303</span><a id="line.303"> public RandomNumberGenerator getRandomNumberGenerator() {</a>
<span class="sourceLineNo">304</span><a id="line.304"> return this.rng;</a>
<span class="sourceLineNo">305</span><a id="line.305"> }</a>
<span class="sourceLineNo">306</span><a id="line.306"></a>
<span class="sourceLineNo">307</span><a id="line.307"> /**</a>
<span class="sourceLineNo">308</span><a id="line.308"> * Returns {@code true} if a public salt should be randomly generated and used to compute a hash if a</a>
<span class="sourceLineNo">309</span><a id="line.309"> * {@link HashRequest} does not specify a salt, {@code false} otherwise.</a>
<span class="sourceLineNo">310</span><a id="line.310"> * &lt;p/&gt;</a>
<span class="sourceLineNo">311</span><a id="line.311"> * The default value is {@code false} but should definitely be set to {@code true} if the</a>
<span class="sourceLineNo">312</span><a id="line.312"> * {@code HashService} instance is being used for password hashing.</a>
<span class="sourceLineNo">313</span><a id="line.313"> * &lt;p/&gt;</a>
<span class="sourceLineNo">314</span><a id="line.314"> * &lt;b&gt;NOTE:&lt;/b&gt; this property only has an effect if a {@link #getPrivateSalt() privateSalt} is NOT configured. If a</a>
<span class="sourceLineNo">315</span><a id="line.315"> * private salt has been configured and a request does not provide a salt, a random salt will always be generated</a>
<span class="sourceLineNo">316</span><a id="line.316"> * to protect the integrity of the private salt (without a public salt, the private salt would be exposed as-is,</a>
<span class="sourceLineNo">317</span><a id="line.317"> * which is undesirable).</a>
<span class="sourceLineNo">318</span><a id="line.318"> *</a>
<span class="sourceLineNo">319</span><a id="line.319"> * @return {@code true} if a public salt should be randomly generated and used to compute a hash if a</a>
<span class="sourceLineNo">320</span><a id="line.320"> * {@link HashRequest} does not specify a salt, {@code false} otherwise.</a>
<span class="sourceLineNo">321</span><a id="line.321"> */</a>
<span class="sourceLineNo">322</span><a id="line.322"> public boolean isGeneratePublicSalt() {</a>
<span class="sourceLineNo">323</span><a id="line.323"> return generatePublicSalt;</a>
<span class="sourceLineNo">324</span><a id="line.324"> }</a>
<span class="sourceLineNo">325</span><a id="line.325"></a>
<span class="sourceLineNo">326</span><a id="line.326"> /**</a>
<span class="sourceLineNo">327</span><a id="line.327"> * Sets whether or not a public salt should be randomly generated and used to compute a hash if a</a>
<span class="sourceLineNo">328</span><a id="line.328"> * {@link HashRequest} does not specify a salt.</a>
<span class="sourceLineNo">329</span><a id="line.329"> * &lt;p/&gt;</a>
<span class="sourceLineNo">330</span><a id="line.330"> * The default value is {@code false} but should definitely be set to {@code true} if the</a>
<span class="sourceLineNo">331</span><a id="line.331"> * {@code HashService} instance is being used for password hashing.</a>
<span class="sourceLineNo">332</span><a id="line.332"> * &lt;p/&gt;</a>
<span class="sourceLineNo">333</span><a id="line.333"> * &lt;b&gt;NOTE:&lt;/b&gt; this property only has an effect if a {@link #getPrivateSalt() privateSalt} is NOT configured. If a</a>
<span class="sourceLineNo">334</span><a id="line.334"> * private salt has been configured and a request does not provide a salt, a random salt will always be generated</a>
<span class="sourceLineNo">335</span><a id="line.335"> * to protect the integrity of the private salt (without a public salt, the private salt would be exposed as-is,</a>
<span class="sourceLineNo">336</span><a id="line.336"> * which is undesirable).</a>
<span class="sourceLineNo">337</span><a id="line.337"> *</a>
<span class="sourceLineNo">338</span><a id="line.338"> * @param generatePublicSalt whether or not a public salt should be randomly generated and used to compute a hash</a>
<span class="sourceLineNo">339</span><a id="line.339"> * if a {@link HashRequest} does not specify a salt.</a>
<span class="sourceLineNo">340</span><a id="line.340"> */</a>
<span class="sourceLineNo">341</span><a id="line.341"> public void setGeneratePublicSalt(boolean generatePublicSalt) {</a>
<span class="sourceLineNo">342</span><a id="line.342"> this.generatePublicSalt = generatePublicSalt;</a>
<span class="sourceLineNo">343</span><a id="line.343"> }</a>
<span class="sourceLineNo">344</span><a id="line.344">}</a>
</pre>
</div>
</main>
</body>
</html>