| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>Hasher.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Shiro :: Tools :: Hasher</a> > <a href="index.source.html" class="el_package">org.apache.shiro.tools.hasher</a> > <span class="el_source">Hasher.java</span></div><h1>Hasher.java</h1><pre class="source lang-java linenums">/* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.shiro.tools.hasher; |
| |
| import org.apache.commons.cli.*; |
| import org.apache.shiro.authc.credential.DefaultPasswordService; |
| import org.apache.shiro.codec.Base64; |
| import org.apache.shiro.codec.Hex; |
| import org.apache.shiro.crypto.SecureRandomNumberGenerator; |
| import org.apache.shiro.crypto.UnknownAlgorithmException; |
| import org.apache.shiro.crypto.hash.SimpleHash; |
| import org.apache.shiro.crypto.hash.format.*; |
| import org.apache.shiro.io.ResourceUtils; |
| import org.apache.shiro.util.ByteSource; |
| import org.apache.shiro.util.JavaEnvironment; |
| import org.apache.shiro.util.StringUtils; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Arrays; |
| |
| /** |
| * Commandline line utility to hash data such as strings, passwords, resources (files, urls, etc). |
| * <p/> |
| * Usage: |
| * <pre> |
| * java -jar shiro-tools-hasher<em>-version</em>-cli.jar |
| * </pre> |
| * This will print out all supported options with documentation. |
| * |
| * @since 1.2 |
| */ |
| <span class="nc bnc" id="L49" title="All 2 branches missed.">public final class Hasher {</span> |
| |
| private static final String HEX_PREFIX = "0x"; |
| private static final String DEFAULT_ALGORITHM_NAME = "MD5"; |
| private static final String DEFAULT_PASSWORD_ALGORITHM_NAME = DefaultPasswordService.DEFAULT_HASH_ALGORITHM; |
| private static final int DEFAULT_GENERATED_SALT_SIZE = 128; |
| private static final int DEFAULT_NUM_ITERATIONS = 1; |
| private static final int DEFAULT_PASSWORD_NUM_ITERATIONS = DefaultPasswordService.DEFAULT_HASH_ITERATIONS; |
| |
| <span class="nc" id="L58"> private static final Option ALGORITHM = new Option("a", "algorithm", true, "hash algorithm name. Defaults to SHA-256 when password hashing, MD5 otherwise.");</span> |
| <span class="nc" id="L59"> private static final Option DEBUG = new Option("d", "debug", false, "show additional error (stack trace) information.");</span> |
| <span class="nc" id="L60"> private static final Option FORMAT = new Option("f", "format", true, "hash output format. Defaults to 'shiro1' when password hashing, 'hex' otherwise. See below for more information.");</span> |
| <span class="nc" id="L61"> private static final Option HELP = new Option("help", "help", false, "show this help message.");</span> |
| <span class="nc" id="L62"> private static final Option ITERATIONS = new Option("i", "iterations", true, "number of hash iterations. Defaults to " + DEFAULT_PASSWORD_NUM_ITERATIONS + " when password hashing, 1 otherwise.");</span> |
| <span class="nc" id="L63"> private static final Option PASSWORD = new Option("p", "password", false, "hash a password (disable typing echo)");</span> |
| <span class="nc" id="L64"> private static final Option PASSWORD_NC = new Option("pnc", "pnoconfirm", false, "hash a password (disable typing echo) but disable password confirmation prompt.");</span> |
| <span class="nc" id="L65"> private static final Option RESOURCE = new Option("r", "resource", false, "read and hash the resource located at <value>. See below for more information.");</span> |
| <span class="nc" id="L66"> private static final Option SALT = new Option("s", "salt", true, "use the specified salt. <arg> is plaintext.");</span> |
| <span class="nc" id="L67"> private static final Option SALT_BYTES = new Option("sb", "saltbytes", true, "use the specified salt bytes. <arg> is hex or base64 encoded text.");</span> |
| <span class="nc" id="L68"> 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.");</span> |
| <span class="nc" id="L69"> private static final Option NO_SALT_GEN = new Option("ngs", "nogensalt", false, "do NOT generate and use a random salt (valid during password hashing).");</span> |
| <span class="nc" id="L70"> private static final Option SALT_GEN_SIZE = new Option("gss", "gensaltsize", true, "the number of salt bits (not bytes!) to generate. Defaults to 128.");</span> |
| |
| <span class="nc" id="L72"> private static final String SALT_MUTEX_MSG = createMutexMessage(SALT, SALT_BYTES);</span> |
| |
| <span class="nc" id="L74"> private static final HashFormatFactory HASH_FORMAT_FACTORY = new DefaultHashFormatFactory();</span> |
| |
| static { |
| <span class="nc" id="L77"> ALGORITHM.setArgName("name");</span> |
| <span class="nc" id="L78"> SALT_GEN_SIZE.setArgName("numBits");</span> |
| <span class="nc" id="L79"> ITERATIONS.setArgName("num");</span> |
| <span class="nc" id="L80"> SALT.setArgName("sval");</span> |
| <span class="nc" id="L81"> SALT_BYTES.setArgName("encTxt");</span> |
| <span class="nc" id="L82"> }</span> |
| |
| public static void main(String[] args) { |
| |
| <span class="nc" id="L86"> CommandLineParser parser = new PosixParser();</span> |
| |
| <span class="nc" id="L88"> Options options = new Options();</span> |
| <span class="nc" id="L89"> options.addOption(HELP).addOption(DEBUG).addOption(ALGORITHM).addOption(ITERATIONS);</span> |
| <span class="nc" id="L90"> options.addOption(RESOURCE).addOption(PASSWORD).addOption(PASSWORD_NC);</span> |
| <span class="nc" id="L91"> options.addOption(SALT).addOption(SALT_BYTES).addOption(SALT_GEN).addOption(SALT_GEN_SIZE).addOption(NO_SALT_GEN);</span> |
| <span class="nc" id="L92"> options.addOption(FORMAT);</span> |
| |
| <span class="nc" id="L94"> boolean debug = false;</span> |
| <span class="nc" id="L95"> String algorithm = null; //user unspecified</span> |
| <span class="nc" id="L96"> int iterations = 0; //0 means unspecified by the end-user</span> |
| <span class="nc" id="L97"> boolean resource = false;</span> |
| <span class="nc" id="L98"> boolean password = false;</span> |
| <span class="nc" id="L99"> boolean passwordConfirm = true;</span> |
| <span class="nc" id="L100"> String saltString = null;</span> |
| <span class="nc" id="L101"> String saltBytesString = null;</span> |
| <span class="nc" id="L102"> boolean generateSalt = false;</span> |
| <span class="nc" id="L103"> int generatedSaltSize = DEFAULT_GENERATED_SALT_SIZE;</span> |
| |
| <span class="nc" id="L105"> String formatString = null;</span> |
| |
| <span class="nc" id="L107"> char[] passwordChars = null;</span> |
| |
| try { |
| <span class="nc" id="L110"> CommandLine line = parser.parse(options, args);</span> |
| |
| <span class="nc bnc" id="L112" title="All 2 branches missed."> if (line.hasOption(HELP.getOpt())) {</span> |
| <span class="nc" id="L113"> printHelpAndExit(options, null, debug, 0);</span> |
| } |
| <span class="nc bnc" id="L115" title="All 2 branches missed."> if (line.hasOption(DEBUG.getOpt())) {</span> |
| <span class="nc" id="L116"> debug = true;</span> |
| } |
| <span class="nc bnc" id="L118" title="All 2 branches missed."> if (line.hasOption(ALGORITHM.getOpt())) {</span> |
| <span class="nc" id="L119"> algorithm = line.getOptionValue(ALGORITHM.getOpt());</span> |
| } |
| <span class="nc bnc" id="L121" title="All 2 branches missed."> if (line.hasOption(ITERATIONS.getOpt())) {</span> |
| <span class="nc" id="L122"> iterations = getRequiredPositiveInt(line, ITERATIONS);</span> |
| } |
| <span class="nc bnc" id="L124" title="All 2 branches missed."> if (line.hasOption(PASSWORD.getOpt())) {</span> |
| <span class="nc" id="L125"> password = true;</span> |
| <span class="nc" id="L126"> generateSalt = true;</span> |
| } |
| <span class="nc bnc" id="L128" title="All 2 branches missed."> if (line.hasOption(RESOURCE.getOpt())) {</span> |
| <span class="nc" id="L129"> resource = true;</span> |
| } |
| <span class="nc bnc" id="L131" title="All 2 branches missed."> if (line.hasOption(PASSWORD_NC.getOpt())) {</span> |
| <span class="nc" id="L132"> password = true;</span> |
| <span class="nc" id="L133"> generateSalt = true;</span> |
| <span class="nc" id="L134"> passwordConfirm = false;</span> |
| } |
| <span class="nc bnc" id="L136" title="All 2 branches missed."> if (line.hasOption(SALT.getOpt())) {</span> |
| <span class="nc" id="L137"> saltString = line.getOptionValue(SALT.getOpt());</span> |
| } |
| <span class="nc bnc" id="L139" title="All 2 branches missed."> if (line.hasOption(SALT_BYTES.getOpt())) {</span> |
| <span class="nc" id="L140"> saltBytesString = line.getOptionValue(SALT_BYTES.getOpt());</span> |
| } |
| <span class="nc bnc" id="L142" title="All 2 branches missed."> if (line.hasOption(NO_SALT_GEN.getOpt())) {</span> |
| <span class="nc" id="L143"> generateSalt = false;</span> |
| } |
| <span class="nc bnc" id="L145" title="All 2 branches missed."> if (line.hasOption(SALT_GEN.getOpt())) {</span> |
| <span class="nc" id="L146"> generateSalt = true;</span> |
| } |
| <span class="nc bnc" id="L148" title="All 2 branches missed."> if (line.hasOption(SALT_GEN_SIZE.getOpt())) {</span> |
| <span class="nc" id="L149"> generateSalt = true;</span> |
| <span class="nc" id="L150"> generatedSaltSize = getRequiredPositiveInt(line, SALT_GEN_SIZE);</span> |
| <span class="nc bnc" id="L151" title="All 2 branches missed."> if (generatedSaltSize % 8 != 0) {</span> |
| <span class="nc" id="L152"> throw new IllegalArgumentException("Generated salt size must be a multiple of 8 (e.g. 128, 192, 256, 512, etc).");</span> |
| } |
| } |
| <span class="nc bnc" id="L155" title="All 2 branches missed."> if (line.hasOption(FORMAT.getOpt())) {</span> |
| <span class="nc" id="L156"> formatString = line.getOptionValue(FORMAT.getOpt());</span> |
| } |
| |
| String sourceValue; |
| |
| Object source; |
| |
| <span class="nc bnc" id="L163" title="All 2 branches missed."> if (password) {</span> |
| <span class="nc" id="L164"> passwordChars = readPassword(passwordConfirm);</span> |
| <span class="nc" id="L165"> source = passwordChars;</span> |
| } else { |
| <span class="nc" id="L167"> String[] remainingArgs = line.getArgs();</span> |
| <span class="nc bnc" id="L168" title="All 4 branches missed."> if (remainingArgs == null || remainingArgs.length != 1) {</span> |
| <span class="nc" id="L169"> printHelpAndExit(options, null, debug, -1);</span> |
| } |
| |
| <span class="nc bnc" id="L172" title="All 4 branches missed."> assert remainingArgs != null;</span> |
| <span class="nc" id="L173"> sourceValue = toString(remainingArgs);</span> |
| |
| <span class="nc bnc" id="L175" title="All 2 branches missed."> if (resource) {</span> |
| <span class="nc bnc" id="L176" title="All 2 branches missed."> if (!ResourceUtils.hasResourcePrefix(sourceValue)) {</span> |
| <span class="nc" id="L177"> source = toFile(sourceValue);</span> |
| } else { |
| <span class="nc" id="L179"> source = ResourceUtils.getInputStreamForPath(sourceValue);</span> |
| } |
| } else { |
| <span class="nc" id="L182"> source = sourceValue;</span> |
| } |
| } |
| |
| <span class="nc bnc" id="L186" title="All 2 branches missed."> if (algorithm == null) {</span> |
| <span class="nc bnc" id="L187" title="All 2 branches missed."> if (password) {</span> |
| <span class="nc" id="L188"> algorithm = DEFAULT_PASSWORD_ALGORITHM_NAME;</span> |
| } else { |
| <span class="nc" id="L190"> algorithm = DEFAULT_ALGORITHM_NAME;</span> |
| } |
| } |
| |
| <span class="nc bnc" id="L194" title="All 2 branches missed."> if (iterations < DEFAULT_NUM_ITERATIONS) {</span> |
| //Iterations were not specified. Default to 350,000 when password hashing, and 1 for everything else: |
| <span class="nc bnc" id="L196" title="All 2 branches missed."> if (password) {</span> |
| <span class="nc" id="L197"> iterations = DEFAULT_PASSWORD_NUM_ITERATIONS;</span> |
| } else { |
| <span class="nc" id="L199"> iterations = DEFAULT_NUM_ITERATIONS;</span> |
| } |
| } |
| |
| <span class="nc" id="L203"> ByteSource salt = getSalt(saltString, saltBytesString, generateSalt, generatedSaltSize);</span> |
| |
| <span class="nc" id="L205"> SimpleHash hash = new SimpleHash(algorithm, source, salt, iterations);</span> |
| |
| <span class="nc bnc" id="L207" title="All 2 branches missed."> if (formatString == null) {</span> |
| //Output format was not specified. Default to 'shiro1' when password hashing, and 'hex' for |
| //everything else: |
| <span class="nc bnc" id="L210" title="All 2 branches missed."> if (password) {</span> |
| <span class="nc" id="L211"> formatString = Shiro1CryptFormat.class.getName();</span> |
| } else { |
| <span class="nc" id="L213"> formatString = HexFormat.class.getName();</span> |
| } |
| } |
| |
| <span class="nc" id="L217"> HashFormat format = HASH_FORMAT_FACTORY.getInstance(formatString);</span> |
| |
| <span class="nc bnc" id="L219" title="All 2 branches missed."> if (format == null) {</span> |
| <span class="nc" id="L220"> throw new IllegalArgumentException("Unrecognized hash format '" + formatString + "'.");</span> |
| } |
| |
| <span class="nc" id="L223"> String output = format.format(hash);</span> |
| |
| <span class="nc" id="L225"> System.out.println(output);</span> |
| |
| <span class="nc" id="L227"> } catch (IllegalArgumentException iae) {</span> |
| <span class="nc" id="L228"> exit(iae, debug);</span> |
| <span class="nc" id="L229"> } catch (UnknownAlgorithmException uae) {</span> |
| <span class="nc" id="L230"> exit(uae, debug);</span> |
| <span class="nc" id="L231"> } catch (IOException ioe) {</span> |
| <span class="nc" id="L232"> exit(ioe, debug);</span> |
| <span class="nc" id="L233"> } catch (Exception e) {</span> |
| <span class="nc" id="L234"> printHelpAndExit(options, e, debug, -1);</span> |
| } finally { |
| <span class="nc bnc" id="L236" title="All 24 branches missed."> if (passwordChars != null && passwordChars.length > 0) {</span> |
| <span class="nc bnc" id="L237" title="All 12 branches missed."> for (int i = 0; i < passwordChars.length; i++) {</span> |
| <span class="nc" id="L238"> passwordChars[i] = ' ';</span> |
| } |
| } |
| } |
| <span class="nc" id="L242"> }</span> |
| |
| private static String createMutexMessage(Option... options) { |
| <span class="nc" id="L245"> StringBuilder sb = new StringBuilder();</span> |
| <span class="nc" id="L246"> sb.append("The ");</span> |
| |
| <span class="nc bnc" id="L248" title="All 2 branches missed."> for (int i = 0; i < options.length; i++) {</span> |
| <span class="nc bnc" id="L249" title="All 2 branches missed."> if (i > 0) {</span> |
| <span class="nc" id="L250"> sb.append(", ");</span> |
| } |
| <span class="nc" id="L252"> Option o = options[0];</span> |
| <span class="nc" id="L253"> sb.append("-").append(o.getOpt()).append("/--").append(o.getLongOpt());</span> |
| } |
| <span class="nc" id="L255"> sb.append(" and generated salt options are mutually exclusive. Only one of them may be used at a time");</span> |
| <span class="nc" id="L256"> return sb.toString();</span> |
| } |
| |
| private static void exit(Exception e, boolean debug) { |
| <span class="nc" id="L260"> printException(e, debug);</span> |
| <span class="nc" id="L261"> System.exit(-1);</span> |
| <span class="nc" id="L262"> }</span> |
| |
| private static int getRequiredPositiveInt(CommandLine line, Option option) { |
| <span class="nc" id="L265"> String iterVal = line.getOptionValue(option.getOpt());</span> |
| try { |
| <span class="nc" id="L267"> return Integer.parseInt(iterVal);</span> |
| <span class="nc" id="L268"> } catch (NumberFormatException e) {</span> |
| <span class="nc" id="L269"> String msg = "'" + option.getLongOpt() + "' value must be a positive integer.";</span> |
| <span class="nc" id="L270"> throw new IllegalArgumentException(msg, e);</span> |
| } |
| } |
| |
| private static ByteSource getSalt(String saltString, String saltBytesString, boolean generateSalt, int generatedSaltSize) { |
| |
| <span class="nc bnc" id="L276" title="All 2 branches missed."> if (saltString != null) {</span> |
| <span class="nc bnc" id="L277" title="All 4 branches missed."> if (generateSalt || (saltBytesString != null)) {</span> |
| <span class="nc" id="L278"> throw new IllegalArgumentException(SALT_MUTEX_MSG);</span> |
| } |
| <span class="nc" id="L280"> return ByteSource.Util.bytes(saltString);</span> |
| } |
| |
| <span class="nc bnc" id="L283" title="All 2 branches missed."> if (saltBytesString != null) {</span> |
| <span class="nc bnc" id="L284" title="All 2 branches missed."> if (generateSalt) {</span> |
| <span class="nc" id="L285"> throw new IllegalArgumentException(SALT_MUTEX_MSG);</span> |
| } |
| |
| <span class="nc" id="L288"> String value = saltBytesString;</span> |
| <span class="nc" id="L289"> boolean base64 = true;</span> |
| <span class="nc bnc" id="L290" title="All 2 branches missed."> if (saltBytesString.startsWith(HEX_PREFIX)) {</span> |
| //hex: |
| <span class="nc" id="L292"> base64 = false;</span> |
| <span class="nc" id="L293"> value = value.substring(HEX_PREFIX.length());</span> |
| } |
| byte[] bytes; |
| <span class="nc bnc" id="L296" title="All 2 branches missed."> if (base64) {</span> |
| <span class="nc" id="L297"> bytes = Base64.decode(value);</span> |
| } else { |
| <span class="nc" id="L299"> bytes = Hex.decode(value);</span> |
| } |
| <span class="nc" id="L301"> return ByteSource.Util.bytes(bytes);</span> |
| } |
| |
| <span class="nc bnc" id="L304" title="All 2 branches missed."> if (generateSalt) {</span> |
| <span class="nc" id="L305"> SecureRandomNumberGenerator generator = new SecureRandomNumberGenerator();</span> |
| <span class="nc" id="L306"> int byteSize = generatedSaltSize / 8; //generatedSaltSize is in *bits* - convert to byte size:</span> |
| <span class="nc" id="L307"> return generator.nextBytes(byteSize);</span> |
| } |
| |
| //no salt used: |
| <span class="nc" id="L311"> return null;</span> |
| } |
| |
| private static void printException(Exception e, boolean debug) { |
| <span class="nc bnc" id="L315" title="All 2 branches missed."> if (e != null) {</span> |
| <span class="nc" id="L316"> System.out.println();</span> |
| <span class="nc bnc" id="L317" title="All 2 branches missed."> if (debug) {</span> |
| <span class="nc" id="L318"> System.out.println("Error: ");</span> |
| <span class="nc" id="L319"> e.printStackTrace(System.out);</span> |
| <span class="nc" id="L320"> System.out.println(e.getMessage());</span> |
| |
| } else { |
| <span class="nc" id="L323"> System.out.println("Error: " + e.getMessage());</span> |
| <span class="nc" id="L324"> System.out.println();</span> |
| <span class="nc" id="L325"> System.out.println("Specify -d or --debug for more information.");</span> |
| } |
| } |
| <span class="nc" id="L328"> }</span> |
| |
| private static void printHelp(Options options, Exception e, boolean debug) { |
| <span class="nc" id="L331"> HelpFormatter help = new HelpFormatter();</span> |
| <span class="nc" id="L332"> String command = "java -jar shiro-tools-hasher-<version>.jar [options] [<value>]";</span> |
| <span class="nc" id="L333"> String header = "\nPrint a cryptographic hash (aka message digest) of the specified <value>.\n--\nOptions:";</span> |
| <span class="nc" id="L334"> String footer = "\n" +</span> |
| "<value> is optional only when hashing passwords (see below). It is\n" + |
| "required all other times." + |
| "\n\n" + |
| "Password Hashing:\n" + |
| "---------------------------------\n" + |
| "Specify the -p/--password option and DO NOT enter a <value>. You will\n" + |
| "be prompted for a password and characters will not echo as you type." + |
| "\n\n" + |
| "Salting:\n" + |
| "---------------------------------\n" + |
| "Specifying a salt:" + |
| "\n\n" + |
| "You may specify a salt using the -s/--salt option followed by the salt\n" + |
| "value. If the salt value is a base64 or hex string representing a\n" + |
| "byte array, you must specify the -sb/--saltbytes option to indicate this,\n" + |
| "otherwise the text value bytes will be used directly." + |
| "\n\n" + |
| "When using -sb/--saltbytes, the -s/--salt value is expected to be a\n" + |
| "base64-encoded string by default. If the value is a hex-encoded string,\n" + |
| "you must prefix the string with 0x (zero x) to indicate a hex value." + |
| "\n\n" + |
| "Generating a salt:" + |
| "\n\n" + |
| "Use the -sg/--saltgenerated option if you don't want to specify a salt,\n" + |
| "but want a strong random salt to be generated and used during hashing.\n" + |
| "The generated salt size defaults to 128 bits. You may specify\n" + |
| "a different size by using the -sgs/--saltgeneratedsize option followed by\n" + |
| "a positive integer (size is in bits, not bytes)." + |
| "\n\n" + |
| "Because a salt must be specified if computing the\n" + |
| "hash later, generated salts will be printed, defaulting to base64\n" + |
| "encoding. If you prefer to use hex encoding, additionally use the\n" + |
| "-sgh/--saltgeneratedhex option." + |
| "\n\n" + |
| "Files, URLs and classpath resources:\n" + |
| "---------------------------------\n" + |
| "If using the -r/--resource option, the <value> represents a resource path.\n" + |
| "By default this is expected to be a file path, but you may specify\n" + |
| "classpath or URL resources by using the classpath: or url: prefix\n" + |
| "respectively." + |
| "\n\n" + |
| "Some examples:" + |
| "\n\n" + |
| "<command> -r fileInCurrentDirectory.txt\n" + |
| "<command> -r ../../relativePathFile.xml\n" + |
| "<command> -r ~/documents/myfile.pdf\n" + |
| "<command> -r /usr/local/logs/absolutePathFile.log\n" + |
| "<command> -r url:http://foo.com/page.html\n" + |
| "<command> -r classpath:/WEB-INF/lib/something.jar" + |
| "\n\n" + |
| "Output Format:\n" + |
| "---------------------------------\n" + |
| "Specify the -f/--format option followed by either 1) the format ID (as defined\n" + |
| <span class="nc" id="L388"> "by the " + DefaultHashFormatFactory.class.getName() + "\n" +</span> |
| <span class="nc" id="L389"> "JavaDoc) or 2) the fully qualified " + HashFormat.class.getName() + "\n" +</span> |
| "implementation class name to instantiate and use for formatting.\n\n" + |
| "The default output format is 'shiro1' which is a Modular Crypt Format (MCF)\n" + |
| "that shows all relevant information as a dollar-sign ($) delimited string.\n" + |
| "This format is ideal for use in Shiro's text-based user configuration (e.g.\n" + |
| "shiro.ini or a properties file)."; |
| |
| <span class="nc" id="L396"> printException(e, debug);</span> |
| |
| <span class="nc" id="L398"> System.out.println();</span> |
| <span class="nc" id="L399"> help.printHelp(command, header, options, null);</span> |
| <span class="nc" id="L400"> System.out.println(footer);</span> |
| <span class="nc" id="L401"> }</span> |
| |
| private static void printHelpAndExit(Options options, Exception e, boolean debug, int exitCode) { |
| <span class="nc" id="L404"> printHelp(options, e, debug);</span> |
| <span class="nc" id="L405"> System.exit(exitCode);</span> |
| <span class="nc" id="L406"> }</span> |
| |
| private static char[] readPassword(boolean confirm) { |
| <span class="nc bnc" id="L409" title="All 2 branches missed."> if (!JavaEnvironment.isAtLeastVersion16()) {</span> |
| <span class="nc" id="L410"> String msg = "Password hashing (prompt without echo) uses the java.io.Console to read passwords " +</span> |
| "safely. This is only available on Java 1.6 platforms and later."; |
| <span class="nc" id="L412"> throw new IllegalArgumentException(msg);</span> |
| } |
| <span class="nc" id="L414"> java.io.Console console = System.console();</span> |
| <span class="nc bnc" id="L415" title="All 2 branches missed."> if (console == null) {</span> |
| <span class="nc" id="L416"> throw new IllegalStateException("java.io.Console is not available on the current JVM. Cannot read passwords.");</span> |
| } |
| <span class="nc" id="L418"> char[] first = console.readPassword("%s", "Password to hash: ");</span> |
| <span class="nc bnc" id="L419" title="All 4 branches missed."> if (first == null || first.length == 0) {</span> |
| <span class="nc" id="L420"> throw new IllegalArgumentException("No password specified.");</span> |
| } |
| <span class="nc bnc" id="L422" title="All 2 branches missed."> if (confirm) {</span> |
| <span class="nc" id="L423"> char[] second = console.readPassword("%s", "Password to hash (confirm): ");</span> |
| <span class="nc bnc" id="L424" title="All 2 branches missed."> if (!Arrays.equals(first, second)) {</span> |
| <span class="nc" id="L425"> String msg = "Password entries do not match.";</span> |
| <span class="nc" id="L426"> throw new IllegalArgumentException(msg);</span> |
| } |
| } |
| <span class="nc" id="L429"> return first;</span> |
| } |
| |
| private static File toFile(String path) { |
| <span class="nc" id="L433"> String resolved = path;</span> |
| <span class="nc bnc" id="L434" title="All 4 branches missed."> if (path.startsWith("~/") || path.startsWith(("~\\"))) {</span> |
| <span class="nc" id="L435"> resolved = path.replaceFirst("\\~", System.getProperty("user.home"));</span> |
| } |
| <span class="nc" id="L437"> return new File(resolved);</span> |
| } |
| |
| private static String toString(String[] strings) { |
| <span class="nc bnc" id="L441" title="All 2 branches missed."> int len = strings != null ? strings.length : 0;</span> |
| <span class="nc bnc" id="L442" title="All 2 branches missed."> if (len == 0) {</span> |
| <span class="nc" id="L443"> return null;</span> |
| } |
| <span class="nc" id="L445"> return StringUtils.toDelimitedString(strings, " ");</span> |
| } |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.eclemma.org/jacoco">JaCoCo</a> 0.7.7.201606060606</span></div></body></html> |