Python – Hardening GnuPG against brute force attacks

I am currently working on a Python program that uses GnuPG (with symmetric encryption) to store data on the client: user enters password, GPG file is decrypted, data is loaded, etc.

Assume that an attacker copies this GPG file. What can be done to slow down the brutal password enforcement? Maybe it is possible to do thousands of iterations in a PBKDF (or maybe SHA) and then use that as a password?

Time and space complexity for the brute force backpack problem

I was wondering if anyone can confirm my work for the complexity of 0/1 Knapsack Brute Force and Dynamic Programming solutions.

I justified it for the brute force $ O (N.2 ^ N) $

This is because to calculate all possible subsets (the method I used brute force was to calculate the potency set and then calculate the weights / values ​​for each set) $ 2 ^ N $ and then we compute the sum of each subset of size from 1-N that lasts $ N.2 ^ N $

Would be space complexity $ O (P) $ Where p is the total number of subsets

But according to my notes, the Brute Force is 0/1 Knapsack $ O (2 ^ N) $ with space $ O (N) $

I think that's for the recursive solution, but my raw strength is not recursive.

hash – brute force hashing of passwords with known format

The meaning of the word fortuitously It has a lot of weight in the Infosec community. In fact, some people are obsessed with it! We keep trying to get a better approximation of actual coincidence, but it can actually be impossible!

The secret to your problem is weak, not because of the reversibility of the hash (which would be very difficult), but because it is just not long enough and not fortuitously enough to have enough entropy to make a brute force attack impossible.

I see that the first "random" value is a date. It looks like the date may be relevant to the system. If the system uses sha512, this value will probably be available sometime in recent years and probably more recently!

The second "random" value is a name. I could probably get a list of names used all over the world and iterate my cracker through various combinations of them. If I could make a few guesses about a user's ethnicity, I could narrow the dictionary even further.

And you see why randomness is so important! Since these values ​​are not really random, they are much easier to guess than others, and a cracker based on dictionary attacks can be programmed to take advantage of this fact.

Throttling – brute force attacks (security php)

After a few weeks of searching and learning "php secure" I created a class of failed logins.

  1. record_failed_login -> Record the logins, if the entry is not found, it creates the new one. If he finds – will be updated.
  2. clear_failed_logins -> is similar to logging in with a failed record. If you accept the user, set the number to 0.
  3. throttle_failed_logins -> returns the number of minutes that must be waited before registrations are possible again.

I don't know how to insert an associative array into a MySQL table with a prepared statement. That's why I used "PHP Procedural Style" + OOP.

$this->sanitized_attributes(); comes from class DatabaseObject

CREATE TABLE `failed_logins` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(255) NOT NULL,
  `count_f` int(11) NOT NULL,
  `last_time` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`)
) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

   escape_string($username) . "' ";
            $sql .= "LIMIT 1";

            $result = self::$database->query($sql);
            $failed_logins = $result->fetch_assoc();
            return $failed_logins;

        protected function add_record_to_db($failed_login) {            
            // Insert record
            foreach($failed_login as $key => $value){

            $failed_login = ();

            $failed_login('username') = $value('username');
            $failed_login('count_f') = $value('count_f');
            $failed_login('last_time') = $value('last_time');

            $sql = "INSERT INTO " . self::$table_name . " (";
            $sql .= join(', ', self::$db_columns);
            $sql .= ") VALUES (";
            $sql .= "'" . self::$database->escape_string($failed_login('username')) . "', ";
            $sql .= "'" . self::$database->escape_string($failed_login('count_f')) . "', ";
            $sql .= "'" . self::$database->escape_string($failed_login('last_time')). "'";
            $sql .= ")";

            $result = self::$database->query($sql);
            if($result) {
              $this->id = self::$database->insert_id;
            return $result;

        protected function update_record_in_db($failed_login) {

            $attributes = $this->sanitized_attributes();
            $attribute_pairs = ();
            foreach($attributes as $key => $value) {
              $attribute_pairs() = "{$key}='{$value}'";

            $sql = "UPDATE " . self::$table_name . " SET ";
            $sql .= join(', ', $attribute_pairs);
            $sql .= " WHERE username='" . self::$database->escape_string($this->username) . "' ";
            $sql .= "LIMIT 1";

            $result = self::$database->query($sql);
            return $result;

        public function record_failed_login($username) {

        $failed_login = $this->find_one_in_db($username);

        if(!isset($failed_login)) {
            $failed_login() = (
                'username'  => $username, 
                'count_f'   => 1, 
                'last_time' => time()

        } else {
            // existing failed_login record
            $this->username = $failed_login('username');
            $this->count_f = $failed_login('count_f') + 1;
            $this->last_time = time();

        return true;

        function clear_failed_logins($username) {
            $failed_login = $this->find_one_in_db($username);

            if(isset($failed_login)) {

                $this->username = $failed_login('username');
                $this->count_f = $failed_login('count_f') = 0;
                $this->last_time = time();

            return true;

        function throttle_failed_logins($username) {
            $throttle_at = 5;
            $delay_in_minutes = 10;
            $delay = 60 * $delay_in_minutes;

            $failed_login = $this->find_one_in_db($username);

            if(isset($failed_login) && $failed_login('count_f') >= $throttle_at) {
                $remaining_delay = ($failed_login('last_time') + $delay) - time();
                $remaining_delay_in_minutes = ceil($remaining_delay / 60);
                return $remaining_delay_in_minutes;
            } else {
                return 0;

Unlock Huawei BootLoader – is brute force the only way now?


So I want to unlock the BootLoader on my Huawei Mate 9 to install LineageOS on it. I have already read that Huawei no longer gives BootLoader codes. Now is the only way (free) to enforce all possible codes?

Brute-forcing method

I would write a simple python script that iterates through all the numbers (16 digits) through 10 ^ 16 and runs the appropriate command. My CPU cores are 3 GHz, so it would only take about 55 minutes (10 ^ 16 / 3,000,000,000).

But I don't know if this is possible. How should I check if a device is unlocked with Python? And will the device lock after a few tries?

Here is someone else's script, it would take too long.

Any advice or help would be appreciated.

Complexity theory – is it true that brute force has to try ALL possible solutions?

If we look at that NP We have problems (or NP-Complete and NP-Hard) for now use brute force to solve them exactly. We currently have to search "all" possible solutions until we come to the right solution.

But doesn't that just require that? final Solution we try will be correct? Isn't it unlikely that we should actually try? all of them, regardless of whether brute force is really needed or not? It can happen that we only have to try 30% of all possible solutions until we have found a correct solution.

So why do people say that Brute Force has to try ALL possible solutions?

Problem with metasploit when operating brute force on the SSH port

I tried to perform a brute force hack on an SSH (port 22) using the Metasploit framework.
The attacking machine that I used is Kali Linux VM, and the "victim" machine is Windows 10 VM.

The error I got every time I used the run command in msfconsole is:

"Could not connect: Connection is rejected by the remote host ("
Any ideas what this error could mean?

I have done the basic checks as; Open the port on Windows 10 and ping any computer that is working properly.

Brute Force – Hydra HTTP post form when there are two forms on the page

I am trying to brutally force the credentials on the following website

        Admin Login -- Cody's First Blog

Admin Login


Incorrect username or password


Add comment:

I have executed the Hydra command

hydra **domain** http-post-form /**subdomain**/?^USER^:password=^PASS^:F='Incorrect username or password' -L ~/Documents/SecLists/Usernames/top-usernames-shortlist.txt -P ~/Documents/SecLists/Passwords/darkweb2017-top100.txt -t 30 -w 30 -o ~/Desktop/hydra-http-post-attack.txt

I get the issue

hydra ( starting at 2019-12-30 16:01:39
(WARNING) Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
(DATA) max 30 tasks per 1 server, overall 30 tasks, 1683 login tries (l:17/p:99), ~57 tries per task
(DATA) attacking http-post-form://**domain**:80/**subdomain**/?^USER^:password=^PASS^:Incorrect username or password
(STATUS) 30.00 tries/min, 30 tries in 00:01h, 1653 to do in 00:56h, 30 active
(STATUS) 10.00 tries/min, 30 tries in 00:03h, 1653 to do in 02:46h, 30 active
(STATUS) 4.29 tries/min, 30 tries in 00:07h, 1653 to do in 06:26h, 30 active
(STATUS) 2.00 tries/min, 30 tries in 00:15h, 1653 to do in 13:47h, 30 active
(STATUS) 0.97 tries/min, 30 tries in 00:31h, 1653 to do in 28:29h, 30 active
(STATUS) 0.64 tries/min, 30 tries in 00:47h, 1653 to do in 43:10h, 30 active
(STATUS) 0.48 tries/min, 30 tries in 01:03h, 1653 to do in 57:52h, 30 active
(STATUS) 0.38 tries/min, 30 tries in 01:19h, 1653 to do in 72:33h, 30 active
(STATUS) 0.32 tries/min, 30 tries in 01:35h, 1653 to do in 87:15h, 30 active
(STATUS) 0.27 tries/min, 30 tries in 01:51h, 1653 to do in 101:57h, 30 active
(STATUS) 0.24 tries/min, 30 tries in 02:07h, 1653 to do in 116:38h, 30 active
(STATUS) 0.21 tries/min, 30 tries in 02:23h, 1653 to do in 131:20h, 30 active
(STATUS) 0.19 tries/min, 30 tries in 02:39h, 1653 to do in 146:01h, 30 active
(STATUS) 0.17 tries/min, 30 tries in 02:55h, 1653 to do in 160:43h, 30 active
(STATUS) 0.16 tries/min, 30 tries in 03:11h, 1653 to do in 175:25h, 30 active
(STATUS) 0.14 tries/min, 30 tries in 03:27h, 1653 to do in 190:06h, 30 active
(STATUS) 0.13 tries/min, 30 tries in 03:43h, 1653 to do in 204:48h, 30 active
(STATUS) 0.13 tries/min, 30 tries in 03:59h, 1653 to do in 219:29h, 30 active
(STATUS) 0.12 tries/min, 30 tries in 04:15h, 1653 to do in 234:11h, 30 active
(STATUS) 0.11 tries/min, 30 tries in 04:31h, 1653 to do in 248:53h, 30 active
(STATUS) 0.10 tries/min, 30 tries in 04:47h, 1653 to do in 263:34h, 30 active

Any idea what's going wrong? It appears that none of the threads are being resolved.

Brute Force – WEP QOS_DATA vs DATA decryption – difference?

I recently played a bit with my pocket size IV hardware WEP sniffer.
It's a 5V tool that I use in my lab when I'm bored:

In my tests, I found out that one of my MIFI routers is sending data packets as QOS_DATA while the other is sending DATA.

I wrote a breeder for WEP years ago, who does magic by spontaneously generating a word list and decrypting it (later).

However, I have noticed that it does not work on QOS_DATA packets, although they are not different from DATA, but prefixed with a 2-byte header.

So I added 2 bytes for QOS_DATA frames to properly position IV, DATA and ICV.

And went with the testing, where

on) MIFI is 64-bit encrypted (24b for IV, 40b for KEY: ola13) QOS

b) MIFI is 64-bit encrypted (24b for IV, 40b for KEY: MYKEY) DATES

For clarity, I also add snapshots of WireShark.

TEST A – crack WEP QOS

Enter image description here

Unfortunately, the cracker does not work, although KEY was included.

WEPCracker (c) Codemaster 2015
Using userkey: ola13
- Found Data packet for BSSID f8:01:13:c9:15:25, Length 121 0/248

IV: 32 0E 32 

DATA: 9B 0C 9E 85 D0 4E 45 3A C1 0A 4A 70 6A 39 C1 76 0E D8 24 9C A6 28 DF A5 A0 2D D9 1B F5 B5 6D 50 1F B8 06 86 FA 5D 5C 14 FC FE 23 66 2A 30 79 A9 D0 32 8E BF 3D 7A 7D 87 36 5A 96 F7 5F 98 F7 C9 F3 93 4B 69 22 06 37 93 92 A4 B1 02 29 88 4D 81 1C F0 76 E1 32 63 81 

ICV: 4D D7 6D 5E 
CRC Check: 8a6d3411 / 1cdf4421 (ola13)
Not found, tried with key ola13

TEST B – crack WEP-data

Enter image description here

This works fine for DATA.

WEPCracker (c) Codemaster 2015
Using userkey: MYKEY
- Found Data packet for BSSID 00:23:cd:1f:73:b0, Length 108 0/5

IV: CE A2 6F 

DATA: FC 98 7D DD CA 59 74 19 2A A5 79 B6 20 BC 61 89 75 E3 31 EC 27 E8 2D 6D 28 3E 87 1B 25 41 0A A5 F5 21 CB 11 D2 57 FF 09 69 48 6C 41 69 37 87 98 30 F9 A2 34 38 FC 5C 7E F3 FB DB 03 6B 68 25 3A CA C0 03 07 ED AF 08 8C 23 25 28 91 

ICV: CD 24 FF 64 

CRC Check: 4c627c0d / 4c627c0d (MYKEY)
(!) Potential KEY found (MYKEY)

decryption process

Let me also explain the encryption process.

KEY = WEP passphrase (either ola13 or MY KEY as seen above)

IV = Initialization vector

ICV = Integrity check value

  1. I get (IV) (DATA) (ICV) from the packet encrypted with QOS or DATA WEP
  2. I start RC4 on the (DATA) (ICV) With (IV) (KEY)
  3. From that moment on I have decrypted one (DATA) (ICV)
  4. I start CRC32 (DATES)
  5. I compare the CRC32 output with decrypted (ICV)
  6. If they match, the (KEY) is a hit
  7. If they do not fit together, they (KEY) is wrong

Is there a difference in the decryption of WEP Protected QOS and DATA or is it missing here a bit ..

Thank you in advance.

Brute Force – Is it safe to implement 15-byte token reset tokens?

For example, suppose you want to be extra careful and hack the token in the event of a database leak (tokens should expire anyway, but some may still be valid shortly after a leak). Also, you do not want to have useful information in the token, because catching emails is not difficult. In fact, you do not even want an incremental reset token ID because someone can see how many tokens have been issued (I do not know what they would do with it, but maybe you're a bit paranoid.

To have a way to bind it to a user while it is still hacking, you decide to take a 256-bit value generated by a CSPRNG, divide it in half, the first 128 bits as the identifier, and the second 128 bits to use as the identifier character. Both halves are included in the reset token URL, the database stores the first half in plain text and hashes the second half before saving.

You now have a 256-bit value. How do you encode it in the URL? If you only want to use letters and numbers, you need ln(2^256) / ln(36) ≈ 49.550 characters. Here you go.

I'm not saying that anyone using a long reset token does this this way, but this is a reasonable thing that would require a longer token.

Does this mean that a 15-character token is bad?

Not really. It only has about 77.5 bits of entropy (assuming it is generated by a CSPRNG it generates) need which is a bit low, but if you're not worried about an offline attack (hopefully your reset tokens will be short lived), that's reasonable. It just means that there is also a reasonable way to develop a 50-character reset token. And really, what do 35 extra characters do in a URL?