Search code examples
unixgnupgcatpassword-encryption

GPG decrypting/encrypting string in memory only


Background:

I have a GPG encrypted secret that must not be written to file unencrypted. Let say that it lives at ~/.secrets/.mysecret.gpg.

Running gpg ~/.secrets/.mysecret.gpg unencrypts the .mysecret.gpg and saves it to file at .mysecret (unacceptable). Running gpg -d ~/.secrets/.mysecret.gpg prints the decrypted secret only (thank you JustinC).

To avoid the stderr and to encode it in base64 for my use purpose, I wrote this shell function as a convenience method:

keyreader() {
  local gpg_file=$1
  echo -n "$(gpg -d "$gpg_file" 2> /dev/null)" | base64
}

Running keyreader ~/.secrets/.mysecret.gpg, after entering the password for the encrypted secret, it prints out the base64 encoded, decrypted secret, no output file.

Questions:

  1. When gpg -d ~/.secrets/.mysecret.gpg is run, does gpg write a tmp file that would include the unencrypted .mysecret?

  2. Why does gpg not output a file, .mysecret, when I use the above syntax? (ANSWER: the -d flag was used, again thank you JustinC).

  3. Assuming I use the appropriate $HISTIGNORE identifier before running the command, how can I encrypt a string from the command line to a .gpg AES256 encrypted file without having first written it unencrypted to file?

For Q3, something like:

$ echo "secret info" | gpg --cipher-algo AES265 -c -o secrets_file.txt.gpg

instead of:

$gpg --cipher-algo AES265 -c secrets_file.txt


Solution

  • Again, @JustinC, thank you for your answer.

    For completeness, here is my solution for encrypting/decrypting a string in memory only:

    encryption:

    # notice the space before echo here
    # it is the default $HISTIGNORE flag which can be set in the ~/.bashrc
    # it keeps this line from being written to the ~/.bash_history file
    
     echo -n 'your secrets here' | gpg -c > ~/.secrets/.mysecret.gpg
    
    # Enter passphrase:
    

    decryption:

    # 2> /dev/null: skip printing strerr
    
    gpg -d ~/.secrets/.mysecrets.gpg 2> /dev/null
    

    NB: If you get the error "inappropriate ioctl for device", you may be running on WSL and this may help you:

    # https://d.sb/2016/11/gpg-inappropriate-ioctl-for-device-errors
    
    echo -e "use-agent\npinentry-mode loopback" >> ~/.gnupg/gpg.conf
    echo "allow-loopback-pinentry" >> ~/.gnupg/gpg-agent.conf
    echo RELOADAGENT | gpg-connect-agent