Bruteforce GPG passphrase using script [duplicate] - linux

This question already has an answer here:
Best way to soft brute-force your own GPG/PGP passphrase?
(1 answer)
Closed 8 years ago.
I have forgotten my passphrase for my gpg key on linux. Can someone please help me write a simple script to use bruteforce to crack the key? I remember some of the words which MIGHT be in the passphrase, so hopefully, it will not take long for my computer to bruteforce it.
All is not lost if I can't recover the passphrase, it just means I will not be able to work on my project for the next 10 days until I get back to work to get another copy of the files, but this time with a new key for which I will remember to passphrase.
However, it will be nice to be able to work on my project in these 10 days.

Maybe something like:
#!/bin/bash
#
# try all word in words.txt
for word in $(cat words.txt); do
# try to decrypt with word
echo "${word}" | gpg --passphrase-fd 0 --no-tty --decrypt somegpgfile.gpg --output somegpgfile;
# if decrypt is successfull; stop
if [ $? -eq 0 ]; then
echo "GPG passphrase is: ${word}";
exit 0;
fi
done;
exit 1;

1) The script won't be simple, at least how you envisage "simple."
2) It will take a long time - that's the point of using pass phrases over simple passwords. Taking the time to write such a script, incorporating your words which may or may not be in the phrase plus a stab at iterating will probably take over ten days.
3) You probably will forget the next passphrase too.
4) Ooops!
Sorry dude, time to start a new project (at least to while away the next ten days - I suggest a passphrase cracker as an ideal distraction.)
Merry Christmas!
-Oisin

Tersmitten's answer may be out of date.
echo "${word}" | gpg --passphrase-fd 0 -q --batch --allow-multiple-messages --no-tty --output the_decrypted_file -d /some/input/file.gpg;
I used the above line with gpg 2.0.20 and libcrypt 1.5.2 to achieve the desired results.

Related

Simulate keytool password keyboard input in bash script

I have like 100 keystore e.g. "store15.jks" files, and a single X.509 certificate "mycert.pem". I need to find out in which "store*.jks", "mycert.pem" is imported in. What I am trying to do is to make a script to iterate 100 times and do command
keytool -list -keystore store*.jks
I initially came up with simple script like this:
#!/bin/bash
for((i=1;i<100;i++))
do
cert="mycert.pem"
str="store"$i".jks"
OUTPUT="$(keytool -list -keystore $str)"
echo $OUTPUT
done
Alas, at the first iteration already, I am prompted for keystore password, like
Enter keystore password: //3 or 4 spaces after colon
That means I'd have to enter password for every single iteration, and there must be a (much) better way to do this, i.e. a way to simulate keyboard input when password is prompted. Browsing through the Stack Overflow I found some examples using certain "Expect" scripting, but they were either rudimentary or I just couldn't manage to get it right, so I failed at combining /bash and /expect. Must say I find it a bit strange that there is no /bash technique for task that might see pretty common. I would appreciate any help, preferring example scripts. Thanks!
The easiest way to do this is to use the -storepass option which allows you to pass the password on the command line. If for some reason that does not work for you (maybe you have an earlier version), here is an expect script that works for me:
expect -c "spawn /usr/bin/keytool -list; expect \"assword:\" { exp_send \"the_password\r\"}; expect EOF {exit}"
First of all, thanks alot to both of you guys, -storepass worked like a charm! You made me very happy :)
I'll now post my updated script that solved the problem:
#!/bin/bash
for((i=1;i<100;i++))
do
str="store"$i".jks"
sha="5A:6B:18"
OUTPUT="$(keytool -list -keystore $str -storepass mypass | grep $sha )"
echo $i
echo $OUTPUT
done
The answer to the original problem is store74.jks. Hope this helps someone someday.
For viewing public keys, now password is needed; if you can output a simple "ENTER" keystroke, that should suffice, too.
E.g.
echo "" |keytool -list -keystore key.jks

Straight bash empty parameter not recognized

Good day SO!
I'm working on a Django Project for learning purposes. Now I have a little bash script (working properly) to migrate my Django database and create a superuser with a onetoone profile.
Now I want to update my bash script so it recognizes some parameters. For example to automatically run the model migrations (makemigrations) or run the server after successfully migrating the database.
So I want to tell the bash to make migrations before migrating and run the server when finished (keys without values).
(venv)edwin#edwin:/project/installs/$ source install_database.sh -m -r
Now, I'm quite new to Linux and completely new to Straight Bash Space Separated bash scripts. I've read that using getopt[s] has no use in this case, since it can't handle empty argument strings.
So I attempted to create the Straight Bash Space Separated like:
#!/usr/bin/env bash
while [[ %# > 1 ]]
do
key=$1
case $key in
-m|--makemigrations)
MAKEMIGRATIONS=true
shift
;;
-r|--runserver)
RUNSERVER=true
shift
;;
*)
echo "invalid argument"
;;
esac
shift
done
echo "${RUNSERVER}"
echo "${MAKEMIGRATIONS}"
Whatever I attempt to initiate
(venv)edwin#edwin:/project/installs/$ source install_database.sh -m -r
(venv)edwin#edwin:/project/installs/$ source install_database.sh -m "test" -r "test"
(venv)edwin#edwin:/project/installs/$ source install_database.sh -m test -r test
I keep getting the result
false
false
Probably it's a beginners mistake, but I can't seem to figure it out...
Can you give me an explanation of what I am doing wrong, and push me in the right direction to solve the problem?
Thanks in advance!
Three mistakes:
1) %# should be $#
2) You have two shift instructions in case of an accepted key (one inside the case and one at the end of the while loop). Just remove the shifts inside the cases and keep the one at the end of the loop (remember you want to shift even if the key is not recognized).
3) $# gives you the number of arguments excluding the program's name, so the while loop condition should be while [[ $# > 0 ]]

bash: How can I assemble the string: `"filename=output_0.csv"`

I am using a bash script to execute a program. The program must take the following argument. (The program is gnuplot.)
gnuplot -e "filename='output_0.csv'" 'plot.p'
I need to be able to assemble the following string: "filename='output_0.csv'"
My plan is to assemble the string STRING=filename='output_0.csv' and then do the following: gnuplot -r "$STRING" 'plot.p'. Note I left the words STRING without stackoverflow syntax style highlighting to emphasise the string I want to produce.
I'm not particularly proficient at bash, and so I have no idea how to do this.
I think that strings can be concatenated by using STRING="$STRING"stuff to append to string? I think that may be required?
As an extra layer of complication the value 0 is actually an integer which should increment by 1 each time the program is run. (Done by a for loop.) If I have n=1 in my program, how can I replace the 0 in the string by the "string value" or text version of the integer n?
A safest way to append something to an existing string would be to include squiggly brackets and quotes:
STRING="something"
STRING="${STRING}else"
You can create the "dynamic" portion of your command line with something like this:
somevalue=0
STRING="filename='output_${somevalue}.csv'"
There are other tools like printf which can handle more complex formatting.
somevalue=1
fmt="filename='output_%s.csv'"
STRING="$(printf "$fmt" "$somevalue")"
Regarding your "extra layer of complication", I gather that this increment has to happen in such a way as to store the value somewhere outside the program, or you'd be able to use a for loop to handle things. You can use temporary files for this:
#!/usr/bin/env bash
# Specify our counter file
counter=/tmp/my_counter
# If it doesn't exist, "prime" it with zero
if [ ! -f "$counter" ]; then
echo "0" > $counter
fi
# And if it STILL doesn't exist, fail.
if [ ! -f "$counter" ]; then
echo "ERROR: can't create counter." >&2
fi
# Read the last value...
read value < "$counter"
# and set up our string, per your question.
STRING="$(printf "filename='output_%d.csv'" "${value}")"
# Last, run your command, and if it succeeds, update the stored counter.
gnuplot -e "$STRING" 'plot.p' && echo "$((value + 1))" > $counter
As always, there's more than one way to solve this problem. With luck, this will give you a head start on your reading of the bash man page and other StackOverflow questions which will help you learn what you need!
An answer was posted, which I thought I had accepted already, but for some reason it has been deleted, possibly because it didn't quite answer the question.
I posted another similar question, and the answer to that helped me also answer this question. You can find said question and answer here: bash: Execute a string as a command

Linux bash script - For loops issues

I'm working on a bash script that will add users in a batch process. This code goes as follows:
#!/bin/bash
# A script that creates users.
echo "This is a script to create new users on this system."
echo "How many users do you want to add?"
read am
echo " "
for i in {0..$am..1}
do
echo "Enter a username below:"
read usern
sudo useradd $usern
sudo passwd $usern
echo " "
echo "User $am '$usern' added."
done
In this case, I wanted to make 4 users. I went through and entered the username "callum3" and set the password as "1234" for ease of login. Once I input everything (correctly, may I add) the terminal window displays the following.
User 4 'callum3' added.
This shows that my for loop isn't actually working, when I can see nothing wrong with it. I have tried using a while loop with no luck there either.
Am I making a rookie mistake here or is there something deeper going on?
Although I suspected it, for a better understanding on what could be wrong with your script I pasted it in shellcheck.net. That the problem is in the line:
for i in {0..$am..1}
Bash doesn't support variables in brace range expansions. That is, you cannot use a variable in an expression like {..}.
Instead, use seq. With seq $var you get a sequence from 1 (default) to $var:
for i in $(seq "$am")
I feel like I'm missing something in that nobody has suggested an arithmetic for loop:
for ((i=0; i<am; i++)); do
…
done
This has the particular benefit in bash of being both readable and not requiring a subshell.
You can use:
for i in `seq 0 $((am-1))`
do
...
done
Sequence will start from 0 and end at $am-1

how to speed up openssl generate md5 checksum

I'am facing a problem, in AIX platform, we use a command to generate checksum:
Sample:
exec 0<list
while read line
do
openssl md5 $line >> checksum.out
done
But this last for a long time. I find out that our cpus still have free resources.
It's the openssl md5 running multithread? If not how can I let it run by multithread, or using other method to speed up it.
Best Regards
Void
If I understand correctly from the answer and comments of this question, it can't be done as there are dependencies between the steps in the hashing algorithm (and I guess OpenSSL would have a multithreaded implementation if it was generally possible).
However you could always parallelize the tasks by starting n instances of openssl md5 in parallel.
For example (assuming n = 4 threads)
while read line; do
openssl md5 $line >> checksum.out0 &
openssl md5 $(read) >> checksum.out1 &
openssl md5 $(read) >> checksum.out2 &
openssl md5 $(read) >> checksum.out3
done
The last one should not run in the background if you want to keep the exact number of threads running at the same time. Also you may want to make sure that the different lines take about the same time to complete so you don't end up with race conditions.
Also this example is not really tested (using $(read)), and there are probably better ways to do it (for example let each instance write its output to a separate file and then concatenate them all afterwards - e.g. cat checksum.out* > checksum.out), but it should be enough of an idea to help you get started.
EDIT:
I just tested and read works the way I hoped, so by making a new output file for each instance of openssl md5 with incremented numbers at the end (for example by including a counter variable) you can just add an extra line at the end of the script to cat the outputs into a single file.
Resulting script:
exec 0<list
COUNT=0
while read line; do
openssl md5 $line >> checksum.out$((COUNT++)) &
openssl md5 $(read) >> checksum.out$((COUNT++)) &
openssl md5 $(read) >> checksum.out$((COUNT++)) &
openssl md5 $(read) >> checksum.out$((COUNT++))
done
cat checksum.out* > checksum.out
Should do the trick (just remember to clean up all the temporary files afterwards...)

Resources