I'm I have two public and private key pairs that I am experimenting with. Let's call them:
private-recipient.asc
public-recipient.asc
private-sender.asc
public-sender.asc
I am trying to encrypt and decrypt a message with gpg without "importing" any keys. I seem to be able to encrypt it with the receiver's public key directly from a file, but can only sign it by importing the signers private key.
This works:
gpg --import private-recipient.asc
gpg --import private-sender.asc
# and then trust them maybe
echo HELLO STACK OVERFLOW | gpg --encrypt --recipient-file public-recipient.asc --armor --sign --local-user sender#example.com > encrypted-message.txt
cat encrypted-message | gpg --decrypt
which says HELLO STACK OVERFLOW and a bunch of info about the key
However, I would like to run several independent experiments in different directories... so I am hoping to do something more like this:
## CAUTION MOST PARAMS IN HERE ARE MADE UP
echo HELLO STACK OVERFLOW | gpg --encrypt --armor --recipient-file public-recipient.asc --sign-with-key private-sender.asc > encrypted-message.txt
cat encrypted-message.txt | gpg --descrypt --recipient-private-key private-recipient.asc --check-signature public-sender.asc
But as far as I can tell, most of those arguments don't exist. Is there a way to do it without importing any keys?
I've decrypted a file successfully using:
gpg --encrypt --recipient user#company.com myfile.txt
If I run the command below, I'm prompted for a passphrase, and decryption works:
gpg --output decrypted_myfile.txt -decrypt myfile.txt.gpg
I can't seem to get any form of non-interactive decryption working. The closest I've come is:
gpg --decrypt --batch --passphrase MYPASSPHRASE myfile.txt.gpg
This gives me:
gpg: encrypted with 2048-bit RSA key, ID F6CF3C25, created 2016-03-17
"Company_20210316 (Incoming Files) <user#company.com>"
gpg: public key decryption failed: Bad passphrase
gpg: decryption failed: No secret key
Is there a different way to do it?
Having error like:
gpg: decryption failed: No secret key
simply means that you don't have a private or secret key in your gpg keyring. You may want to check first if:
gpg --list-secret-keys if it has a private key there and if not,
Import it and then trust it.
To trust, use:
gpg --key-edit <yourKey> then "trust" then "5" then "quit"
To get your keyID run:
gpg --edit-key <yourKey> then
On the first line you'll see: "Private key available"
Then two sub-keys on the left of the fist, you'll see similar to:
sec rsa2048/E7E43C5C844E2917
and the part on a right after slash - will be your
E7E43C5C844E2917
So to explicitly export from where it was generated, the key to a file, you need to use that like this:
gpg --export-secret-keys --armor E7E43C5C844E2917>yourSecretKey.asc
This will create a secret key in a file ONLY, unlike if you use keyname in the export call. Then it will contain more than that.
Then to import use:
gpg --import yourSecretKey.asc
Then check your key in the list updated. Add a trust if needed.
Then line to decrypt copied from terminal of my MAC and tested works, w/ no prompt:
gpg --batch --passphrase MyPassphrase -o test.tt7 -d CE.txt.gpg
NOTE that: -d is the same as --decrypt and
-o the same as --output
And the value of the passphrase is the actual value I used in my test to decrypt the above and not the variable. The same created during the time key generated, and actual recommendation is to use a longer set of characters but actually any number is accepted.
Having error like: gpg: decryption failed: No secret key simply means that you don't have a private or secret key in your gpg keyring. You may want to check first if gpg -k (same as gpg --list-keys) has a private key there and import it and then trust it,
To add trust, use "1 to 5":
gpg --key-edit <yourKey>
then trust then 5 then `quit
To get your keyID run:
gpg --edit-key <yourKey>
then first line you'll see: Private key available
then two sub-keys on the left of the fist you'll see
sec rsa2048/E7E43C5C844E2917
and the part on a right after slash - will be your <keyID> E7E43C5C844E2917
so, to explicitly export from where it was generated, the key to a file you need to use that like:
gpg --export-secret-keys --armor E7E43C5C844E2917>yourSecretKey.asc
this will create secret key in a file ONLY, unlike if you use keyname in the export call then it will contain more than that.
Then to import use:
gpg --import E7E43C5C844E2917
then check your key in the list updated. Add trust if needed.
Then line to decrypt copied from terminal of my MAC and tested works, w/ no prompt:
gpg --batch --passphrase MyPassphrase -o test.tt7 -d CE.txt.gpg
NOTE that: -d is the same as --decrypt just like -o is the same as --output
You can try this command:
gpg --output File.txt --batch--passphrase-fd YourPassword --decrypt file.pgp
I generated a key pair using GPG by following command in Debian 8.
gpg --gen-key
I left the passphrase step of key generation empty and just hit the Enter key. After that, I exported private and public key using following commands.
gpg --export-secret-key -a "X" > private.key
gpg --export-key -a "X" > public.key
Then I tried to encrypt a folder using the private key. It was successful and without asking any passphrase the encrypted file was generated.
But When I transferred the public key to another computer with Ubuntu OS 14.04 and import it using following command, gpg requested passphrase. Even, by giving empty passphrase to gpg, it says that passphrase is incorrect.
gpg --import public.key
Furthermore, when I imported the private key in the second computer for encryption, it asks me passphrase again.
Does anyone have any idea what is the problem?
There is no need to export and import keys. Just copy the key files located in ~/.ssh/ on your source machine to the other system.
It was because there exist other keyring in second system before. Indeed, it is required to clear all keys before import
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
I encryptd a file using gpg, now I want to decrypt the file.
Is there any way to decrypt the file without need to import the secret file?
We have the secret key in a file called key.sec; can we pass the secret file to gpg as a parameter (when we run the decrypt command from the bash command line) to use when decrypting the encrypted file? Or must we import the secret key then decrypt the encrypted files?
You must add the secret key to a keyring. From the gpg(1) documentation:
--no-default-keyring
Do not add the default keyrings to the list of
keyrings. Note that GnuPG will not operate without any
keyrings, so if you use this option and do not provide
alternate keyrings via --keyring or --secret-keyring,
then GnuPG will still use the default public or secret
keyrings.
You could --import --no-default-keyring --secret-keyring temporary to import the key, use --secret-keyring temporary when decrypting the content, then delete the ~/.gnupg/temporary.gpg file when you're done. But that's just a work-around.
You have to import the secret key to use it but the way that secret keys are managed by GnuPG version 2.x has changed. There is a gpg-agent daemon that handles secret keys access and its use is mandatory from version 2.1.
Here is a way that you can quickly create a temporary keyring to decrypt with a secret key that is contained in a file:
$ mkdir -m 700 ~/.gnupg-temp
$ gpg --homedir .gnupg-temp --import key.sec
$ gpg --homedir .gnupg-temp -d an_ecrypted_file
If you want to clean up afterwards, stop the agent and remove the directory:
$ gpg-connect-agent --homedir .gnupg-temp KILLAGENT /bye
$ rm -r ~/.gnupg-temp
There used to be an option --secret-keyring about which the documentation for version 2.1 has this to say:
This is an obsolete option and ignored. All secret keys are stored in the private-keys-v1.d directory below the GnuPG home directory.
The private-keys-v1.d directory (wthin the --homedir or ~/.gnupg) is owned and operated by the agent.
The objective of the OP Mohammed appears to be keeping his PUBLIC and SECRET key apart. After all, do we want to keep the Secret key with the data it was used to encrypt? Thus, Mohammed's and 10,650+ others (at the time I write this) are interested in if/how it's possible. Indeed it is, and this is how you do it:
The publicly-facing host only has two keys: Both are Public Keys
Your GPG Public key used to encrypt data
Your SSH Public key in .ssh/authorized_keys to facilitate non-interactive logins.
Round-tripping an encrypted file using Public-Secret key separation:
The following bash snippet when executed on the host with the Secret Key will fetch the crypted file from the DMZ host via scp, and squirt the gpg decrypted standard output back onto the DMZ host into a file so it can be read/operated upon. This code is tested and known to work correctly:
echo "$(gpg -d $(scp myuser#192.168.1.10:/home/myuser/test-gpg.txt.asc .;ls ./test-gpg.txt.asc))" | ssh myuser#192.168.1.10 'cat > /home/myuser/test-gpg.txt'
Note that you will still be prompted for a password once decryption begins. But once the password is supplied, the script continues and injects the decrypted gpg stream into a file on DMZ host.
And don't forget to do an rm test-gpg.txt of the decrypted file once the operation that required it's contents to be readable has been completed.
So yes, very possible to keep your secret key apart from the publicly accessible host where encryption occurs and your secret key tucked safely away in a host outside of that DMZ. HTH- Terrence Houlahan