Search code examples
hashterminalapplescriptosx-mavericks

Generate a Salted Hash in Terminal


I want to make an AppleScript that generates a salted hash with Terminal. Is there a specific Terminal command that can generate a salted hash, preferably a secure one like SHA-512? If possible, I would like one that's a one-liner so I can use it with the do shell script command. I searched the web but didn't find a way to generate a salted hash in Terminal, just a regular one.

I'm running OS X Mavericks 10.9.5.


Solution

  • From what I understand, at least conceptually, what you're asking for requires 2 steps:

    • Obtain a random salt value.
    • Concatenate the salt value with the input text (password) and compute the hash for the combined value.

    For later verification, you'll have to store the salt along with the resulting hash.

    The following AppleScript handlers wrap shell functions that provide the requisite functionality - they're preceded by sample invocations.

    Disclaimer: my understanding of this field is limited, so take these functions with a grain of salt (ha!).

    The salt-generating function was gratefully adapted from this post.

    # Sample text to hash.
    set passwd to "somePassword"
    
    # Generate salt value with 10 chars, amounting to about a 64-bit value.
    set salt to generateSalt(10)
    
    # Compute hash from combined salt and input value.
    set hash to getSha512(salt & passwd)
    
    
    # SYNOPSIS
    #   getSha512(text)
    # DESCRIPTION
    #   Calculates and outputs TEXT's hash value using the SHA-512 (SHA-2) algorithm.
    #   Output is a 128-characters string composed of lowercase hexadecimal digits.
    #   To create a salted hash, obtain a salt with generateSalt() first and
    #   prepend it to the text to hash.
    # PREREQUISITES
    #   Requires either the sha512sum or the shasum utility. One or the other should be
    #   available on BSD/OSX and Linux systems.
    # EXAMPLE
    #   set salt to generateSalt(20)
    #   set hash to getSha512(salt & passwd)
    on getSha512(txt)
        do shell script "
    getSha512() {
      local -a shaCmd
      if command -v sha512sum &>/dev/null; then
        shaCmd=( sha512sum )
      elif command -v shasum  &>/dev/null; then
        shaCmd=( shasum -a 512 )
      else
        { echo 'ERROR: Cannot locate SHA-512-generating utility.' >&2; return 1; }
      fi
      # Invoke the SHA-generating command and output the first space-separated field.
      # (The subsequent fields indicate the mode and input filename.)
      \"${shaCmd[@]}\" <<<\"$1\" | cut -d' ' -f1
      return \"${PIPESTATUS[0]}\"
    }
    getSha512 " & quoted form of txt
    end getSha512
    
    # SYNOPSIS
    #   generateSalt(numChars)
    # DESCRIPTION
    #   Generates NUMCHARS random *printable* ASCII characters that can serve as 
    #   cryptographic salt. Due to the range of printable characters, each character
    #   returned contains ca. 6.55 bits of information.
    #   Thus, for instance, to get a 64-bit salt value, specify 10 for NUMCHARS.
    #   For a 128-bit value, specify 20.
    #   Use /dev/urandom as the source of random data.
    # PREREQUISITES
    #   File /dev/urandom as a source of random bytes.
    #   The `head` utility must support the -c option to extract a number of *bytes*.
    #   Both BSD/OSX and Linux systems fulfill these requirements.
    # EXAMPLE
    #   set salt to generateSalt(20) # get a ca. 128-bit salt value as 20 printable ASCII chars.
    on generateSalt(numChars)
        do shell script "
    generateSalt() {
      [[ -c /dev/urandom ]] || { echo 'ERROR: Random source /dev/urandom not available.' >&2; return 1; }
      LC_ALL=C tr -cd '!\"#$%&'\\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' < /dev/urandom | head -c $1
    }
    generateSalt " & numChars
    end generateSalt