Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8130879

Browse files
Merge pull request #16 from maximmasiutin/master
Thank you for your great program! It is excellent, but today I was unable to decode secrets generated using the 512 hash algorithm widely used nowadays. I had to decode such secrets, so I modified the program, and now it supports such algorithms. I hope these contributions will be beneficial for the other users as well.
2 parents b6ed04f + 9777c3e commit 8130879

File tree

2 files changed

+92
-15
lines changed

2 files changed

+92
-15
lines changed

‎README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,39 @@ make OPENSSL=/usr/local/opt/openssl/include OPENSSL_LIB=-L/usr/local/opt/openssl
3636

3737
```
3838
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE
39+
```
40+
41+
## Run with different HMAC functions
42+
43+
The following hash functions are supported for HMAC, i.e. to generate keyed-hashed message authentication codes: "sha256" for JSON HS256 (HMAC using SHA-256), "sha384" for HS384 and "sha512" for HS512, respectively. You can specify the name of any other hash function exactly as it is named in the OpenSSL. If OpenSSL allows this hash function to be used for HMAC, then jwtcrack will try to decode the secret. However, since jwtcrack is only a decoder, there is no guarantee that this algorithm was actually used for encoding, let alone among the list of algorithms allowed for the "JSON Web Algorithms" RFC. See section 3.1. of the RFC 7518 for more details.
44+
45+
In the following example, we use a sha256 hash function that corresponds to JSON HS256 (HMAC-SHA256), see the "sha256" as a last command line parameter. Also, in this example we specify maximum secret length of 5 characters, and limit the alphabet to the following characters: ABCSNFabcsnf1234
46+
47+
```
48+
$ > ./jwtcrack eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.cAOIAifu3fykvhkHpbuhbvtH807-Z2rI1FS3vX1XMjE ABCSNFabcsnf1234 5 sha256
49+
```
50+
In the above example, the key is `Sn1f`, and it takes less than a second on an average notebook manufactured around 2019 (e.g. with an Intel CPU based on Ice Lake microarchitecture). GCC version 9.3.0 with "-O3" was used to compile the jwtcrack program. It was linked with the OpenSSL library version 1.1.1f under Linux Ubuntu 20.04.1 LTS.
51+
52+
Here, in the next example, we use "sha512" as a last command line parameter to specify HS512 (HMAC-SHA512), we also specify maximum secret length of 9 characters, and limit the alphabet to the following seven lowercase latin characters: "adimnps".
53+
54+
```
55+
$ > ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiYWRtaW4ifQ.RnWtv7Rjggm8LdMU3yLnz4ejgGAkIxoZwsCMuJlHMwTh7CJODDZWR8sVuNvo2ws25cbH9HWcp2n5WxpIZ9_v0g adimnps 9 sha512
3956
```
4057

41-
In the above example, the key is `Sn1f`. It takes approximately 2 seconds to crack on my Macbook.
58+
In the above example, the key is `adminpass`, and it takes about 15 seconds on average to decode on a notebook with Intel Core i7 1065G7 CPU on Ice Lake microarchitecture (2019), base frequency 1.30 GHz, max turbo 3.90 GHz). The combined number of CPU seconds consumed from each of the cores in the user mode due to multithreading is about 100 on average to decode that secret.
59+
60+
61+
Example of using "sha384":
62+
63+
```
64+
$ > ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJyb2xlIjoiYWRtaW4ifQ.31xCH3k8VRqB8l5qBy7RyqI2htyCskBy_4cIWpk3o43UkIMW-IcjTUEL_NyFXUWJ 0123456789 6 sha384
65+
```
66+
67+
## Measurement of time consumed by jwtcrack
68+
69+
```
70+
/usr/bin/time -f "Total number of CPU-seconds consumed directly from each of the CPU cores: %U\nElapsed real wall clock time used by the process: %E" ./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiYWRtaW4ifQ.RnWtv7Rjggm8LdMU3yLnz4ejgGAkIxoZwsCMuJlHMwTh7CJODDZWR8sVuNvo2ws25cbH9HWcp2n5WxpIZ9_v0g adimnps 9 sha512
71+
```
4272

4373
## Contribute
4474

‎main.c

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
/*
2+
3+
Copyright (c) 2017 Brendan Rius. All rights reserved
4+
5+
Configurable HMAC hash functions implemented in 2021 by Maxim Masiutin,
6+
see the "README.md" file for more details.
7+
8+
*/
9+
110
#include <stdlib.h>
211
#include <stdio.h>
312
#include <string.h>
@@ -29,7 +38,7 @@ size_t g_alphabet_len = 0;
2938
char *g_found_secret = NULL;
3039

3140
struct s_thread_data {
32-
EVP_MD *g_evp_md; // The hash function to apply the HMAC to
41+
constEVP_MD *g_evp_md; // The hash function to apply the HMAC to
3342

3443
// Holds the computed signature at each iteration to compare it with the original
3544
// signature
@@ -42,15 +51,15 @@ struct s_thread_data {
4251
size_t max_len; // And tries combinations up to a certain length
4352
};
4453

45-
void init_thread_data(struct s_thread_data *data, char starting_letter, size_t max_len) {
54+
void init_thread_data(struct s_thread_data *data, char starting_letter, size_t max_len, constEVP_MD*evp_md) {
4655
data->max_len = max_len;
4756
data->starting_letter = starting_letter;
48-
// The chosen hash function is SHA-256
49-
data->g_evp_md = (EVP_MD*) EVP_sha256();
57+
// The chosen hash function for HMAC
58+
data->g_evp_md = evp_md;
5059
// Allocate the buffer used to hold the calculated signature
51-
data->g_result = malloc(EVP_MAX_MD_SIZE);
60+
data->g_result = malloc(EVP_MAX_MD_SIZE);
5261
// Allocate the buffer used to hold the generated key
53-
data->g_buffer = malloc(max_len + 1);
62+
data->g_buffer = malloc(max_len + 1);
5463
}
5564

5665
void destroy_thread_data(struct s_thread_data *data) {
@@ -71,7 +80,7 @@ bool check(struct s_thread_data *data, const char *secret, size_t secret_len) {
7180
pthread_exit(NULL);
7281
}
7382

74-
// Hash to_encryptusing HMAC into result
83+
// Hash the "to_encrypt" buffer using HMAC into the "result" buffer
7584
HMAC(
7685
data->g_evp_md,
7786
(const unsigned char *) secret, secret_len,
@@ -150,18 +159,26 @@ char *brute_sequential(struct s_thread_data *data)
150159
return NULL;
151160
}
152161

153-
void usage(const char *cmd) {
154-
printf("%s <token> [alphabet] [max_len]\n"
155-
"Defaults: max_len=6, "
156-
"alphabet=eariotnslcudpmhgbfywkvxzjqEARIOTNSLCUDPMHGBFYWKVXZJQ0123456789", cmd);
162+
void usage(const char *cmd, const char *alphabet, const size_t max_len, const char *hmac_alg) {
163+
printf("%s <token> [alphabet] [max_len] [hmac_alg]\n"
164+
"Defaults: "
165+
"alphabet=%s, "
166+
"max_len=%zd, "
167+
"hmac_alg=%s\n", cmd, alphabet, max_len, hmac_alg);
157168
}
158169

159170
int main(int argc, char **argv) {
171+
172+
const EVP_MD *evp_md;
160173
size_t max_len = 6;
174+
175+
// by default, use OpenSSL EVP_sha256 which corresponds to JSON HS256 (HMAC-SHA256)
176+
const char *default_hmac_alg = "sha256";
177+
161178
g_alphabet = "eariotnslcudpmhgbfywkvxzjqEARIOTNSLCUDPMHGBFYWKVXZJQ0123456789";
162179

163180
if (argc < 2) {
164-
usage(argv[0]);
181+
usage(argv[0], g_alphabet, max_len, default_hmac_alg);
165182
return 1;
166183
}
167184

@@ -170,8 +187,38 @@ int main(int argc, char **argv) {
170187

171188
if (argc > 2)
172189
g_alphabet = argv[2];
190+
173191
if (argc > 3)
174-
max_len = (size_t) atoi(argv[3]);
192+
{
193+
int i3 = atoi(argv[3]);
194+
if (i3 > 0)
195+
{
196+
max_len = i3;
197+
} else
198+
{
199+
printf("Invalid max_len value %s (%d), defaults to %zd\n", argv[3], i3, max_len);
200+
}
201+
}
202+
203+
if (argc > 4)
204+
{
205+
evp_md = EVP_get_digestbyname(argv[4]);
206+
if (evp_md == NULL)
207+
printf("Unknown message digest %s, will use default %s\n", argv[4], default_hmac_alg);
208+
} else
209+
{
210+
evp_md = NULL;
211+
}
212+
213+
if (evp_md == NULL)
214+
{
215+
evp_md = EVP_get_digestbyname(default_hmac_alg);
216+
if (evp_md == NULL)
217+
{
218+
printf("Cannot initialize the default message digest %s, aborting\n", default_hmac_alg);
219+
return 1;
220+
}
221+
}
175222

176223
g_alphabet_len = strlen(g_alphabet);
177224

@@ -203,7 +250,7 @@ int main(int argc, char **argv) {
203250

204251
for (size_t i = 0; i < g_alphabet_len; i++) {
205252
pointers_data[i] = malloc(sizeof(struct s_thread_data));
206-
init_thread_data(pointers_data[i], g_alphabet[i], max_len);
253+
init_thread_data(pointers_data[i], g_alphabet[i], max_len, evp_md);
207254
pthread_create(&tid[i], NULL, (void *(*)(void *)) brute_sequential, pointers_data[i]);
208255
}
209256

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /