It's a good practice nowadays to verify a hash sum of downloaded tarballs via gnupg with the help of key servers. One of the most used keyserver in my experience is ha.pool.sks-keyservers.net (reports 5M added keys). Very often I get the following error with this key server gpg: keyserver receive failed: Address not available.
It's super annoying. Is this a problem of just sks-keyservers.net? If so, why people keep using it?
Seems to be a common error, the solution is to use multiple key servers. There's a simple script how you can do it gpg_verify:
#!/usr/bin/env bash
set -e
if [[ -n "${DEBUG}" ]]; then
set -x
fi
signature="${1}"
file="${2}"
found="";
declare -a keyservers=(
"ha.pool.sks-keyservers.net"
"hkp://keyserver.ubuntu.com:80"
"hkp://p80.pool.sks-keyservers.net:80"
"pgp.mit.edu"
)
export GNUPGHOME="$(mktemp -d)"
IFS=';' read -ra keys <<< "${GPG_KEYS}"
for key in "${keys[#]}"; do
for server in "${keyservers[#]}"; do
echo "Fetching GPG key ${key} from ${server}"
gpg --keyserver "$server" --keyserver-options timeout=10 --recv-keys "${key}" && found="yes" && break 2
done
done
if [[ -z "${found}" ]]; then
echo >&2 "error: failed to fetch GPG key ${GPG_KEYS}"
exit 1
fi
gpg --batch --verify "${signature}" "${file}"
rm -rf "${GNUPGHOME}" "${signature}"
Usage:
export GPG_KEYS=[YOUR GPG KEY]
gpg_verify archive.tar.gz.asc archive.tar.gz
Related
I have 2 GitHub account and I can't use the same public key for both accounts. I have already generated 2 ssh key
C:\Users\{User_Name}\.ssh\id_rsa
C:\Users\{User_Name}\.ssh\id_rsa_another
My question is, how I can use multiple ssh keys for Windows? On Linux, I just have to add by using ssh-add command, but on Windows, this command does not exist.
What have I done to make the other ssh key work, I have to change the id_rsa to id_rsa_temp and id_rsa_another to id_rsa. I know this is stupid.
First, ssh-add exists on Windows, as part of Git For Windows:
C:\Users\vonc>where ssh-add
C:\Program Files\Git\usr\bin\ssh-add.exe
It is needed for caching the passphrase protecting a private key (which is not always needed, since you can create a private key without passphrase)
Using different account, as commented, uses a %USERPROFILE%.ssh\config file, with in it:
Host gh1
Hostname github.com
User git
IdentityFile ~/.ssh/id_rsa
Host gh2
Hostname github.com
User git
IdentityFile ~/.ssh/id_rsa_another
You can test them with:
ssh -Tv gh1
ssh -Tv gh2
You should see a different "Welcome" message per key.
And the URL to use for cloning your repo would be:
gh1:user1/repo1
gh2:user2/repo2
If, and only if, your private ssh keys are encrypted (protected by a passphrase), then you need a .bashrc to start the SSH agent, and register your keys in it, effectively caching said keys.
See "Auto-launching ssh-agent on Git for Windows"
You can run ssh-agent automatically when you open bash or Git shell.
Copy the following lines and paste them into your ~/.bashrc (%USERPROFILE%/.bashrc) file in Git shell:
env=~/.ssh/agent.env
agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }
agent_start () {
(umask 077; ssh-agent >| "$env")
. "$env" >| /dev/null ; }
agent_load_env
# agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2=agent not running
agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)
if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
agent_start
ssh-add
ssh-add ~/.ssh/id_rsa_another
elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
ssh-add
ssh-add ~/.ssh/id_rsa_another
fi
unset env
You will have to enter the passphrase on the first start, then no more: said passphrase will be cached by the agent.
Finally, I found the solution
I have to use Git Bash because I can't use a regular Windows terminal when running this command
$ eval $(ssh-agent -s)
And then I can add the SSH key by running this command
$ ssh-add C:/Users/{User_Name}/.ssh/id_rsa_another
We must use the forward-slash for the path
I'm writing a script that uses gpg to encrypt a file. During testing/experimentation with gpg from the command-line, I found some odd behavior. This works perfectly fine:
$ cat myFile.txt | gpg --encrypt -r 'jdoe#gmail.com'
gpg: B2D17635: There is no assurance this key belongs to the named user
pub 4096R/B2D17635 2016-01-31 John Doe (I am now a real person.) <jdoe#gmail.com>
Primary key fingerprint: B17F 98BA 1DA9 3FE1 A08F 1443 509D 87ED 32AF 2078
Subkey fingerprint: BB63 42DA 8FAD 194A E1C9 1F6D 39BA 73B9 B2D1 7635
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) y
�
Nϴ��[�mDZ.#�Bc���J������z�{p���%
<GIBBERISH SNIPPED>
i�)��/&N��t�Z�8�#�I<�Bq�!�K?�vQ�I�H6&+��(
But I don’t like that because I interactively had to type ‘y’. I would like it to assume “yes” and do the encryption without requiring any interactivity. So I ran the following command with the --batch and --yes switches. Why did it fail?
$ cat myFile.txt | gpg --encrypt --batch --yes -r 'jdoe#gmail.com'
gpg: B2D17635: There is no assurance this key belongs to the named user
gpg: [stdin]: encryption failed: unusable public key
The error you're receiving from GnuPG is because the public key isn't trusted/verified within your keyring. Because your OP stated that your running tests you may want to check out the code within a helper script written for my own experiments, GnuPG_Gen_Key.sh, specifically the functions copied/modded below.
#!/usr/bin/env bash
Var_gnupg_import_key="${1}"
Var_gnupg_import_key_trust="${2}"
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 "# ${Var_script_name} 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 "# ${Var_script_name} 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 "# ${Var_script_name} reports: error no public key [${_gnupg_import_key}] as file or on key server [${Var_gnupg_key_server}]"
fi
else
echo "# ${Var_script_name} reports: error no public key [${_gnupg_import_key}] as file or on key server [${Var_gnupg_key_server}]"
fi
fi
}
One can either trust the public key with above or use the following command to have GnuPG ignore trust issues.
gpg --armor --always-trust -r 'jdoe#gmail.com' -e myFile.txt -o myFile.txt.gpg
Note I've added the --armor option because the output in the OP looks to have missed that based off the snipped output.
You have to add --always-trust to your command:
echo "test" | gpg --batch --yes --always-trust --encrypt --armor -r "mail#example.com"
Probably better than using --always-trust is to sign the keys your are relying on once with your private key.
Then gpg won't ask again.
Also you encrypted standard input, so the ciphertext will be sent to standard output.
In most cases you want to use option --armor to produce ASCII output.
I want to create a shell script and I haven't worked with it before.
There is a command for gpg:
gpg --keyserver SERVER --recv-keys KEY
The problem is that I don't want to run this command if key has been already added. Is there any method to check that key exists in keys list?
Thank you!
Run gpg --list-keys [key-id] (or the abbreviated command -k), which will have a return code of 0 (success) if a matching key exists, or something else (failure) otherwise. Don't list all keys and grep afterwards as proposed by others in the comments, this will get horribly slow for larger numbers of keys in the keyring. Run
gpg --list-keys [key-id] || gpg --keyserver [server] --recv-keys [key-id]
to fetch missing keys, possibly discarding the first gpg call's output (gpg --list-keys [key-id] >/dev/null 2>&1 || ...), as you're only interested in the return code.
Be aware that
updating keys from time to time might be a reasonable thing to do to fetch revocations
especially short key IDs should never be used, use the whole fingerprint if possible.
You can do:
[[ $(gpg --list-keys | grep -w KEY) ]] && echo "Key exists" ||
gpg --keyserver SERVER --recv-keys KEY
Additional (for apt keyring):
[[ $(apt-key list | grep -w KEY) ]] && echo "Key exists" ||
gpg --keyserver SERVER --recv-keys KEY
If apt-key is available
The correct way to do it is running the following command
gpg --keyserver hkp://keyserver.ubuntu.com -k [your-key-id]
I want to create an auto GnuPG key generation script for one person atm who, although they run ubuntu, does not feel comfortable using the CLI. In addition, someone else manages their computer, keeping it up to date and in good running order, so they do not have root/sudo access either. And I would really like to try and avoid doing as much as possible with instructions over the phone... been there too many times to know what a PITA that can be!
So I whipped up this script borrowing heavily from an example I found on the gnupg.org forums (I think?). But it does not seem to do anything once the gpg --gen-key --batch command is run no matter how much mouse activity is generated in 3 or 4 minutes. All the echo statements btw are just a temporary means to indicate script progress, which isn't very far atm.
#!/bin/bash
# First run give your server some work, otherwise gpg won't be able to generator random bytes.
#sudo rngd -r /dev/urandom
#no sudo so:
echo -e "\nYou need to begin moving your mouse continuously and in random patterns for as long as it takes to generate a new key. This could take a minute or two, so be patient and just keep moving the mouse.\n"
echo -e "\ngpg --gen-key --batch\n"
gpg --batch --gen-key
%echo Generating a default key
Key-Type: default
Key-Length: 2048
Subkey-Type: default
Name-Real: Firstname Lastname
Name-Comment: No comment
Name-Email: user#domain.com
Expire-Date: 0
Passphrase: abcde
%pubring foo.pub
%secring foo.sec
# Do a commit here, so that we can later print "done" :-)
%commit
%echo done
# kill the rngd task.
#sudo service rng-tools stop
echo -e "\ngpg -k\n"
gpg -k
# get key id for newly created passkey
echo -e "\nkId=$(gpg -k Firstname|grep pub|sed -r 's/^pub[ ]*2048R\/([A-Z0-9]{8,})[ ]*.*$/\1/')\n" #; echo "\$kId: ${kId}"
kId=$(gpg -k Firstname|grep pub|sed -r 's/^pub[ ]*2048R\/([A-Z0-9]{8,})[ ]*.*$/\1/') ; echo -e "\n\$kId: ${kId}\n"
# set key as the default key (if desired) by entering this line in your ~/.bashrc
echo -e "\nexport GPGKEY=$kId\n"
export GPGKEY="$kId"
# restart the gpg-agent and source your .bashrc again
echo -e "\nkillall -q gpg-agent\n"
killall -q gpg-agent
eval $(gpg-agent --daemon)
source ~/.bashrc
#create revocation cert
echo -e "\ngpg --output revoke.asc --gen-revoke $GPGKEY\n"
gpg --output revoke.asc --gen-revoke $GPGKEY
# send public key to keyserver
echo -e "\ngpg --send-keys --keyserver keyserver.ubuntu.com $GPGKEY\n"
#gpg --send-keys --keyserver keyserver.ubuntu.com $GPGKEY
I wonder if anyone can see any obvious problems or omissions feeding 'gpg' required key details?
I get the same thing even if I run the script with the sudo rngd -r /dev/random command that I need to bypass for the intended user (no sudo access).
So I guess the prob is in the key params I want to pass to gpg, but I have cross referenced them with the man page and can't seem to find what the problem might be. It is funny though that gpg does not return the error.
With batch key generation, GnuPG expects the creation commands in a file, compare with the GnuPG manual page on batch key generation.
cat <<EOT >batch-cmds
%echo Generating a default key
Key-Type: default
Key-Length: 2048
Subkey-Type: default
Name-Real: Firstname Lastname
Name-Comment: No comment
Name-Email: user#domain.com
Expire-Date: 0
Passphrase: abcde
%pubring foo.pub
%secring foo.sec
# Do a commit here, so that we can later print "done" :-)
%commit
%echo done
EOT
gpg --batch --gen-key batch-cmds
Consider the security implications of storing the passwords in a file on the hard disk. I'm not sure if you can also pipe the contents directly into GnuPG instead of storing them to a file. Try something like this:
gpg --batch --gen-key <<EOT
%echo Generating a default key
Key-Type: default
Key-Length: 2048
Subkey-Type: default
Name-Real: Firstname Lastname
Name-Comment: No comment
Name-Email: user#domain.com
Expire-Date: 0
Passphrase: abcde
%pubring foo.pub
%secring foo.sec
# Do a commit here, so that we can later print "done" :-)
%commit
%echo done
EOT
I have several hundred gpg encrypted files in a directory, of the format filename.xyz.gpg where "xyz" is some arbitrary extension. I need to decrypt all of the files to generate filename.xyz decrypted in such a way that I don't have to manually enter the password for each file.
I have tried the following for directory "Testing":
for file in 'ls Testing'; do (echo <password>|gpg --passphrase-fd 0 -d $file
--output $file.decrypted);
I just wind up with a command prompt >, and nothing happens.
What is the matter with my syntax? Is there some more efficient way to do this without a bash shell loop?
gpg can decrypt multiple files so you shouldn't need to write a loop.
Try the following. You will need to enter your password once.
gpg --passphrase-fd 0 --decrypt-files *.gpg
As it is said in the manual you need to add --batch option:
--passphrase-fd n
Read the passphrase from file descriptor n. Only the first line will be read from file descriptor n. If you use 0 for n, the passphrase will be read from
STDIN. This can only be used if only one passphrase is supplied. Note that this passphrase is only used if the option --batch has also been given. This is
different from gpg.
--passphrase string
Use string as the passphrase. This can only be used if only one passphrase is supplied. Obviously, this is of very questionable security on a multi-user sys‐
tem. Don't use this option if you can avoid it. Note that this passphrase is only used if the option --batch has also been given. This is different from
gpg.
You can have either of these two forms:
echo "passphrase" | gpg --passphrase-fd 0 --batch -d --output "decrypted.file" "file.gpg"
Or simpler:
gpg --passphrase "passphrase" --batch -d --output "decrypted.file" "file.gpg"
You can try a script like this to extract your files:
#!/bin/bash
read -rsp "Enter passphrase: " PASSPHRASE
for FILE in *.*.gpg; do
echo "Extracting $FILE to ${FILE%.gpg}."
echo "$PASSPHRASE" | gpg --passphrase-fd 0 --batch -d --output "${FILE%.gpg}" "$FILE"
done
I had success with
gpg --decrypt-files *.gpg
cf. https://serverfault.com/a/388068/103585
I had success with gpg --decrypt-files *
but not *.gpg
It worked with below commands for me:
For single file:
gpg --decrypt --input C:\PGPFiles\[encryptedfilename.pgp] --passphrase [yourpassphrase]
For multiple files:
gpg --decrypt --input C:\PGPFiles\* --passphrase [yourpassphrase]