jwtear 0.2.0 → 1.0.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +8 -1
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +71 -0
- data/README.md +107 -27
- data/bin/jwtear +40 -115
- data/jwtear.gemspec +9 -3
- data/lib/jwtear.rb +15 -19
- data/lib/jwtear/errors.rb +11 -4
- data/lib/jwtear/helpers/extensions.rb +17 -0
- data/lib/jwtear/helpers/utils.rb +71 -0
- data/lib/jwtear/jwe.rb +102 -0
- data/lib/jwtear/jws.rb +80 -0
- data/lib/jwtear/token.rb +67 -0
- data/lib/jwtear/version.rb +1 -1
- data/plugins/bruteforce.rb +103 -0
- data/plugins/generate.rb +68 -0
- data/plugins/parse.rb +111 -0
- data/plugins/plugin-template.rb +32 -0
- data/plugins/wiki.rb +50 -0
- data/plugins/wiki/README.md +212 -0
- metadata +105 -16
- data/LICENSE.txt +0 -21
- data/lib/jwtear/algorithms.rb +0 -83
- data/lib/jwtear/extensions.rb +0 -41
- data/lib/jwtear/jwt.rb +0 -129
- data/lib/jwtear/utils.rb +0 -57
- data/modules/bruteforce.rb +0 -39
data/jwtear.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["KING SABRI"]
|
9
9
|
spec.email = ["king.sabri@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary = %q{JWTear, command-line tool
|
12
|
-
spec.description = %q{JWTear, command-line tool
|
11
|
+
spec.summary = %q{JWTear, a modular command-line tool to parse, create and manipulate JWT tokens for security testing purposes.}
|
12
|
+
spec.description = %q{JWTear, a modular command-line tool to parse, create and manipulate JWT tokens for security testing purposes.}
|
13
13
|
spec.homepage = "https://github.com/KINGSABRI/jwtear"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -18,5 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = ['jwtear']
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
21
|
+
spec.add_dependency 'gli', '~> 2.19', '>= 2.19.0'
|
22
|
+
spec.add_dependency 'json-jwt', '~> 1.10', '>= 1.10.2'
|
23
|
+
spec.add_dependency 'jwe', "~> 0.4.0"
|
24
|
+
spec.add_dependency 'tty-markdown', "~> 0.6.0"
|
25
|
+
spec.add_dependency 'tty-pager', "~> 0.12.1"
|
26
|
+
|
27
|
+
# spec.add_development_dependency('rake', '~> 0.9.2.2')
|
22
28
|
end
|
data/lib/jwtear.rb
CHANGED
@@ -1,25 +1,21 @@
|
|
1
|
-
# Standard libraries
|
2
|
-
require 'base64'
|
3
|
-
require 'json'
|
4
|
-
require 'digest'
|
5
|
-
require 'openssl'
|
6
|
-
require 'open-uri'
|
7
|
-
|
8
1
|
# JWTear
|
9
2
|
require_relative 'jwtear/version'
|
10
3
|
require_relative 'jwtear/errors'
|
11
|
-
require_relative 'jwtear/
|
12
|
-
require_relative 'jwtear/
|
13
|
-
require_relative 'jwtear/
|
14
|
-
|
4
|
+
require_relative 'jwtear/helpers/utils'
|
5
|
+
require_relative 'jwtear/helpers/extensions'
|
6
|
+
require_relative 'jwtear/token'
|
15
7
|
|
16
|
-
|
17
|
-
|
8
|
+
# External gems
|
9
|
+
require 'json/jwt'
|
10
|
+
require 'tty-markdown'
|
11
|
+
require 'tty-pager'
|
12
|
+
require 'colorize'
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# end
|
14
|
+
module JWTear
|
15
|
+
# extend JWTear::Helpers::Extensions::Print
|
16
|
+
# include JWTear::Helpers::Extensions::Print
|
17
|
+
# Kernel.include JWTear::Helpers::Extensions::Print
|
18
|
+
# autoload(:Print, 'jwtear/helpers/extensions')
|
25
19
|
end
|
20
|
+
|
21
|
+
|
data/lib/jwtear/errors.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
module JWTear
|
2
2
|
|
3
3
|
# Token
|
4
|
-
class InvalidTokenError <
|
4
|
+
# class InvalidTokenError < JSON::JWT::InvalidFormat; end
|
5
5
|
|
6
6
|
# Algorithm Errors
|
7
|
-
class AlgorithmRequiresKeyError < TypeError; end
|
8
|
-
class AlgorithmUnknownError <
|
9
|
-
end
|
7
|
+
# class AlgorithmRequiresKeyError < JSON::JWT::TypeError; end
|
8
|
+
# class AlgorithmUnknownError < JSON::JWS::UnexpectedAlgorithm; end
|
9
|
+
# class InvalidFormat < JSON::JWT::InvalidFormat; end
|
10
|
+
# class Error < StandardError; end
|
11
|
+
|
12
|
+
# class MissingOption < CustomExit
|
13
|
+
#
|
14
|
+
# end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module JWTear
|
2
|
+
module Helpers
|
3
|
+
module Extensions
|
4
|
+
# Add print styles
|
5
|
+
module Print
|
6
|
+
def print_status(msg); puts "[*] ".blue + "#{msg}"; end
|
7
|
+
def print_good(msg); puts "[+] ".green + "#{msg}"; end
|
8
|
+
def print_error(msg); puts "[x] ".red + "#{msg}"; end
|
9
|
+
def print_bad(msg); puts "[!] ".red + "#{msg}"; end
|
10
|
+
def print_warning(msg); puts "[!] ".yellow + "#{msg}"; end
|
11
|
+
def print_h1(msg); puts "-[" + "#{msg}".green.bold + "]----"; end
|
12
|
+
def print_h2(msg); puts "[+] ".green + "#{msg}:" ; end
|
13
|
+
def print_h3(*msg); print " - ".cyan.bold + "#{msg[0]}:" " #{msg[1..-1].join(' ')}\n" ; end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module JWTear
|
2
|
+
module Helpers
|
3
|
+
module Utils
|
4
|
+
|
5
|
+
# Check latest version
|
6
|
+
def latest_version
|
7
|
+
begin
|
8
|
+
current_version = JWTear::VERSION
|
9
|
+
rubygem_api = JSON.parse open("https://rubygems.org/api/v1/versions/jwtear.json").read
|
10
|
+
remote_version = rubygem_api.first["number"]
|
11
|
+
latest = remote_version.eql?(current_version)? true : false
|
12
|
+
|
13
|
+
latest ? current_version : remote_version
|
14
|
+
rescue Exception => e
|
15
|
+
print_bad " Couldn't check the latest version, please check internet connectivity."
|
16
|
+
exit!
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# read key as a string or from file(eg. pub_key.pem)
|
21
|
+
def read_key(key)
|
22
|
+
if key
|
23
|
+
File.file?(key)? File.read(key) : key
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# check_dependencies
|
28
|
+
# check dependencies for plugins and throw a gentle error if not installed
|
29
|
+
# @param deps [Hash]
|
30
|
+
# The key is the library to be require, the key is the gem to be required
|
31
|
+
# @example
|
32
|
+
# deps = {'async-io' => 'async/ip'}
|
33
|
+
# check_dependencies(deps)
|
34
|
+
#
|
35
|
+
def check_dependencies(deps={})
|
36
|
+
return if deps.empty?
|
37
|
+
missing = []
|
38
|
+
|
39
|
+
deps.each do |gem, req|
|
40
|
+
begin
|
41
|
+
require req
|
42
|
+
rescue LoadError
|
43
|
+
missing << gem
|
44
|
+
end
|
45
|
+
end
|
46
|
+
ensure
|
47
|
+
unless missing.empty?
|
48
|
+
print_error "Missing dependencies!"
|
49
|
+
print_warning "Please install as follows:"
|
50
|
+
puts "gem install #{missing.join(' ')}"
|
51
|
+
exit!
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# JWTear's logo
|
56
|
+
def banner
|
57
|
+
%Q{\n 888888 888 888 88888888888
|
58
|
+
"88b 888 o 888 888
|
59
|
+
888 888 d8b 888 888
|
60
|
+
888 888 d888b 888 888 .d88b. 8888b. 888d888
|
61
|
+
888 888d88888b888 888 d8P Y8b "88b 888P"
|
62
|
+
888 88888P Y88888 888 88888888 .d888888 888
|
63
|
+
88P 8888P Y8888 888 Y8b. 888 888 888
|
64
|
+
888 888P Y888 888 "Y8888 "Y888888 888
|
65
|
+
.d88P v#{JWTear::VERSION}
|
66
|
+
.d88P"
|
67
|
+
888P" }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/jwtear/jwe.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'jwe'
|
2
|
+
|
3
|
+
module JWTear
|
4
|
+
# JWE
|
5
|
+
# Takes a parsed token from JSON::JWT#decode
|
6
|
+
#
|
7
|
+
class JWE
|
8
|
+
include JWTear::Helpers::Extensions::Print
|
9
|
+
|
10
|
+
attr_accessor :header, :encrypted_key, :iv, :cipher_text, :authentication_tag,
|
11
|
+
:kid, :auth_data, :plaintext, :alg, :enc, :zip, :cek,
|
12
|
+
:iss, :sub, :iat
|
13
|
+
|
14
|
+
# parse
|
15
|
+
# is a basic parser for JWE token
|
16
|
+
#
|
17
|
+
# @param token [String]
|
18
|
+
# parsed token string
|
19
|
+
#
|
20
|
+
# @return [Self]
|
21
|
+
#
|
22
|
+
def parse(token)
|
23
|
+
jwt = JSON::JWT.decode(token, :skip_decryption, :skip_verification)
|
24
|
+
@header = jwt.header
|
25
|
+
@encrypted_key = jwt.send(:jwe_encrypted_key)
|
26
|
+
@iv = jwt.iv
|
27
|
+
@cipher_text = jwt.cipher_text
|
28
|
+
@authentication_tag = jwt.send(:authentication_tag)
|
29
|
+
@algorithm = jwt.algorithm
|
30
|
+
@auth_data = jwt.auth_data
|
31
|
+
@plaintext = jwt.send(:plain_text)
|
32
|
+
@kid = jwt.kid
|
33
|
+
@alg = @header["alg"]
|
34
|
+
@typ = @header["typ"]
|
35
|
+
@cty = @header["cty"]
|
36
|
+
@enc = @header["enc"]
|
37
|
+
@zip = @header["zip"]
|
38
|
+
@iat = @encrypted_key["iat"]
|
39
|
+
@iss = @encrypted_key["iss"]
|
40
|
+
@cek = @encrypted_key
|
41
|
+
self
|
42
|
+
rescue JSON::JWS::UnexpectedAlgorithm => e
|
43
|
+
puts e.full_message
|
44
|
+
rescue JSON::JWT::InvalidFormat => e
|
45
|
+
print_error e.message
|
46
|
+
puts token
|
47
|
+
exit!
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_json_presentation
|
51
|
+
header = @header
|
52
|
+
if is_encrypted?(@encrypted_key)
|
53
|
+
encrypted_key = Base64.urlsafe_encode64(@encrypted_key, padding: false)
|
54
|
+
else
|
55
|
+
encrypted_key = @encrypted_key.to_json
|
56
|
+
end
|
57
|
+
iv = Base64.urlsafe_encode64(@iv)
|
58
|
+
cipher_text = Base64.urlsafe_encode64(@cipher_text, padding: false)
|
59
|
+
authentication_tag = Base64.urlsafe_encode64(@authentication_tag, padding: false)
|
60
|
+
|
61
|
+
"#{header.to_json}" + "●" +
|
62
|
+
"#{encrypted_key}" + "●" +
|
63
|
+
"#{iv}" + "●" +
|
64
|
+
"#{cipher_text}" + "●" +
|
65
|
+
"#{authentication_tag}"
|
66
|
+
end
|
67
|
+
|
68
|
+
# generate_jwe
|
69
|
+
# generate JWE token
|
70
|
+
#
|
71
|
+
# @param header [JSON]
|
72
|
+
# @param payload [JSON]
|
73
|
+
# @param key [String]
|
74
|
+
#
|
75
|
+
# @return [String] the generated token
|
76
|
+
#
|
77
|
+
def generate_jwe(header:, payload:, key:)
|
78
|
+
key = OpenSSL::PKey::RSA.new(key)
|
79
|
+
jwt = JSON::JWT.new(JSON.parse(payload, symbolize_names: true))
|
80
|
+
jwt.header = JSON.parse(header, symbolize_names: true)
|
81
|
+
::JWE.encrypt(payload, key, enc: jwt.header[:enc]) # I had to use this gem as json-jwt does not support A192GCM AFAIK
|
82
|
+
rescue TypeError => e
|
83
|
+
print_bad "Invalid data type."
|
84
|
+
print_warning "Make sure your public/private key file exists."
|
85
|
+
rescue ArgumentError => e
|
86
|
+
print_error e.message
|
87
|
+
print_warning "Make sure that you have a proper header."
|
88
|
+
puts jwt.header
|
89
|
+
rescue OpenSSL::PKey::RSAError => e
|
90
|
+
print_error "#{e.message} '#{key}'"
|
91
|
+
print_warning "Make sure your public/private key file exists."
|
92
|
+
exit!
|
93
|
+
end
|
94
|
+
|
95
|
+
def is_encrypted?(item)
|
96
|
+
JSON.parse item
|
97
|
+
false
|
98
|
+
rescue JSON::ParserError
|
99
|
+
true
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/jwtear/jws.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module JWTear
|
2
|
+
# JWS
|
3
|
+
# Takes a parsed token from JSON::JWT#decode
|
4
|
+
#
|
5
|
+
class JWS
|
6
|
+
include JWTear::Helpers::Extensions::Print
|
7
|
+
|
8
|
+
attr_accessor :header, :payload, :signature,
|
9
|
+
:typ, :cty, :alg, :kid, :jku,
|
10
|
+
:iss, :sub, :iat, :exp, :aud, :hd,
|
11
|
+
:azp, :email, :at_hash, :email_verified
|
12
|
+
|
13
|
+
# parse
|
14
|
+
# is a basic parser for JWS token
|
15
|
+
#
|
16
|
+
# @param token [String]
|
17
|
+
# parsed token string
|
18
|
+
#
|
19
|
+
# @return [Self]
|
20
|
+
#
|
21
|
+
def parse(token)
|
22
|
+
jwt = JSON::JWT.decode(token, :skip_verification)
|
23
|
+
@header = jwt.header
|
24
|
+
@payload = jwt.to_h
|
25
|
+
@signature = jwt.signature
|
26
|
+
@alg = @header["alg"]
|
27
|
+
@typ = @header["typ"]
|
28
|
+
@cty = @header["cty"]
|
29
|
+
@kid = @header["kid"]
|
30
|
+
@jku = @header["jku"]
|
31
|
+
@iat = @payload["iat"]
|
32
|
+
self
|
33
|
+
rescue JSON::JWT::InvalidFormat => e
|
34
|
+
print_error e.message
|
35
|
+
puts token
|
36
|
+
exit!
|
37
|
+
rescue Exception => e
|
38
|
+
puts e.full_message
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_json_presentation
|
42
|
+
"#{@header.to_json}" + "●" + "#{@payload.to_json}" + "●" + "#{Base64.urlsafe_encode64(@signature, padding: false)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
# generate_jws
|
46
|
+
# generate JWS token
|
47
|
+
#
|
48
|
+
# @param header [JSON]
|
49
|
+
# @param payload [JSON]
|
50
|
+
# @param key [String]
|
51
|
+
#
|
52
|
+
# @return [String] the generated token
|
53
|
+
#
|
54
|
+
def generate_jws(header:, payload:, key:)
|
55
|
+
jwt = JSON::JWT.new(JSON.parse(payload, symbolize_names: true))
|
56
|
+
jwt.header = JSON.parse(header, symbolize_names: true)
|
57
|
+
handle_signing(jwt, key)
|
58
|
+
rescue JSON::JWS::UnexpectedAlgorithm => e
|
59
|
+
puts "Unexpected algorithm '#{jwt.header[:alg]}'."
|
60
|
+
puts e.message
|
61
|
+
exit!
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# handle_signing
|
67
|
+
# Handles the algorithm 'none'.
|
68
|
+
# @param jwt [JSON]
|
69
|
+
# @param key [String]
|
70
|
+
#
|
71
|
+
def handle_signing(jwt, key=nil)
|
72
|
+
if jwt.alg =~ /none/i
|
73
|
+
jwt.to_s
|
74
|
+
else
|
75
|
+
raise JSON::JWS::UnexpectedAlgorithm.new("Encryption algorithm '#{jwt.alg}' requires key.") if key.nil?
|
76
|
+
jwt.sign(key).to_s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/jwtear/token.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative 'jws'
|
2
|
+
require_relative 'jwe'
|
3
|
+
|
4
|
+
module JWTear
|
5
|
+
class Token
|
6
|
+
include JWTear::Helpers::Extensions::Print
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@jws = JWS.new
|
10
|
+
@jwe = JWE.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# parse
|
14
|
+
# An interface for JWS and JWE parse operation.
|
15
|
+
# @param token [String]
|
16
|
+
#
|
17
|
+
# @return [JWS|JWE]
|
18
|
+
def parse(token)
|
19
|
+
token_segments = token.split('.').size
|
20
|
+
if token_segments <= 3 # JWS
|
21
|
+
@jws.parse(token)
|
22
|
+
else # JWE
|
23
|
+
@jwe.parse(token)
|
24
|
+
end
|
25
|
+
rescue Exception => e
|
26
|
+
print_error "Unknown Exception: #{method(__method__).owner}"
|
27
|
+
print_warning 'Please report the issue to: https://github.com/KINGSABRI/jwtear/issues'.underline
|
28
|
+
puts e
|
29
|
+
puts e.backtrace
|
30
|
+
exit!
|
31
|
+
end
|
32
|
+
|
33
|
+
# generate
|
34
|
+
# An interface for JWS and JWE token generation operation.
|
35
|
+
# @param type [Symbol]
|
36
|
+
# @param header [JSON]
|
37
|
+
# @param payload [JSON]
|
38
|
+
# @param key [String]
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# token = JWTear::Token.new
|
42
|
+
# token.generate(:jws, header: '{"alg":"HS256","typ":"JWT"}', payload: '{"user":"admin"}', key: "P@ssw0rd123")
|
43
|
+
#
|
44
|
+
# @return [JWS | JWE]
|
45
|
+
def generate(type, header:, payload:, key:)
|
46
|
+
case type
|
47
|
+
when :jws
|
48
|
+
@jws.generate_jws(header:header , payload:payload , key:key)
|
49
|
+
when :jwe
|
50
|
+
@jwe.generate_jwe(header:header , payload:payload , key:key)
|
51
|
+
else
|
52
|
+
print_error "Unknown type: #{type}"
|
53
|
+
raise
|
54
|
+
end
|
55
|
+
rescue JSON::ParserError => e
|
56
|
+
print_error "Unexpected Token."
|
57
|
+
puts e.message
|
58
|
+
rescue Exception => e
|
59
|
+
method = method(__method__)
|
60
|
+
print_error "Unknown Exception: #{method.owner}##{method.name}"
|
61
|
+
print_warning 'Please report the issue to: https://github.com/KINGSABRI/jwtear/issues'.underline
|
62
|
+
puts e.full_message
|
63
|
+
exit!
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/jwtear/version.rb
CHANGED
@@ -0,0 +1,103 @@
|
|
1
|
+
module JWTear
|
2
|
+
module CLI
|
3
|
+
extend GLI::App
|
4
|
+
extend JWTear::Helpers::Extensions::Print
|
5
|
+
|
6
|
+
desc %Q{plugin to offline bruteforce and crack token's signature.}
|
7
|
+
command [:bruteforce, :bfs] do |c|
|
8
|
+
c.desc 'Token to crack its key.'
|
9
|
+
c.arg_name 'JWT_TOKEN'
|
10
|
+
c.flag [:t, :token], required: true
|
11
|
+
|
12
|
+
c.desc 'Password or password list to bruteforce the signature'
|
13
|
+
c.arg_name 'PASS_LIST'
|
14
|
+
c.flag [:l, :p, :list, :password], required: true
|
15
|
+
|
16
|
+
c.desc "Run verbosely."
|
17
|
+
c.switch [:v, :verbose], negatable: false
|
18
|
+
|
19
|
+
c.example %Q{jwtear bruteforce -t TOKEN -l rockyou.list -v}
|
20
|
+
c.example %Q{jwtear bruteforce -t TOKEN -l P@ssw0rd123}
|
21
|
+
|
22
|
+
c.action do |_, options, _|
|
23
|
+
begin
|
24
|
+
bf = Bruteforce.new(options[:token], options[:list])
|
25
|
+
bf.run(options[:verbose])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Bruteforce
|
33
|
+
include JWTear::Helpers::Extensions::Print
|
34
|
+
include JWTear::Helpers::Utils
|
35
|
+
|
36
|
+
def initialize(token, list)
|
37
|
+
deps = {'async-io' => 'async/io'}
|
38
|
+
check_dependencies(deps)
|
39
|
+
@token = Token.new
|
40
|
+
@jws = @token.parse(token)
|
41
|
+
@list = list
|
42
|
+
end
|
43
|
+
|
44
|
+
def run(verbose=false)
|
45
|
+
keys = handle_key
|
46
|
+
case
|
47
|
+
when keys.kind_of?(Enumerator::Lazy)
|
48
|
+
keys.each do |key|
|
49
|
+
print_status "Trying password: #{key}" if verbose
|
50
|
+
|
51
|
+
gen_token = @token.generate(:jws, header: @jws.header.to_json, payload:@jws.payload.to_json , key: key)
|
52
|
+
sig = gen_token.split('.').last
|
53
|
+
if sig == Base64.urlsafe_encode64(@jws.signature, padding: false)
|
54
|
+
print_good "Password found: #{key}"
|
55
|
+
puts gen_token
|
56
|
+
exit!
|
57
|
+
else
|
58
|
+
print_bad "Invalid key: #{key}" if verbose
|
59
|
+
# puts gen_token if verbose
|
60
|
+
end
|
61
|
+
end
|
62
|
+
when keys.kind_of?(String)
|
63
|
+
gen_token = @token.generate(:jws, header: @jws.header.to_json, payload:@jws.payload.to_json , key: keys)
|
64
|
+
sig = gen_token.split('.').last
|
65
|
+
if sig == Base64.urlsafe_encode64(@jws.signature, padding: false)
|
66
|
+
print_good "Password found: #{keys}"
|
67
|
+
puts gen_token
|
68
|
+
else
|
69
|
+
print_bad "Invalid key: #{keys}"
|
70
|
+
end
|
71
|
+
|
72
|
+
else
|
73
|
+
print_error "Unknown key type"
|
74
|
+
raise
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def handle_key
|
80
|
+
if File.file?(@list)
|
81
|
+
read_wordlist(@list)
|
82
|
+
else
|
83
|
+
@list
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def read_wordlist(file)
|
88
|
+
if File.file?(file)
|
89
|
+
print_status "Found '#{file}' file."
|
90
|
+
File.readlines(file, chomp: true)
|
91
|
+
.lazy
|
92
|
+
.map(&:strip)
|
93
|
+
.reject(&:empty?)
|
94
|
+
.reject(&:nil?)
|
95
|
+
else
|
96
|
+
print_bad "File not found. #{file}"
|
97
|
+
exit!
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|