Generate HMAC in Bash without revealing the secret

6,286

Re-directions are not part of the argument list.

This are considered safe from ps snooping:

cmd </file/key
cmd <<<"key"

Un-named pipes are also possible inside an script

echo "secret" | cmd

Example of secure password passing

So, this script is regarded as secure:

#!/bin/bash

read secretkey </dev/stdin

var="<?= hash_hmac(\"sha512\", \"$1\", \"$secretkey\"); ?>"

php7.1 <<<"$var"

The </dev/stdin could be replaced with a </dir/keyfile if the key could be stored in a file.

For the stdin version, use it as this:

./script "Message" <<<"secretkey"
Share:
6,286

Related videos on Youtube

Mark Howard
Author by

Mark Howard

Updated on September 18, 2022

Comments

  • Mark Howard
    Mark Howard almost 2 years

    I'd like to compute a HMAC-SHA512 digest in my bash script. So far I've found only this repeated many times over many different sites.

    echo -n message | openssl dgst -sha256 -hmac secret -binary >message.mac
    

    Apparently no one posting this realizes this is not the proper way to pass a secret string to a program as the secret will be visible in the process list for every other process running on the system. Is there any other way (perhaps with other tool) to easily make an HMAC in the shell with better interface for passing secrets?

    UPDATE

    I use the following tool (~/bin/hmac) now. It takes the key from the MACKEY environment variable.

    #!/usr/bin/env python3
    import hmac, sys, os
    
    key    = os.environ['MACKEY'].encode('utf-8')
    algo   = os.getenv('MACALGO', 'sha512')
    digest = hmac.new(key, digestmod = algo)
    
    while True:
        buf = sys.stdin.buffer.read(512)
        if not buf:
            break
        digest.update(buf)
    
    print(digest.hexdigest())
    

    Usage:

    echo -n message | MACKEY=foobar hmac
    
    • Jeff Schaller
      Jeff Schaller over 6 years
      Where is the secret now? (Just before the openssl call)
    • ilkkachu
      ilkkachu over 6 years
      -passin would support envvars or files, but I can't see anything like that for a MAC key... And no, -passin itself doesn't work.
    • RobotJohnny
      RobotJohnny over 6 years
      if you want to just hide the process from other users on the machine, you can remount /proc with hidepid=2: mount -o remount,rw,hidepid=2 /proc - don't forget to update fstab if you want /proc persistently mounted like that: proc /proc proc defaults,hidepid=2 0 0. NB: this will obviously not be useful in your situation if you're trying to hide the secret entirely from ps/top outputs for all users.
    • Mark Howard
      Mark Howard over 6 years
      @JeffSchaller In an environment variable where it got from file via cat keys | { read api_key; read api_secret }.
    • meuh
      meuh over 6 years
    • Neil McGuigan
      Neil McGuigan over 6 years
      run it on a single-user computer
    • Jeff Schaller
      Jeff Schaller over 6 years
    • done
      done over 6 years
      Read here that should never be used as you can list environment, in many ps implementations by ps -e, in the /proc/<PID>/environ file on Linux etc.