Skip to content

Commit 9cc88cb

Browse files
HipDragonbdemers
authored andcommitted
Added private salt option to password Hasher
1 parent 6d738af commit 9cc88cb

File tree

1 file changed

+34
-5
lines changed
  • tools/hasher/src/main/java/org/apache/shiro/tools/hasher

1 file changed

+34
-5
lines changed

tools/hasher/src/main/java/org/apache/shiro/tools/hasher/Hasher.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@
2323
import org.apache.commons.cli.HelpFormatter;
2424
import org.apache.commons.cli.Option;
2525
import org.apache.commons.cli.Options;
26-
import org.apache.commons.cli.PosixParser;
26+
import org.apache.commons.cli.DefaultParser;
2727
import org.apache.shiro.authc.credential.DefaultPasswordService;
2828
import org.apache.shiro.codec.Base64;
2929
import org.apache.shiro.codec.Hex;
3030
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
3131
import org.apache.shiro.crypto.UnknownAlgorithmException;
32-
import org.apache.shiro.crypto.hash.SimpleHash;
32+
import org.apache.shiro.crypto.hash.DefaultHashService;
33+
import org.apache.shiro.crypto.hash.Hash;
34+
import org.apache.shiro.crypto.hash.HashRequest;
35+
import org.apache.shiro.crypto.hash.SimpleHashRequest;
3336
import org.apache.shiro.crypto.hash.format.DefaultHashFormatFactory;
3437
import org.apache.shiro.crypto.hash.format.HashFormat;
3538
import org.apache.shiro.crypto.hash.format.HashFormatFactory;
@@ -77,6 +80,8 @@ public final class Hasher {
7780
private static final Option SALT_GEN = new Option("gs", "gensalt", false, "generate and use a random salt. Defaults to true when password hashing, false otherwise.");
7881
private static final Option NO_SALT_GEN = new Option("ngs", "nogensalt", false, "do NOT generate and use a random salt (valid during password hashing).");
7982
private static final Option SALT_GEN_SIZE = new Option("gss", "gensaltsize", true, "the number of salt bits (not bytes!) to generate. Defaults to 128.");
83+
private static final Option PRIVATE_SALT = new Option("ps", "privatesalt", true, "use the specified private salt. <arg> is plaintext.");
84+
private static final Option PRIVATE_SALT_BYTES = new Option("psb", "privatesaltbytes", true, "use the specified private salt bytes. <arg> is hex or base64 encoded text.");
8085

8186
private static final String SALT_MUTEX_MSG = createMutexMessage(SALT, SALT_BYTES);
8287

@@ -92,12 +97,13 @@ public final class Hasher {
9297

9398
public static void main(String[] args) {
9499

95-
CommandLineParser parser = new PosixParser();
100+
CommandLineParser parser = new DefaultParser();
96101

97102
Options options = new Options();
98103
options.addOption(HELP).addOption(DEBUG).addOption(ALGORITHM).addOption(ITERATIONS);
99104
options.addOption(RESOURCE).addOption(PASSWORD).addOption(PASSWORD_NC);
100105
options.addOption(SALT).addOption(SALT_BYTES).addOption(SALT_GEN).addOption(SALT_GEN_SIZE).addOption(NO_SALT_GEN);
106+
options.addOption(PRIVATE_SALT).addOption(PRIVATE_SALT_BYTES);
101107
options.addOption(FORMAT);
102108

103109
boolean debug = false;
@@ -110,6 +116,8 @@ public static void main(String[] args) {
110116
String saltBytesString = null;
111117
boolean generateSalt = false;
112118
int generatedSaltSize = DEFAULT_GENERATED_SALT_SIZE;
119+
String privateSaltString = null;
120+
String privateSaltBytesString = null;
113121

114122
String formatString = null;
115123

@@ -161,6 +169,12 @@ public static void main(String[] args) {
161169
throw new IllegalArgumentException("Generated salt size must be a multiple of 8 (e.g. 128, 192, 256, 512, etc).");
162170
}
163171
}
172+
if (line.hasOption(PRIVATE_SALT.getOpt())) {
173+
privateSaltString = line.getOptionValue(PRIVATE_SALT.getOpt());
174+
}
175+
if (line.hasOption(PRIVATE_SALT_BYTES.getOpt())) {
176+
privateSaltBytesString = line.getOptionValue(PRIVATE_SALT_BYTES.getOpt());
177+
}
164178
if (line.hasOption(FORMAT.getOpt())) {
165179
formatString = line.getOptionValue(FORMAT.getOpt());
166180
}
@@ -209,9 +223,13 @@ public static void main(String[] args) {
209223
}
210224
}
211225

212-
ByteSource salt = getSalt(saltString, saltBytesString, generateSalt, generatedSaltSize);
226+
ByteSource publicSalt = getSalt(saltString, saltBytesString, generateSalt, generatedSaltSize);
227+
ByteSource privateSalt = getSalt(privateSaltString, privateSaltBytesString, false, generatedSaltSize);
228+
HashRequest hashRequest = new SimpleHashRequest(algorithm, ByteSource.Util.bytes(source), publicSalt, iterations);
213229

214-
SimpleHash hash = new SimpleHash(algorithm, source, salt, iterations);
230+
DefaultHashService hashService = new DefaultHashService();
231+
hashService.setPrivateSalt(privateSalt);
232+
Hash hash = hashService.computeHash(hashRequest);
215233

216234
if (formatString == null) {
217235
//Output format was not specified. Default to 'shiro1' when password hashing, and 'hex' for
@@ -375,6 +393,17 @@ private static void printHelp(Options options, Exception e, boolean debug) {
375393
"encoding. If you prefer to use hex encoding, additionally use the\n" +
376394
"-sgh/--saltgeneratedhex option." +
377395
"\n\n" +
396+
"Specifying a private salt:" +
397+
"\n\n" +
398+
"You may specify a private salt using the -ps/--privatesalt option followed\n" +
399+
"by the private salt value. If the private salt value is a base64 or hex \n" +
400+
"string representing a byte array, you must specify the -psb/--privatesaltbytes\n" +
401+
"option to indicate this, otherwise the text value bytes will be used directly." +
402+
"\n\n" +
403+
"When using -psb/--privatesaltbytes, the -ps/--privatesalt value is expected to\n" +
404+
"be a base64-encoded string by default. If the value is a hex-encoded string,\n" +
405+
"you must prefix the string with 0x (zero x) to indicate a hex value." +
406+
"\n\n" +
378407
"Files, URLs and classpath resources:\n" +
379408
"---------------------------------\n" +
380409
"If using the -r/--resource option, the <value> represents a resource path.\n" +

0 commit comments

Comments
 (0)