Class HashingResult

java.lang.Object
de.gustavblass.commons.crypto.HashingResult
All Implemented Interfaces:
de.gustavblass.commons.Copyable<HashingResult>

public class HashingResult extends Object implements de.gustavblass.commons.Copyable<HashingResult>
The result of a hashing operation. Does not contain the input text that was hashed, but only the hash itself and the Argon2 parameters that were used to compute it.
Implementation Note:
This class is not a record, because the constructor needs to check that the provided hash is not null or empty and throw an IllegalArgumentException if that's the case. While that could be done in a record as well, we cannot add throws IllegalArgumentException to the record's constructor signature, risking that callers of the constructor will not handle the exception. JavaDoc is not a sufficient replacement here!
  • Field Details

    • LOG

      private static final org.apache.logging.log4j.Logger LOG
    • hash

      private final byte[] hash
      The Argon2 hash of the input text.
    • argon2Configuration

      @NonNull private final @NonNull Argon2Configuration argon2Configuration
      The Argon2 parameters that were used to compute the hash.
  • Constructor Details

    • HashingResult

      public HashingResult(byte[] hash, @NonNull @NonNull Argon2Configuration argon2Configuration) throws de.gustavblass.commons.exceptions.IllegalArgumentException
      Constructs a new HashingResult object with the provided Argon2 hash and the Argon2 parameters that were used to compute the hash.
      Parameters:
      hash - The Argon2 hash of the input text.
      argon2Configuration - The Argon2 parameters that were used to compute the hash.
      Throws:
      de.gustavblass.commons.exceptions.IllegalArgumentException - If the provided hash is null or empty.
  • Method Details

    • getArgon2Configuration

      @NonNull public @NonNull Argon2Configuration getArgon2Configuration()
      Returns:
      A deep copy of the object instead of the exact same reference, for security reasons.
    • verify

      public boolean verify(@NonNull @NonNull String expectedInput) throws de.gustavblass.commons.exceptions.IllegalArgumentException
      Verifies that this hash is the hash of the provided input text.
      Parameters:
      expectedInput - The string that is assumed to have been the input for this hash. Must not be blank.
      Returns:
      True if this hash corresponds to the provided input text, false otherwise.
      Throws:
      de.gustavblass.commons.exceptions.IllegalArgumentException - If the provided input text is blank.
    • toBase64

      @NonNull public @NonNull String toBase64()

      Converts the hash and the argon2Configuration to a string representation that contains all the information necessary to convert it back to a HashingResult object. The string representation is in the format $[base64]$[base64]$[base64]$[base64]$[hash] with:

      1. The string argon2id, Base64-encoded.
      2. v=[version] (Base64-encoded) where [version] is Argon2Version.version.
      3. m=[memory],t=[iterations],p=[parallelism] (Base64-encoded) with
      invalid reference
      Argon2Configuration#getMemory()
      ,
      invalid reference
      Argon2Configuration#getIterations()
      and
      invalid reference
      Argon2Configuration#getParallelism()
      .
      1. The Base64-encoded
      invalid reference
      salt
      .
      1. The base64-encoded hash of the input text.
      Returns:
      The hash as a string with all necessary information to verify it.
      See Also:
    • toString

      @NonNull public @NonNull String toString()

      Converts the hash and the argon2Configuration to a string representation that contains all the information necessary to convert it back to a HashingResult object. The string representation is in the format $argon2id$v=[version]$m=[memory],t=[iterations],p=[parallelism]$[salt] where

      invalid reference
      Argon2Configuration#getMemory()
      • [iterations] is
      invalid reference
      Argon2Configuration#getIterations()
      • [parallelism] is
      invalid reference
      Argon2Configuration#getParallelism()
      • [salt] is the base64-encoded
      invalid reference
      Argon2Configuration#getSalt()
      • [hash] is the base64-encoded hash of the input text.
      Overrides:
      toString in class Object
      Returns:
      The hash as a string with all necessary information to verify it.
      See Also:
    • parse

      @NonNull public static @NonNull HashingResult parse(@NonNull @NonNull String hash) throws de.gustavblass.commons.exceptions.IllegalArgumentException
      Converts the string representation of a HashingResult object back to a HashingResult object.
      Parameters:
      hash -

      The string representation of a HashingResult object, in the format $argon2id$v=[version]$m=[memory],t=[iterations],p=[parallelism]$[salt] where

      invalid reference
      Argon2Configuration#getMemory()
      • [iterations] is
      invalid reference
      Argon2Configuration#getIterations()
      • [parallelism] is
      invalid reference
      Argon2Configuration#getParallelism()
      • [salt] is the base64-encoded
      invalid reference
      Argon2Configuration#getSalt()
      • [hash] is the base64-encoded hash of the input text.
      Returns:
      The HashingResult object that was represented by the provided string.
      Throws:
      de.gustavblass.commons.exceptions.IllegalArgumentException - If the provided string is not a valid HashingResult string representation or if the Argon2 configuration cannot be parsed.
    • parseBase64

      @NonNull public static @NonNull HashingResult parseBase64(@NonNull @NonNull String hash) throws de.gustavblass.commons.exceptions.IllegalArgumentException
      Converts the base64 string representation of a HashingResult object back to a HashingResult object.
      Parameters:
      hash -

      The base64 string representation of a HashingResult object, in the format $[base64]$[base64]$[base64]$[base64]$[hash] with:

      1. The string argon2id, Base64-encoded.
      2. v=[version] (Base64-encoded) where [version] is Argon2Version.version.
      3. m=[memory],t=[iterations],p=[parallelism] (Base64-encoded) with
      invalid reference
      Argon2Configuration#getMemory()
      ,
      invalid reference
      Argon2Configuration#getIterations()
      and
      invalid reference
      Argon2Configuration#getParallelism()
      .
      1. The Base64-encoded
      invalid reference
      salt
      .
      1. The base64-encoded hash of the input text.
      Returns:
      The HashingResult object that was represented by the provided string.
      Throws:
      de.gustavblass.commons.exceptions.IllegalArgumentException - If any of the parts specified by toBase64() are missing/invalid or if there are unexpected parts.
    • copy

      @NonNull public @NonNull HashingResult copy() throws IllegalStateException
      Creates a deep copy of this HashingResult object.
      Specified by:
      copy in interface de.gustavblass.commons.Copyable<HashingResult>
      Returns:
      A new HashingResult object with the same hash and argon2Configuration as this object.
      Throws:
      IllegalStateException - If the values of this object's fields are considered invalid by the constructor (should not happen).
    • equals

      @NonNull public @NonNull de.gustavblass.commons.FuzzyBoolean equals(@NonNull @NonNull HashingResult other)
      Compares all fields of this object to the fields of another HashingResult object.
      Parameters:
      other - The other HashingResult object to compare this object to.
      Returns:
      • FuzzyBoolean.TRUE if the hashes and the argon2Configuration of both objects are equal.
      • FuzzyBoolean.FALSE if the Argon2 configurations of both objects are equal, but the hashes are different.
      • FuzzyBoolean.MAYBE if the Argon2 configurations of both objects are different. If we compute the Argon2 hash of a string with two different Argon2 configurations, we will always get two different hashes. Therefore, if the two configurations differ, this does not permit us to draw any conclusions about the hash inputs.
      Implementation Note:
      This method intentionally does NOT override Object.equals(Object) because the different return type (FuzzyBoolean) would “clash” with the superclass method (which returns a regular boolean).