gpg encrypt file without keyboard interaction [closed] - bash

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 4 years ago.
Improve this question
I am running next command within a crontab to encrypt a file and I don't want a keyboard interaction
echo "PASSPHRASE" | gpg --passphrase-fd 0 -r USER --encrypt FILENAME.TXT
but I have this answer:
gpg: C042XXXX: There is no assurance this key belongs to the named user
pub 40XXX/C042XXXX 2012-01-11 Name LastName. (comment) <user#email.com>
Primary key fingerprint: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
Subkey fingerprint: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
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)

As David intimated, the problem here is that gpg doesn't trust the public key you're using to encrypt. You could sign the key as he explained.
An alternative--especially if the key might be changing occasionally--would be to tack on --trust-model always to your gpg command.
Here's the relevant bit from the man page:
--trust-model pgp|classic|direct|always|auto
Set what trust model GnuPG should follow. The models are:
pgp This is the Web of Trust combined with trust signatures as used in
PGP 5.x and later. This is the default trust model when creating a
new trust database.
classic
This is the standard Web of Trust as used in PGP 2.x and earlier.
direct Key validity is set directly by the user and not calculated via
the Web of Trust.
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.
auto Select the trust model depending on whatever the internal trust
database says. This is the default model if such a database
already exists.

Here is my solution, based on gpg2 (but I bet you can apply similar technique to gpg)
$ gpg2 --edit-key {recipient email address}
> trust
> 5 (select 5 if you ultimately trust the key)
> save
This will tell gpg2 to trust the key fully, so that you can encrypt without prompt

The hack approach:
echo -n PASSPHRASE > phrase
chmod 400 phrase #Make sure ONLY the user running the cron job can read the phrase
yes | gpg --passphrase-fd 3 --recipient USER --encrypt FILENAME.txt 3<phrase
The underlying problem is that the key you have for USER isn't signed. If you trust it, you can sign it with
gpg --edit-key USER sign
It will probably ask a couple questions, depending on your configuration. Do this once, then you should be good to go in your crontab. I'd still recommend using the solution I proposed, putting the passphrase in a separate file and making it only readable by the one user that command runs as. If you do that, you can kill the yes |, and just have the encrypt line.

Use this command, it will help you
echo "PASSPHRASE" | gpg --passphrase-fd 0 --always-trust -r USER --encrypt FILENAME.TX

I was running into this too. I couldn't get sign-key to do anything interesting. Here's what I did:
create a gpg key:
gpg --gen-key
get long key ID (result is in 5th column):
gpg --list-keys --with-colon name#domain.tld
Add trusted key line to ~/gnupg/gpg.conf
trusted-key 16DIGITALPHANUMERICKEYID
gpg line in backup script:
gpg -e -r name#domain.tld backup_file.tgz
Debugging cron:
I'm also capturing cron dubugging output by sending stdout and stderr to a log file in the cron command line. It's helpful to know

I assume that like me, a lot of people come here for the 'without keyboard interaction' part of the question. With gpg2 and gpg-agent it got quite complicated to sign/encrypt/decrypt stuff without any keyboard interaction. Here is how you would create a signature when your plaintext private key passphrase is saved in a text file:
cat something_so_sign.xzy | gpg \
--passphrase-file "plaintext_passphrase.txt" \
--batch \
--pinentry-mode loopback \
-bsa
Change -b -s -a depending on your needs. The other switches are mandatory. You may also just use --passphrase 'SECRET'. As already pointed out, be careful with that. Plaintext textfiles are not that much better of course.

Or sign the key (after you veryfied the fingerprint, of course):
gpg --sign-key <recipient email address>
After that you fully trust the key.
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

When you create a certificate first time with your email-id select fully trusted certificate then whenever you encrypt any file will not ask question like.... for more information open image in above link.
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)

A different approach:
This solution will work without user input.
To deny access to sensitive data (rather than encrypt it using third-party's keys), I upload *ONLY my PUBLIC key to the server I want to protect data on and use that key to encrypt with. This negates the need for an interactive prompt to supply a password facilitating automation and best of all, the PRIVATE key is apart from the public server.
gpg --batch --yes --trust-model always -r $YOURPUBKEYEMAILADDRESS -e ./file.txt
However, if NOT encrypting with your own public key, the use of the switch --trust-model always is a bit ropey. Anyway, a different way of solving the problem of denying access to data. HTH- Terrence Houlahan

Related

Is there any way to encrypt and then sign with GPG?

I am working on a tool that sends out automated reports to our clients. This specific client wants the file to be encrypted and then signed. I have tried several different methods, with hours of searching, and have not had much luck. I know GPG signs then encrypts, but does anyone know if it is possible to swap the order? And if not does anyone know of any command line alternatives that can be run in a Linux container?
Example:
gpg --always-trust --batch --yes -s -u 'signee#email.com' -r 'receiver#email.com' -o 'test.txt.pgp' -e 'test.txt'
On verify :
gpg: verify signatures failed: Unexpected error
GPG doesn't seem to allow this in a single pass.
You have two options:
use a detached signing, then you'll need to send two files: one with encrypted data and second with the signature
encrypt data in first pass and then sign it in the second. However that would also need two steps on the receiving side: first verify signatures/unwrap data, then decrypt it.
Also it could be useful to ask client what exact format he expects to receive. Just example of gpg --list-packets report-file should be helpful.

GPG large file decryption duration

I want to encrypt large files on linux with a bash script. When I was looking for methods to accomplish that, I thought about GPG and gave it a try. But when I ran some benchmarks I noticed that en-/decryption of large files takes very long.
Test scenario
I generated a 30GB large file filled with random content. Then I encrypted it with an RSA 4096 bit key. As I understand it, GPG is a hybird-encryption programm which encrypts sessions keys with the RSA Public Key. Therefore the en-/decryption should be done wihtin seconds or at least within a minute, as it uses these session keys to encrypt the actual data, isn't it? But here are the test results - I didnt bother decrypting the file with compressen turn on as it would take me another 2 - 3 hours...
System Specs:
GPG Version: 2.2.19
Arch Linux
Docker
Intel i7
My gpg keys were generated with a config file which contained the following values:
Key-Type: RSA
Key-Length: 4096
Subkey-Type: RSA
Subkey-Length: 4096
Name-Real: some-key-name
Name-Comment: some-key-comment
Expire-Date: 0
Passphrase: 123456789
For encryption i used the following commands:
gpg -q --output /outputFile.txt --recipient some-key-name --encrypt /inputFile.txt (with compression)
gpg -q --output /outputFile.txt -z 0 --recipient some-key-name --encrypt /inputFile.txt (without compression)
This command for decrypting the files:
gpg -q --pinentry-mode loopback --batch --passphrase 123456789 --output /decryptedFile.txt --decrypt /encryptedFile.txt
Test results
Encryption with compression turned on:
real 36m23.096s
user 14m54.920s
sys 2m31.870s
Encryption with compression turned off:
real 21m9.781s
user 1m39.590s
sys 2m20.980s
Decryption with compression turned off:
real 140m13.050s
user 5m5.340s
sys 16m33.020s
Questions
Am I missing something or am I using the tool in a wrong way?
Do you know a better way to encrypt large files with which uses an asymmetric encryption or at least uses it to encrypt the session keys?
PS
I googled very much and didn't find a applicable solution. I also read the man page and didn't find a hint what I might miss or did wrong. Also please be aware that I know that passing the password to gpg that way isn't the most secure way ;)

Update the content of an encrypted file using gpg2 and bash scripting

Say there's an encrypted file file.txt
In order to update its content the file must be decrypted first, then run through the desired processing and afterwards it must be encrypted again.
(1) What would be the most straight forward way to do so in bash scripting using gpg2? The operation should request the user only once for a password to decrypt. It should use the same password for the final encryption afterwards.
Here is a most likely extremely unsecure, but working example of what I try to archieve:
function update-encrypted-file() {
read pass_tmp;
local pass=$pass_tmp;
unset pass_tmp;
local file="file.txt";
local tmp_result=$(cat $file | gpg2 --batch --passphrase $pass | update);
echo $tmp_result | gpg2 -c --batch --passphrase $pass > $file;
}
whereas update might be sth. like this: alias update="tr -d X" (delete all X's)
(2) What exactly could make the above example insecure? I guess using read itself is a no-go, but it would be interesting to see why. Not having the variable set locally causes the password to be inside the global space for some short time. Could that possibly be fetched? I could not figure out how to use pinentry-tty in this case (see this post)
(3) Apart from that, the gpg2 documentation remarks regarding the --passphrase option: "Obviously, this is of very questionable security on a multi-user system. Don't use this option if you can avoid it."
Is this only the case when manually used inside a terminal, since the commands are logged? Or would there also be concerns when using e.g. inside a function with the password having saved in only this function scope.
I'm not answering your individual questions directly, but have a slight discussion of password management and GnuPG, but for the third question: the command line of all processes from all users running on the machine are available to anybody. To confirm, just run a simple ps ax as an unprivileged user. Never pass secrets as parameters!
Obviously, the most secure option will be to never get hold of the passphrase at all. If you don't have it, you can't mess with it. With GnuPG 2.1, this was even applied to the actual GnuPG binary (gpg/gpg2): The most critical secret key operations (involving handling the passphrase) are performed by the small gpg-agent (thus having smaller attack surface), the rather large and complicated GnuPG binary neither gets direcct access to the key nor the passphrase.
This is also what I'd go for: instead of handling the passphrase, rely on gpg-agent doing so instead. It is available (and since GnuPG 2.1, also required) anyway. If configured properly (and this is the default), gpg-agent will cache the passphrase for a while. If the user configured something else, he decided he does not want cached passphrases, which you also should respect with your application.
As soon as required, the gpg-agent will query the user for the passphrase through the configured method -- if you're running a graphical user interface, this will likely be a window popping up.
If you mess with the GnuPG configuration (for example, your own configuration files, starting your own gpg-agent, ...), it's your job of course to take care of this. To start your own instance of gpg-agent to have full control over caching and other options, take advantage of the --options, --homedir and --no-use-standard-socket as required by your individual use case.
Finally, you're storing an intermediate result of the contents, which you echo:
local tmp_result=$(cat $file | gpg2 --batch --passphrase $pass | update);
echo $tmp_result | gpg2 -c --batch --passphrase $pass > $file;
Don't do this for the same reasons discussed for passphrases! Instead, directly pipe the result into the encryption process (and there is no need for cat here):
< $file gpg2 --batch --passphrase $pass | update | gpg2 -c --batch --passphrase $pass > $file;

How to use Gnupg's passphrase-fd argument?

I would like to use GnuPG´s decrypt command without any user interation. The script's --passphrase-fd argument seems exactly what I need. But I don't know how it works - haven't found examples.
Could anyone give me an example of such a command, on both Windows and UNIX environments?
(FYI, I'm using GnuPG 2).
Thanks already :)
In order to use the gpg option --passphrase-fd in GnuPG v2, you must specify the --batch parameter. I will first explain how --passphrase-fd works, and then get to the examples.
--passphrase-fd tells GnuPG which file descriptor (-fd) to expect the passphrase to come from. The standard file descriptors are STDIN (0), STDOUT (1) and STDERR (2). For the context of this question, you would normally only be concerned about STDIN (0).
You didn't specify where you want the passphrase to come from, so I will demonstrate the usage of STDIN (standard in) in a variety of ways.
--passphrase-fd 0 tells GnuPG to retrieve the passphrase from input into the current shell; so for example if you want GnuPG to get the passphrase data in the very next line of console input, the command and output would be like so:
gpg2 --batch --passphrase-fd 0 --armor --decrypt /path/to/encrypted_file.pgp
<next line of input is passphrase followed by hitting enter>
gpg: encrypted with 1024-bit RSA key, ID EC18C175, created 2013-10-26
"testkey4321 (4321) <test#4321.com>"
this is a test... this is only a test...
In the above example, the passphrase was provided via file descriptor 0 (STDIN) - which we provided by entering it on the shells current standard input.
In the next example, we will tell GnuPG to retrieve the passphrase from input into the current shell that is actually the output of another command (echo, in this case, which merely "echos" what you tell it to):
echo "mypassphrase" | gpg2 --batch --passphrase-fd 0 --armor --decrypt /path/to/encrypted_file.pgp
gpg: encrypted with 1024-bit RSA key, ID EC18C175, created 2013-10-26
"testkey4321 (4321) <test#4321.com>"
this is a test... this is only a test...
Another example that dumps the contents of a file that contains the passphrase to STDIN -
cat /path/to/file_with_passphrase | gpg2 --batch --passphrase-fd 0 --armor --decrypt /path/to/encrypted_file.pgp
gpg: encrypted with 1024-bit RSA key, ID EC18C175, created 2013-10-26
"testkey4321 (4321) <test#4321.com>"
this is a test... this is only a test...
In summary, --passphrase-fd just tells GnuPG that you want to feed it the requisite passphrase via a standard file descriptor; the difference between GnuPG v2 and GnuPG is merely the --batch parameter.
The above examples should work the same in Windows and *nix environments, with the only difference being that in Windows - depending on your configuration and version - you will have to replace cat with type in order to dump the contents of a file to STDIN.
kylehuff's answer still wouldn't work for me, with gpupg still popping up a password prompt.
According to https://wiki.archlinux.org/index.php/GnuPG#Unattended_passphrase with gnupg version 2.1.0 and higher, you need to do additional steps to support --passphrase-fd
First, edit the gpg-agent configuration to allow loopback pinentry mode:
~/.gnupg/gpg-agent.conf
allow-loopback-pinentry
Restart the gpg-agent process if it is running to let the change take effect.
Second, either the application needs to be updated to include a commandline parameter to use loopback mode like so:
$ gpg --pinentry-mode loopback ...
Using GPG4win/gpg 2.2.3: to use the passphrase-fd 0 and bypass the prompt, I can confirm that the following works:
--pinentry-mode loopback
As I've had to recently figure this out myself I thought it might be worth chiming in.
The answer by kylehuff is very good if you're decryping files, however, if you've need of input/output redirection, such as piping, here's an example of using a non-0 file descriptor to pass the passphrase.
#!/usr/bin/env bash
# Set some variables for easy modding
Var_fd='9'
Var_pass_location="/path/to/passphrase.file"
Var_gpg_decrypt_opts="--passphrase-fd ${Var_fd} --decrypt"
Var_output_location="out.txt"
Arr_string=( "$#" )
# Open file descriptor and shove the passphrase file into it
exec ${Var_fd}<${Var_pass_location}
# Pipe input array though gpg and append to output file
cat <<<"${Arr_string[*]}" | $(which gpg) ${Var_gpg_decrypt_opts} >> ${Var_output_location}
# Do not forget to close the file descriptor
exec ${Var_fd}>&-
Do be warned, outside of special use cases, that saving your private keys passphrase is generally seen as a bad idea or bad security practice. -Also please don't forget to close the descriptor when finished so that your passphrase isn't accessible via that method anymore.- Often I've seen advised in these use cases to use specifically non-passphrase protected keys but that's totally your choose. If you like the above code then you may want to also checkout the script I debugged for key generation either unattended or attended because it covers even less commonly used gpg file descriptor options.
Edits/updates
So I've been debugging the bulk decryption operations and have evidence to show that file descriptors seem to close automatically or perhaps it's auto closed by GnuPG. Check build 152 all the way at the bottom of the raw logs, just before diff checks, you'll find that the first block of encrypted data ate the passphrase leaving the next two blocks of data without a valid passphrase. The related scripts in this operation are ; first the script_decrypt.sh build script sets the test key's passphrase to file descriptor 9 as shown in above examples, then the Helper script is called such that it'll make use of that file descriptor... it's a funky use case but the moral of the story seems to be that what ever bulk decryption operations you plan to implement with GnuPG file descriptors will likely need to follow the steps outlined above as a whole function to properly have the file descriptors reopened. I'll be rewriting the helper script over the next few pushes so check the Travis-CI build logs greater than 152 to find if I've a solution to where file descriptors get closed...
... so that only took two tries to get things working, see the difference in build 154 both the encrypted file and raw input log match. As hypothesised the file descriptors get dumped after first usage by either GnuPG or a sub shell, thus the passphrase needs to be assigned before every decrypt command for bulk decryption to happen.
Hope this was valuable to y'all.

Automatically press Enter to continue in Bash

I want to change RSA Keys to open ssh connections without any problems. It works fine, if I use this tutorial but I want to have it done in a bash script. Unfortunately I am asked to enter a passphrase (I want to enter nothing). How can I achieve to automatically press Enter three times in a row, when the script reaches this point?
This thread did not help, because I am not allowed to install new programs on my work PC and the echo | command trick seems only to work for one Enter. Also I need to enter "n" and Enter, if the procedure was already made, to not overwrite any files. How do i achieve that?
If you just need to press Enter a bunch of times this will do it:
yes "" | command
For anything more complicated than that you might want to use expect as suggested in the other thread, which you can install in your homedir without root priviliges.
PS: Please avoid re-posting questions in the future. If you don't like an answer for some reason, just comment on it.
If you want to just create ssh keys in a bash script without requiring any user input, you can specify arguments to ssh-keygen:
# rsa type (default), no passphrase, write to file id_rsa and id_rsa.pub
captain:~> ssh-keygen -t rsa -N "" -f id_rsa
Generating public/private rsa key pair.
Your identification has been saved in id_rsa.
Your public key has been saved in id_rsa.pub.
The key fingerprint is:
fe:4a:82:08:0e:ab:b7:02:62:11:4d:3e:79:a4:d3:98 mrb#captain.local

Resources