Most other GPG commands allow you to use --batch mode, but it doesn't appear to be the case when trying to edit a passphrase.
You have to run gpg --edit-key user
Which opens up an interactive GPG prompt.
This isn't going to work in my case as I need the ability to change the passphrase without the command line interaction.
The closest thing I've found is
gpg --batch --passphrase-fd 0 --status-fd 2 --command-fd 0 --edit-key
But this just gives me an invalid command after I enter the existing passphrase.
Any suggestions greatly appreciated.
I just encountered this problem while writing a key-gen script and came up with a solution!
A few things to note:
Lots of folks point towards --batch because --passphrase* requires it. In this case we'll be working with STDIN (as specified by --command-fd 0) and thus want to pass raw input rather than messing with the GnuPG functions.
While --status-fd 2 is useful for debugging, it isn't necessary. That said, including it lead me to the insight that --change-passphrase is requesting two, and only two, entries.
Set --pinentry-mode loopback to avoid having a prompt asking for your passphrase.
The solution is to pipe (or redirect) both the original and new passphrases to STDIN where GnuPG can processes them. While my initial code used (echo ..;echo ..)|gpg .. it is better to use a here-document.
# Using GnuPG to change PGP key passphrase non-interactively
gpg --command-fd 0 --pinentry-mode loopback \
--change-passphrase ${KEYID} <<END
${OLD_PASS}
${NEW_PASS}
END
Just set up the variables and that should work. Enjoy!
I'm trying to write a parallel compress / encrypt backup script for archiving
using GNU parallel, xz and GnuPG. The core part's of script is:
tar --create --format=posix --preserve-permissions --same-owner --directory $BASE/$name --to-stdout . \
| parallel --pipe --recend '' --keep-order --block-size 128M "xz -9 --check=sha256 | gpg --encrypt --recipient $RECIPIENT" \
| pv > $TARGET/$FILENAME
Without GnuPG encryption, it works great (uncompress and untar works),
but after adding parallel encryption, it's fail to decrypt with below error:
[don't know]: invalid packet (ctb=0a)
gpg: WARNING: encrypted message has been manipulated!
gpg: decrypt_message failed: Unexpected error
: Truncated tar archive
tar: Error exit delayed from previous errors.
Because uncompressed size is as same as gnu parallel's block size(around 125M), I assume that it's related GnuPG's support of partial block encryption. How can I solve this problem?
FYI
Another parallel gpg encrption issue about random number generation
https://unix.stackexchange.com/questions/105059/parallel-pausing-and-resuming
Pack
tar --create --format=posix --preserve-permissions --same-owner --directory $BASE/$name --to-stdout . |
parallel --pipe --recend '' --keep-order --block-size 128M "xz -9 --check=sha256 | gpg --encrypt --recipient $RECIPIENT;echo bLoCk EnD" |
pv > $TARGET/$FILENAME
Unpack
cat $TARGET/$FILENAME |
parallel --pipe --recend 'bLoCk EnD\n' -N1 --keep-order --rrs 'gpg --decrypt | xz -d' |
tar tv
-N1 is needed to make sure we pass a single record at a time. GnuPG does not support decrypting multiple merged records.
GnuPG does not support concatenating multiple encryption streams and decrypting them at once. You will have to store multiple files, and decrypt them individually. If I'm not mistaken, your command even mixes up the outputs of all parallel instances of GnuPG, so the result is more or less random garbage.
Anyway: GnuPG also takes care of compression, have a look at the --compression-algo option. If you prefer to use xz, apply --compression-algo none so GnuPG does not try to compress the already-compressed message again. Encryption has massive support by CPU-instructions ourdays, xz -9 might in fact be more time intensive than encryption (although I did not benchmark this).
that's mainly a gpg issue. gpg does not support multithreading and probably
never will. you can search the web about the why.
it even got worse with gpg v2: you cannot even run multiple gpg v2 instances in
parallel because they all lock the gpg-agent which is now doing all the
work........ maybe we should look for an alternative when doing mass encryption.
https://answers.launchpad.net/duplicity/+question/296122
EDIT: No. It is possible to run multiple gpg v2 instances at the same time, without any problem with the gpg-agent.
I am currently writing a batch script to automate signing and encrypting files, on GnuPG version 2.0.30.
Can someone explain why the following will not work on my Windows machine:
echo "passphrase"| gpg2 --batch --yes --always-trust --passphrase-fd 0 -es -r "Public key for encryption" "Path of file to encrypt"
To my knowledge, this should be piping the output of echo (my passphrase) as the input of --passphrase-fd 0 (0 operating on STDIN handle of course). I can't seem to get this to work, and wasn't sure if it was my code, or if it's just an issue running this on Windows.
Whenever I execute this command, I get
"no default secret key: Bad passphrase"
"sign+encrypt failed: Bad passphrase"
As a workaround, I was able to use redirection operater < and passed the filepath to my passphrase, still using the STDIN handle (0):
gpg2 --batch --yes --always-trust --passphrase-fd 0 -es -r "Public key for encryption" "Path of file to encrypt" < "Filepath to passphrase"
I realize it's bad practice to store a passphrase in a local file, and may consider removing the signature altogether, but for my own sake, I want to better understand why this won't work using piping (on Windows).
Thanks!
I'm using a script to pack and encrypt archives in order to backup them in cloud storage.
It generates shell commands like this:
cd /vault/backup/pictures; tar cf - vacation-201309 | xz -3 | gpg --symmetric --cipher-algo TWOFISH --digest-algo SHA512 --no-secmem-warning --yes --batch --passphrase-file /vault/keys/back_keyfile -o /vault/backup/upload/vacation-201309.tar.xz.gpg
TWOFISH is a 256-bit cipher which means, that it can only use a keyfile not bigger than,
openssl rand -base64 256:
3zXeZC/XWC1h1lxre88gzkhCZqk6tV7YKCg9HiKDLrooEDYkvwYXQ5LMBLSFdpYr
c2KAP10aq6pfEi4YeL7llQXfd47qXsEDi8nOpBpPRALxv2NYE4qjZC3sTPe+d1ue
cbFM18BmxHN0094YotLBD+6cQIfZyU8GVLLHx8iH2jf48+7QuXigqWW1oT33BPbQ
zrlND50ZFeGNYo7woIRpSvt8KeBm8t75jVEqXIzA2Zei0r9Xsx0mu828t0wZ6mGL
hkj4B5M56eJzFUCFG207Mf/bXvV5X7Pz6W72Y8nhjAtkumdAsEb0Vc0iIHJ64mfH
XWEfs/1T3n2F8/kxASIvPQ==
At least that's how I understand it.
My question is, how would GPG behave, if I pass a bigger key file to it like
openssl rand -base64 512:
P0MzGpZItSu6fKObtJvAx1fLRxPBK/pOIjR9Yv+mCrHLlit7ksHOjif6ln32lXl3
8g/zxdQc39kanAproaOzZ1ulebxbfK1Bi6/OfwhdP1HF61nWBZb03TDtdNNXEDFW
9lAN6kHUUctpY9PhFCv2AmoKSKzv1HsAGkrhqslO4E+3sIlGgVLg69qKHE9yQJSX
s5xhXKTcAcaVZ++HwuTTvIduf3sc2J+BEDzpqrAwES2hV5gFwnFFA6G0md31VwEI
9wf22p07qbOrRryV/0WZUNZfOuZ5g/JgrqhRgq53lK0VHvyRkNjMlx7BW4n3Y/0y
5Lgve8Q89Cx5jwbxPcBnXW5h4SWLFa8bSLrGrn/eDH+F1mA5BbU+3IrBdLgivz0u
Unr+jLD3FbBOv/8jRAyp/iOwMmOw9welTu/mcEEa20gyupeJXxAZaVrNfWdWVORi
PdjW5vR9Rn/NLh6fV46+E39dgTn4TBp/v9h+LZpiVK3nNkry+as9vH73o+nFIe8Q
H/UkchDqmIBLntKc9rBZQrkx8NOzruoWGJoFE/Wb23AHN7RNyYgVgvZTy5QWhILz
CW/mzwMQYAuLbFfnY4cgDs9zLMo4OqFGUmbgbnXO9KbYgsplU2aps9JoOjyWCchm
uWYRNAGWrgdfl8vIaxMz1WUwWJFDxyNrANPRiPFQTUg=
Will it just take the first 256 characters and ignore the rest?
You are using the random as input as a passphrase. Only the first line is used. So you are not generating the key at all, the key is generated using the S2K algorithms, using just the first line.
Note that a 256 bit key does not consist of 256 "characters" or bytes.
I am trying to add my GPG public key as a part of our appliance installation process. The purpose of it to encrypt any important files like logs before admin pulling them into his local using admin portal and then decrypt them using private key.
The plan is to export public key into a file and make appliance installation process to import it using gpg --import command. But I realized, the key is needed to be trusted/signed before do any encryption.
How to make this key is trusted without any human intervention at the time of installation?
Btw, our appliance os is ubuntu vm and we use kickstart to automate.
Advance thanks for all help.
Your question is really "How do I encrypt to a key without gpg balking at the fact that the key is untrusted?"
One answer is you could sign the key.
gpg --edit-key YOUR_RECIPIENT
sign
yes
save
The other is you could tell gpg to go ahead and trust.
gpg --encrypt --recipient YOUR_RECIPIENT --trust-model always YOUR_FILE
Coincidentally I have a similar situation to the OP - I'm trying to use public/private keys to sign and encrypt firmware for different embedded devices. Since no answer yet shows how to add trust to a key you already have imported, here is my answer.
After creating and testing the keys on a test machine, I exported them as ascii:
$ gpg --export -a <hex_key_id> > public_key.asc
$ gpg --export-secret-keys -a <hex_key_id> > private_key.asc
Then secure-copied and imported them to the build server:
$ gpg --import public_key.asc
$ gpg --import private_key.asc
Important: add trust
Now edit the key to add ultimate trust:
$ gpg --edit-key <user#here.com>
At the gpg> prompt, type trust, then type 5 for ultimate trust, then y to confirm, then quit.
Now test it with a test file:
$ gpg --sign --encrypt --yes --batch --status-fd 1 --recipient "recipient" --output testfile.gpg testfile.txt
which reports
...
[GNUPG:] END_ENCRYPTION
without adding trust, I get various errors (not limited to the following):
gpg: There is no assurance this key belongs to the named user
gpg: testfile.bin: sign+encrypt failed: Unusable public key
There's an easier way to tell GPG to trust all of its keys by using the --trust-model option:
gpg -a --encrypt -r <recipient key name> --trust-model always
From the man page:
--trust-model pgp|classic|direct|always|auto
Set what trust model GnuPG should follow. The models are:
always Skip key validation and assume that used
keys are always fully trusted. You generally
won't use this unless you are using some
external validation scheme. This option also
suppresses the "[uncertain]" tag printed
with signature checks when there is no evidence
that the user ID is bound to the key. Note that
this trust model still does not allow the use
of expired, revoked, or disabled keys.
Add trusted-key 0x0123456789ABCDEF to your ~/.gnupg/gpg.conf replacing the keyid. This is equivalent to ultimately trusting this key which means that certifications done by it will be accepted as valid. Just marking this key as valid without trusting it is harder and either requires a signature or switching the trust-model to direct. If you are sure to only import valid keys you can simply mark all keys as valid by adding trust-model always. In the latter case ensure that you disable automatic key retrieval (not enabled by default).
This worked for me:
Trying to encrypt a file responds with this:
gpg -e --yes -r <uid> <filename>
It is NOT certain that the key belongs to the person named
in the user ID. If you *really* know what you are doing,
you may answer the next question with yes.
Use this key anyway? (y/N)
That causes my shell script to fail.
So I:
$gpg --edit-key <uid>
gpg> trust
Please decide how far you trust this user to correctly verify other
users' keys (by looking at passports, checking fingerprints from
different sources, etc.)
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
Please note that the shown key validity is not necessarily correct
unless you restart the program.
gpg> quit
Now the encrypt works properly.
Based on #tersmitten's article and a bit of trial and error, I ended up with the following command line to trust all keys in a given keyring without user interaction. I use it for keys used with both StackEschange Blackbox and hiera-eyaml-gpg:
# The "-E" makes this work with both GNU sed and OS X sed
gpg --list-keys --fingerprint --with-colons |
sed -E -n -e 's/^fpr:::::::::([0-9A-F]+):$/\1:6:/p' |
gpg --import-ownertrust
Personally, I prefer a solution which stores the results in the trustdb file itself rather than depends on user environment outside the shared Git repo.
Here's a trick I've figured out for automation of GnuPG key management, hint heredoc + --command-fd 0 is like magic. Below is an abridged version of one of the scripts that's been written to aid in automation with GnuPG.
#!/usr/bin/env bash
## First argument should be a file path or key id
Var_gnupg_import_key="${1}"
## Second argument should be an integer
Var_gnupg_import_key_trust="${2:-1}"
## Point to preferred default key server
Var_gnupg_key_server="${3:-hkp://keys.gnupg.net}"
Func_import_gnupg_key_edit_trust(){
_gnupg_import_key="${1:-${Var_gnupg_import_key}}"
gpg --no-tty --command-fd 0 --edit-key ${_gnupg_import_key} <<EOF
trust
${Var_gnupg_import_key_trust}
quit
EOF
}
Func_import_gnupg_key(){
_gnupg_import_key="${1:-${Var_gnupg_import_key}}"
if [ -f "${_gnupg_import_key}" ]; then
echo "# ${0##*/} reports: importing key file [${_gnupg_import_key}]"
gpg --no-tty --command-fd 0 --import ${_gnupg_import_key} <<EOF
trust
${Var_gnupg_import_key_trust}
quit
EOF
else
_grep_string='not found on keyserver'
gpg --dry-run --batch --search-keys ${_gnupg_import_key} --keyserver ${Var_gnupg_key_server} | grep -qE "${_grep_string}"
_exit_status=$?
if [ "${_exit_status}" != "0" ]; then
_key_fingerprint="$(gpg --no-tty --batch --dry-run --search-keys ${_gnupg_import_key} | awk '/key /{print $5}' | tail -n1)"
_key_fingerprint="${_key_fingerprint//,/}"
if [ "${#_key_fingerprint}" != "0" ]; then
echo "# ${0##*/} reports: importing key [${_key_fingerprint}] from keyserver [${Var_gnupg_key_server}]"
gpg --keyserver ${Var_gnupg_key_server} --recv-keys ${_key_fingerprint}
Func_import_gnupg_key_edit_trust "${_gnupg_import_key}"
else
echo "# ${0##*/} reports: error no public key [${_gnupg_import_key}] as file or on key server [${Var_gnupg_key_server}]"
fi
else
echo "# ${0##*/} reports: error no public key [${_gnupg_import_key}] as file or on key server [${Var_gnupg_key_server}]"
fi
fi
}
if [ "${#Var_gnupg_import_key}" != "0" ]; then
Func_import_gnupg_key "${Var_gnupg_import_key}"
else
echo "# ${0##*/} needs a key to import."
exit 1
fi
Run with script_name.sh 'path/to/key' '1' or script_name.sh 'key-id' '1' to import a key and assign a trust value of 1 or edit all values with script_name.sh 'path/to/key' '1' 'hkp://preferred.key.server'
Encryption should now be without complaint but even if it does the following --always-trust option should allow encryption even with complaint.
gpg --no-tty --batch --always-trust -e some_file -r some_recipient -o some_file.gpg
If you wish to see this in action, then check the Travis-CI build logs and how the helper script GnuPG_Gen_Key.sh is used for both generating and importing keys in the same operation... version two of this helper script will be much cleaner and modifiable but it's a good starting point.
This oneliner updates the trustdb with the ownertrust values from STDIN -- by extracting the fingerprint to the format required by --import-ownertrust flag.
This flag, as detailed on gpg man page, should be used In case of a severely damaged trustdb and/or if you have a recent backup of the ownertrust values, you may re-create the trustdb.
gpg --list-keys --fingerprint \
| grep ^pub -A 1 \
| tail -1 \
| tr -d ' ' \
| awk 'BEGIN { FS = "\n" } ; { print $1":6:" }' \
| gpg --import-ownertrust
One way to trust imported gpg keys:
gpg --import <user-id.keyfile>
fpr=`gpg --with-colons --fingerprint <user-id> |awk -F: '$1 == "fpr" {print$10; exit}'`
gpg --export-ownertrust && echo $fpr:6: |gpg --import-ownertrust
here, I assume that you import a key with the <user-id> from <user-id.keyfile>. The second line only extracts fingerprint, you can drop it if you know the fingerprint beforehand.
I think, I figured way to do this.
I used 'gpg --import-ownertrust' to export my trust db into a text file then removed all of my keys from it except public key I needed to push. And then imported my public key and edited owner-trust file on to server. This seems like working.
Now I am having trouble implementing these steps in Kickstart file:-(
With powershell, here is how to trust john.doe#foo.bar (adapted from #tersmitten blog post):
(gpg --fingerprint john.doe#foo.bar | out-string) -match 'fingerprint = (.+)'
$fingerprint = $Matches[1] -replace '\s'
"${fingerprint}:6:" | gpg --import-ownertrust
Note: using cinst gpg4win-vanilla
There is a way to autotrust key using --edit-key, but without getting into interactive shell (so can be automated in script). Below is a sample for windows:
(echo trust &echo 5 &echo y &echo quit) | gpg --command-fd 0 --edit-key your#email.com
Unix based:
echo -e "5\ny\n" | gpg --homedir . --command-fd 0 --expert --edit-key user#exaple.com trust;
For more info read this post. It details if you are creating more than one key.
I used following script for import key:
#!/bin/bash
function usage() {
cat >&2 <<EOF
Usage: $0 path_of_private_key
Example: gpg_import.sh ~/.ssh/my_gpg_private.key
Import gpg key with trust.
EOF
exit 1
}
[[ $# -lt 1 ]] && usage
KEY_PATH=$1
KEY_ID=$(gpg --list-packets ${KEY_PATH}/${GPG_PRIVATE_KEY} | awk '/keyid:/{ print $2 }' | head -1)
gpg --import ${KEY_PATH}/${GPG_PRIVATE_KEY}
(echo trust &echo 5 &echo y &echo quit) | gpg --command-fd 0 --edit-key $KEY_ID
I am using windows with gpgwin4.0.2 installed.
Open the Kleopatra (the GUI) -> Certificates -> Right Click -> Certify. Once the has been certify, this message will not show any.
Try this :
(echo trust &echo 5 &echo y &echo quit &echo save) | gpg --homedir 'gpgDirectory/' --batch --command-fd 0 --edit-key 'youKey'
--homedir : not required