diff --git a/include/convert.h b/include/convert.h index d15b538ab..e87eba667 100644 --- a/include/convert.h +++ b/include/convert.h @@ -27,21 +27,20 @@ void u8_to_hex_lower (const u8 v, u8 hex[2]); void u32_to_hex_lower (const u32 v, u8 hex[8]); void u64_to_hex_lower (const u64 v, u8 hex[16]); -u8 int_to_base32 (const u8 c); -u8 base32_to_int (const u8 c); -u8 int_to_base64 (const u8 c); -u8 base64_to_int (const u8 c); - -u8 int_to_itoa32 (const u8 c); -u8 itoa32_to_int (const u8 c); -u8 int_to_itoa64 (const u8 c); -u8 itoa64_to_int (const u8 c); - -u8 int_to_bf64 (const u8 c); -u8 bf64_to_int (const u8 c); - -u8 int_to_lotus64 (const u8 c); -u8 lotus64_to_int (const u8 c); +u8 int_to_base32 (const u8 c); +u8 base32_to_int (const u8 c); +u8 int_to_base64 (const u8 c); +u8 base64_to_int (const u8 c); +u8 int_to_base64url (const u8 c); +u8 base64url_to_int (const u8 c); +u8 int_to_itoa32 (const u8 c); +u8 itoa32_to_int (const u8 c); +u8 int_to_itoa64 (const u8 c); +u8 itoa64_to_int (const u8 c); +u8 int_to_bf64 (const u8 c); +u8 bf64_to_int (const u8 c); +u8 int_to_lotus64 (const u8 c); +u8 lotus64_to_int (const u8 c); int base32_decode (u8 (*f) (const u8), const u8 *in_buf, int in_len, u8 *out_buf); int base32_encode (u8 (*f) (const u8), const u8 *in_buf, int in_len, u8 *out_buf); diff --git a/include/interface.h b/include/interface.h index 6c8f9e684..e11df9f9d 100644 --- a/include/interface.h +++ b/include/interface.h @@ -1336,8 +1336,8 @@ typedef enum display_len DISPLAY_LEN_MAX_16300 = 11 + 1 + 1248 + 1 + 40 + 1 + 32, DISPLAY_LEN_MIN_16400 = 10 + 32 + 32, DISPLAY_LEN_MAX_16400 = 10 + 32 + 32, - DISPLAY_LEN_MIN_16500 = 1 + 1 + 1 + 1 + 64, - DISPLAY_LEN_MAX_16500 = 2047 + 1 + 2047 + 1 + 128, + DISPLAY_LEN_MIN_16500 = 1 + 1 + 1 + 1 + 43, + DISPLAY_LEN_MAX_16500 = 2047 + 1 + 2047 + 1 + 86, DISPLAY_LEN_MIN_99999 = 1, DISPLAY_LEN_MAX_99999 = 55, diff --git a/src/convert.c b/src/convert.c index fcd58d9d9..a2aaae87f 100644 --- a/src/convert.c +++ b/src/convert.c @@ -429,6 +429,44 @@ u8 base64_to_int (const u8 c) return tbl[c]; } +u8 int_to_base64url (const u8 c) +{ + const u8 tbl[0x40] = + { + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, + 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2d, 0x5f, + }; + + return tbl[c]; +} + +u8 base64url_to_int (const u8 c) +{ + const u8 tbl[0x100] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + return tbl[c]; +} + u8 int_to_bf64 (const u8 c) { const u8 tbl[0x40] = diff --git a/src/interface.c b/src/interface.c index 78d96eda1..c024a2cfc 100644 --- a/src/interface.c +++ b/src/interface.c @@ -16216,17 +16216,17 @@ int jwt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED if (hashconfig->kern_type == (u32) -1) { - if (signature_len == 64) - { // it would be more accurate to base64 decode the header_pos buffer and then to string match HS256 - same goes for the other algorithms + if (signature_len == 43) + { hashconfig->kern_type = KERN_TYPE_JWT_HS256; } - else if (signature_len == 96) + else if (signature_len == 64) { hashconfig->kern_type = KERN_TYPE_JWT_HS384; } - else if (signature_len == 128) + else if (signature_len == 86) { hashconfig->kern_type = KERN_TYPE_JWT_HS512; } @@ -16237,15 +16237,15 @@ int jwt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED } else { - if ((hashconfig->kern_type == KERN_TYPE_JWT_HS256) && (signature_len == 64)) + if ((hashconfig->kern_type == KERN_TYPE_JWT_HS256) && (signature_len == 43)) { // OK } - else if ((hashconfig->kern_type == KERN_TYPE_JWT_HS384) && (signature_len == 96)) + else if ((hashconfig->kern_type == KERN_TYPE_JWT_HS384) && (signature_len == 64)) { // OK } - else if ((hashconfig->kern_type == KERN_TYPE_JWT_HS512) && (signature_len == 128)) + else if ((hashconfig->kern_type == KERN_TYPE_JWT_HS512) && (signature_len == 86)) { // OK } @@ -16257,8 +16257,6 @@ int jwt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED if (esalt_len > 4096) return (PARSER_SALT_LENGTH); - if (is_valid_hex_string (signature_pos, signature_len) == false) return (PARSER_SALT_ENCODING); - /** * store data */ @@ -16304,26 +16302,15 @@ int jwt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED // hash - if (signature_len == 64) - { - u32 *digest = (u32 *) hash_buf->digest; + u8 tmp_buf[100] = { 0 }; - digest[ 0] = hex_to_u32 ((const u8 *) &signature_pos[ 0]); - digest[ 1] = hex_to_u32 ((const u8 *) &signature_pos[ 8]); - digest[ 2] = hex_to_u32 ((const u8 *) &signature_pos[16]); - digest[ 3] = hex_to_u32 ((const u8 *) &signature_pos[24]); - digest[ 4] = hex_to_u32 ((const u8 *) &signature_pos[32]); - digest[ 5] = hex_to_u32 ((const u8 *) &signature_pos[40]); - digest[ 6] = hex_to_u32 ((const u8 *) &signature_pos[48]); - digest[ 7] = hex_to_u32 ((const u8 *) &signature_pos[56]); - digest[ 8] = 0; - digest[ 9] = 0; - digest[10] = 0; - digest[11] = 0; - digest[12] = 0; - digest[13] = 0; - digest[14] = 0; - digest[15] = 0; + base64_decode (base64url_to_int, signature_pos, signature_len, tmp_buf); + + if (signature_len == 43) + { + memcpy (hash_buf->digest, tmp_buf, 32); + + u32 *digest = (u32 *) hash_buf->digest; digest[0] = byte_swap_32 (digest[0]); digest[1] = byte_swap_32 (digest[1]); @@ -16334,18 +16321,11 @@ int jwt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED digest[6] = byte_swap_32 (digest[6]); digest[7] = byte_swap_32 (digest[7]); } - else if (signature_len == 96) + else if (signature_len == 64) { - u64 *digest = (u64 *) hash_buf->digest; + memcpy (hash_buf->digest, tmp_buf, 48); - digest[0] = hex_to_u64 ((const u8 *) &signature_pos[ 0]); - digest[1] = hex_to_u64 ((const u8 *) &signature_pos[ 16]); - digest[2] = hex_to_u64 ((const u8 *) &signature_pos[ 32]); - digest[3] = hex_to_u64 ((const u8 *) &signature_pos[ 48]); - digest[4] = hex_to_u64 ((const u8 *) &signature_pos[ 64]); - digest[5] = hex_to_u64 ((const u8 *) &signature_pos[ 80]); - digest[6] = 0; - digest[7] = 0; + u64 *digest = (u64 *) hash_buf->digest; digest[0] = byte_swap_64 (digest[0]); digest[1] = byte_swap_64 (digest[1]); @@ -16353,21 +16333,12 @@ int jwt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED digest[3] = byte_swap_64 (digest[3]); digest[4] = byte_swap_64 (digest[4]); digest[5] = byte_swap_64 (digest[5]); - digest[6] = byte_swap_64 (digest[6]); - digest[7] = byte_swap_64 (digest[7]); } - else if (signature_len == 128) + else if (signature_len == 86) { - u64 *digest = (u64 *) hash_buf->digest; + memcpy (hash_buf->digest, tmp_buf, 64); - digest[0] = hex_to_u64 ((const u8 *) &signature_pos[ 0]); - digest[1] = hex_to_u64 ((const u8 *) &signature_pos[ 16]); - digest[2] = hex_to_u64 ((const u8 *) &signature_pos[ 32]); - digest[3] = hex_to_u64 ((const u8 *) &signature_pos[ 48]); - digest[4] = hex_to_u64 ((const u8 *) &signature_pos[ 64]); - digest[5] = hex_to_u64 ((const u8 *) &signature_pos[ 80]); - digest[6] = hex_to_u64 ((const u8 *) &signature_pos[ 96]); - digest[7] = hex_to_u64 ((const u8 *) &signature_pos[112]); + u64 *digest = (u64 *) hash_buf->digest; digest[0] = byte_swap_64 (digest[0]); digest[1] = byte_swap_64 (digest[1]); @@ -20339,45 +20310,63 @@ int ascii_digest (hashcat_ctx_t *hashcat_ctx, char *out_buf, const size_t out_le if (hashconfig->kern_type == KERN_TYPE_JWT_HS256) { - snprintf (out_buf, out_len - 1, "%s.%08x%08x%08x%08x%08x%08x%08x%08x", - (char *) jwt->salt_buf, - digest_buf[0], - digest_buf[1], - digest_buf[2], - digest_buf[3], - digest_buf[4], - digest_buf[5], - digest_buf[6], - digest_buf[7]); + digest_buf[0] = byte_swap_32 (digest_buf[0]); + digest_buf[1] = byte_swap_32 (digest_buf[1]); + digest_buf[2] = byte_swap_32 (digest_buf[2]); + digest_buf[3] = byte_swap_32 (digest_buf[3]); + digest_buf[4] = byte_swap_32 (digest_buf[4]); + digest_buf[5] = byte_swap_32 (digest_buf[5]); + digest_buf[6] = byte_swap_32 (digest_buf[6]); + digest_buf[7] = byte_swap_32 (digest_buf[7]); + + memset (tmp_buf, 0, sizeof (tmp_buf)); + + memcpy (tmp_buf, digest_buf, 32); + + base64_encode (int_to_base64url, (const u8 *) tmp_buf, 32, (u8 *) ptr_plain); + + ptr_plain[43] = 0; } else if (hashconfig->kern_type == KERN_TYPE_JWT_HS384) { - u32 *ptr = digest_buf; + digest_buf64[0] = byte_swap_64 (digest_buf64[0]); + digest_buf64[1] = byte_swap_64 (digest_buf64[1]); + digest_buf64[2] = byte_swap_64 (digest_buf64[2]); + digest_buf64[3] = byte_swap_64 (digest_buf64[3]); + digest_buf64[4] = byte_swap_64 (digest_buf64[4]); + digest_buf64[5] = byte_swap_64 (digest_buf64[5]); - snprintf (out_buf, out_len - 1, "%s.%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", - (char *) jwt->salt_buf, - ptr[ 1], ptr[ 0], - ptr[ 3], ptr[ 2], - ptr[ 5], ptr[ 4], - ptr[ 7], ptr[ 6], - ptr[ 9], ptr[ 8], - ptr[11], ptr[10]); + memset (tmp_buf, 0, sizeof (tmp_buf)); + + memcpy (tmp_buf, digest_buf64, 48); + + base64_encode (int_to_base64url, (const u8 *) tmp_buf, 48, (u8 *) ptr_plain); + + ptr_plain[64] = 0; } else if (hashconfig->kern_type == KERN_TYPE_JWT_HS512) { - u32 *ptr = digest_buf; + digest_buf64[0] = byte_swap_64 (digest_buf64[0]); + digest_buf64[1] = byte_swap_64 (digest_buf64[1]); + digest_buf64[2] = byte_swap_64 (digest_buf64[2]); + digest_buf64[3] = byte_swap_64 (digest_buf64[3]); + digest_buf64[4] = byte_swap_64 (digest_buf64[4]); + digest_buf64[5] = byte_swap_64 (digest_buf64[5]); + digest_buf64[6] = byte_swap_64 (digest_buf64[6]); + digest_buf64[7] = byte_swap_64 (digest_buf64[7]); - snprintf (out_buf, out_len - 1, "%s.%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", - (char *) jwt->salt_buf, - ptr[ 1], ptr[ 0], - ptr[ 3], ptr[ 2], - ptr[ 5], ptr[ 4], - ptr[ 7], ptr[ 6], - ptr[ 9], ptr[ 8], - ptr[11], ptr[10], - ptr[13], ptr[12], - ptr[15], ptr[14]); + memset (tmp_buf, 0, sizeof (tmp_buf)); + + memcpy (tmp_buf, digest_buf64, 64); + + base64_encode (int_to_base64url, (const u8 *) tmp_buf, 64, (u8 *) ptr_plain); + + ptr_plain[86] = 0; } + + snprintf (out_buf, out_len - 1, "%s.%s", + (char *) jwt->salt_buf, + (char *) ptr_plain); } else if (hash_mode == 99999) { diff --git a/tools/test.pl b/tools/test.pl index 432bf7886..c1aeff0ef 100755 --- a/tools/test.pl +++ b/tools/test.pl @@ -34,7 +34,7 @@ use Crypt::UnixCrypt_XS qw (crypt_rounds fold_password base64_to_int24 block_to_ use Crypt::Skip32; use Crypt::OpenSSH::ChachaPoly; use JSON; -use MIME::Base64; +use MIME::Base64 qw (encode_base64url decode_base64url); use Authen::Passphrase::NTHash; use Authen::Passphrase::MySQL323; use Authen::Passphrase::PHPass; @@ -9376,7 +9376,7 @@ END_CODE { my ($header_base64) = split (/\./, $salt_buf); - my $header_jwt = decode_base64 ($header_base64); + my $header_jwt = decode_base64url ($header_base64); my $header = decode_json ($header_jwt); @@ -9384,22 +9384,22 @@ END_CODE if ($alg eq "HS256") { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&sha256, 64); + $hash_buf = hmac ($salt_buf, $word_buf, \&sha256, 64); } elsif ($alg eq "HS384") { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&sha384, 128); + $hash_buf = hmac ($salt_buf, $word_buf, \&sha384, 128); } elsif ($alg eq "HS512") { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&sha512, 128); + $hash_buf = hmac ($salt_buf, $word_buf, \&sha512, 128); } else { die "not supported hash\n"; } - $tmp_hash = sprintf ("%s.%s", $salt_buf, $hash_buf); + $tmp_hash = sprintf ("%s.%s", $salt_buf, encode_base64url ($hash_buf, "")); } elsif ($mode == 99999) { @@ -11092,8 +11092,8 @@ sub get_random_jwt_salt my $header_json = encode_json ($header); my $payload_json = encode_json ($payload); - my $header_base64 = encode_base64 ($header_json, ""); - my $payload_base64 = encode_base64 ($payload_json, ""); + my $header_base64 = encode_base64url ($header_json, ""); + my $payload_base64 = encode_base64url ($payload_json, ""); return $header_base64 . "." . $payload_base64; }