jwtear 0.1.1 → 0.1.2
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 +4 -4
- data/README.md +1 -1
- data/bin/jwtear +10 -8
- data/lib/jwtear/algorithms.rb +1 -0
- data/lib/jwtear/errors.rb +4 -0
- data/lib/jwtear/jwt.rb +27 -24
- data/lib/jwtear/utils.rb +15 -4
- data/lib/jwtear/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd40b5099b880a09ed4277d0964f85d0255a1be9
|
4
|
+
data.tar.gz: 9b016a13f78d711c0b1e4e61de499ed5bdfa30fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d2d82eeabaa80693048981de0f3e3c7ea5688ad3d4b833f9b0893050e04c442adba291a696ac143bfc7f5521b778624e4ed057abba887bbd040a710e2feef35
|
7
|
+
data.tar.gz: 4506e71a5e670fd92c23584e9aa2d2a9cd1e0a5dd235f683b7f60ebd9b3269b705fe6634fff22a9991815237e6a044575b836e26c9c7fb7a703c12c9a9708a5f
|
data/README.md
CHANGED
@@ -45,7 +45,7 @@ Usage:
|
|
45
45
|
jwtear <OPTIONS>
|
46
46
|
|
47
47
|
Example:
|
48
|
-
jwtear --generate-token --header '{"typ":"JWT","alg":"
|
48
|
+
jwtear --generate-token --header '{"typ":"JWT","alg":"HS256"}' --payload '{"login":"admin"}' --key 'P@ssw0rd!'
|
49
49
|
jwtear --generate-sig --header '{"typ":"JWT","alg":"HS256"}' --payload '{"login":"admin"}' --key 'P@ssw0rd!'
|
50
50
|
jwtear --parse 'eyJwI...6IfJ9.kxrMS...MjAMm.zEybN...TU2Njk3ZmE3OA'
|
51
51
|
|
data/bin/jwtear
CHANGED
@@ -22,21 +22,21 @@ option_parser.banner = "#{"JWTear".bold} - Parse, create and manipulate JWT toke
|
|
22
22
|
option_parser.set_summary_indent ' '
|
23
23
|
option_parser.separator "\nHelp menu:".underline
|
24
24
|
option_parser.on('-p', '--parse JWT_TOKEN' , 'Parse JWT token') {|v| options[:parse] = v}
|
25
|
-
option_parser.on('--generate-token', 'Generate JWT token.') {|v| options[:generate_token] = v}
|
26
|
-
option_parser.on('--generate-sig', 'Generate JWT signature.') {|v| options[:generate_sig] = v}
|
27
|
-
option_parser.on('--header HEADER',
|
25
|
+
option_parser.on('-t', '--generate-token', 'Generate JWT token.') {|v| options[:generate_token] = v}
|
26
|
+
option_parser.on('-s', '--generate-sig', 'Generate JWT signature.') {|v| options[:generate_sig] = v}
|
27
|
+
option_parser.on('-H', '--header HEADER',
|
28
28
|
'JWT header (JSON format). (required for generate-token and generate-sig)',
|
29
29
|
' eg. {"typ":"JWT","alg":"HS256"} | Supported algorithms: [HS256, RS512, etc]'
|
30
30
|
) {|v| options[:header] = v}
|
31
|
-
option_parser.on('--payload PAYLOAD' ,
|
31
|
+
option_parser.on('-P', '--payload PAYLOAD' ,
|
32
32
|
'JWT payload (JSON format). (required for generate-token and generate-sig)',
|
33
33
|
' eg. {"login":"admin"}'
|
34
34
|
) {|v| options[:payload] = v}
|
35
|
-
option_parser.on('--alg ALGORITHM',
|
35
|
+
option_parser.on('-g', '--alg ALGORITHM',
|
36
36
|
'Force algorithm type when generating a new token (ignore the one in header). (optional with generate-token)',
|
37
37
|
' Supported algorithms: [HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512]'
|
38
38
|
) {|v| options[:alg] = v}
|
39
|
-
option_parser.on('--key SECRET',
|
39
|
+
option_parser.on('-k', '--key SECRET',
|
40
40
|
'Secret Key for symmetric encryption. (required for generate-token and generate-sig. Accept password as a string or a file)',
|
41
41
|
' eg. P@ssw0rd | eg. public_key.pem'
|
42
42
|
) {|v| options[:key] = v}
|
@@ -47,7 +47,7 @@ option_parser.on('--key SECRET',
|
|
47
47
|
option_parser.on('-h', '--help', 'Show this help message') {puts JWTear::Utils.banner , option_parser; exit!}
|
48
48
|
option_parser.on_tail "\nUsage:\n".underline + "jwtear <OPTIONS>"
|
49
49
|
option_parser.on_tail "\nExample:".underline
|
50
|
-
option_parser.on_tail %Q{jwtear --generate-token --header #{"'".bold}{"typ":"JWT","alg":"
|
50
|
+
option_parser.on_tail %Q{jwtear --generate-token --header #{"'".bold}{"typ":"JWT","alg":"HS256"}#{"'".bold} --payload #{"'".bold}{"login":"admin"}#{"'".bold} --key 'P@ssw0rd!'}
|
51
51
|
option_parser.on_tail %Q{jwtear --generate-sig --header #{"'".bold}{"typ":"JWT","alg":"HS256"}#{"'".bold} --payload #{"'".bold}{"login":"admin"}#{"'".bold} --key 'P@ssw0rd!'}
|
52
52
|
option_parser.on_tail %Q{jwtear --parse #{"'".bold}eyJwI...6IfJ9#{'.'.bold}kxrMS...MjAMm#{'.'.bold}zEybN...TU2Njk3ZmE3OA#{"'".bold}\n\n}
|
53
53
|
|
@@ -55,6 +55,7 @@ begin
|
|
55
55
|
option_parser.parse!
|
56
56
|
include JWTear::Utils
|
57
57
|
case
|
58
|
+
# parse
|
58
59
|
when options[:parse]
|
59
60
|
jwt = JWTear::JWT.new(options[:parse])
|
60
61
|
jwt_parsed = jwt.parse
|
@@ -70,9 +71,11 @@ begin
|
|
70
71
|
puts "[+] ".dark_green + "Signature (envelope segment) - encoded:".bold.underline
|
71
72
|
puts "#{Base64.urlsafe_encode64(jwt.signature)}"
|
72
73
|
|
74
|
+
# checking missing for generate_token
|
73
75
|
when options[:generate_token] && (options[:header] || options[:payload] || options[:key]).nil?
|
74
76
|
puts '[!] '.red + "Missing mandatory switch(es) '--header/--payload/--alg/--key'"
|
75
77
|
|
78
|
+
# checking missing for generate_sig
|
76
79
|
when options[:generate_sig] && (options[:header] || options[:payload] || options[:key]).nil?
|
77
80
|
puts '[!] '.red + "Missing mandatory switch(es) '--header/--payload/--key'"
|
78
81
|
|
@@ -112,7 +115,6 @@ rescue OptionParser::InvalidOption => e
|
|
112
115
|
rescue Exception => e
|
113
116
|
puts "[x] ".red + "Unknown Exception: option parser"
|
114
117
|
puts '[!] '.yellow + 'Please report the issue at: https://github.com/KINGSABRI/jwtear/issues'.underline
|
115
|
-
puts e.backtrace
|
116
118
|
puts e.backtrace_locations
|
117
119
|
puts e
|
118
120
|
end
|
data/lib/jwtear/algorithms.rb
CHANGED
data/lib/jwtear/errors.rb
CHANGED
data/lib/jwtear/jwt.rb
CHANGED
@@ -8,8 +8,8 @@ module JWTear
|
|
8
8
|
include JWTear::Utils
|
9
9
|
|
10
10
|
# @!attribute [rw] token [String] generated or parsed token
|
11
|
-
# @!attribute [rw] header [
|
12
|
-
# @!attribute [rw] payload [
|
11
|
+
# @!attribute [rw] header [Hash]
|
12
|
+
# @!attribute [rw] payload [Hash]
|
13
13
|
attr_accessor :token, :header, :payload
|
14
14
|
# @!attribute [rw] alg [String] generated or parsed algorithm
|
15
15
|
# @!attribute [rw] key [String] given encryption key
|
@@ -18,7 +18,7 @@ module JWTear
|
|
18
18
|
# @!attribute [r] json [JSON] given or parsed json
|
19
19
|
# @!attribute [r] hash [Hash] hash result of parsing given or generated json
|
20
20
|
attr_reader :json, :hash
|
21
|
-
# @!attribute [r] signature [String] generated or parsed signature
|
21
|
+
# @!attribute [r] signature [String] generated or parsed signature.
|
22
22
|
# @!attribute [r] rsa_private [String] generated private private key
|
23
23
|
# @!attribute [r] rsa_public [String] generated or given public key
|
24
24
|
attr_reader :signature, :rsa_private, :rsa_public
|
@@ -33,27 +33,28 @@ module JWTear
|
|
33
33
|
#
|
34
34
|
# @param token String
|
35
35
|
def parse(token=@token)
|
36
|
+
is_token?(token)
|
36
37
|
_token = token.split('.')
|
37
|
-
@header = JSON.parse(
|
38
|
+
@header = JSON.parse(decode(_token[0]))
|
38
39
|
@type, @alg = @header['type'], @header['alg']
|
39
|
-
@payload = JSON.parse(
|
40
|
-
@signature =
|
40
|
+
@payload = JSON.parse(decode(_token[1]))
|
41
|
+
@signature = decode(_token[2]) unless (_token[2].nil? or _token[2].empty?)
|
41
42
|
set_hash_and_json
|
42
43
|
end
|
43
44
|
|
44
45
|
# build the hash and Json format from the parsed or generated token
|
45
46
|
def set_hash_and_json
|
46
|
-
@
|
47
|
-
@
|
47
|
+
@hash = {header: @header, payload: @payload, signature: encode(@signature)}
|
48
|
+
@json = "#{@header.to_json}.#{@payload.to_json}.#{encode(@signature)}"
|
48
49
|
end
|
49
50
|
|
50
51
|
# generate signature
|
51
52
|
#
|
52
53
|
# @param data [String]. 'Base64.encode(header)'.'Base64.encode(payload)'>
|
53
|
-
# @param alg [String] supported algorithms:
|
54
|
+
# @param alg [String] supported algorithms: @see [Algorithms#supported_algorithms]
|
54
55
|
# @param key String
|
55
56
|
#
|
56
|
-
# @return [
|
57
|
+
# @return [Self] the generate signature
|
57
58
|
#
|
58
59
|
def generate_sig(data, alg, key)
|
59
60
|
begin
|
@@ -66,9 +67,9 @@ module JWTear
|
|
66
67
|
@rsa_private = rsa[:private_key]
|
67
68
|
@signature = rsa[:signature]
|
68
69
|
when /^ES/
|
69
|
-
ecdsa(data, alg)
|
70
|
+
@signature = ecdsa(data, alg)
|
70
71
|
when /none/i
|
71
|
-
none
|
72
|
+
@signature = none
|
72
73
|
else
|
73
74
|
raise AlgorithmUnknownError
|
74
75
|
end
|
@@ -93,22 +94,24 @@ module JWTear
|
|
93
94
|
end
|
94
95
|
|
95
96
|
# generate JWT token
|
96
|
-
# by default, generate_token uses the given json header to detect the algorithm.
|
97
|
-
# and force it to you another algorithm.
|
97
|
+
# by default, generate_token uses the given json header to detect the algorithm.
|
98
|
+
# But it also accept to ignore that and force it to you another algorithm.
|
98
99
|
#
|
99
100
|
# @return [String] the generated token
|
100
101
|
#
|
101
102
|
def generate_token
|
102
|
-
|
103
|
-
@
|
104
|
-
@
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
103
|
+
|
104
|
+
@header = JSON.parse(@header) unless @header.is_a?(Hash)
|
105
|
+
@payload = JSON.parse(@payload) unless @payload.is_a?(Hash)
|
106
|
+
@alg = @header['alg'] if @alg.nil? # if algorithm not forced, take if from the header
|
107
|
+
|
108
|
+
header_encoded = encode(@header.to_json)
|
109
|
+
payload_encoded = encode(@payload.to_json)
|
110
|
+
data = "#{header_encoded}.#{payload_encoded}"
|
111
|
+
signature_encoded = encode(generate_sig(data, @alg, @key).signature)
|
112
|
+
token = [header_encoded, payload_encoded, signature_encoded].join('.')
|
113
|
+
|
114
|
+
set_hash_and_json
|
112
115
|
|
113
116
|
token
|
114
117
|
end
|
data/lib/jwtear/utils.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
module JWTear
|
2
2
|
module Utils
|
3
3
|
|
4
|
+
# check token format
|
5
|
+
def is_token?(token)
|
6
|
+
begin
|
7
|
+
token_size = token.split('.').size
|
8
|
+
raise InvalidTokenError if token_size < 2
|
9
|
+
rescue InvalidTokenError
|
10
|
+
puts '[!] '.red + "Invalid token: #{token}"
|
11
|
+
exit!
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
def encode(data)
|
5
16
|
Base64.urlsafe_encode64(data, padding: false)
|
6
17
|
end
|
@@ -9,13 +20,13 @@ module JWTear
|
|
9
20
|
Base64.urlsafe_decode64(data)
|
10
21
|
end
|
11
22
|
|
12
|
-
def
|
13
|
-
|
14
|
-
end
|
23
|
+
# def encode_header_payload_signature(header, payload, signature)
|
24
|
+
# [header, payload, signature].map {|part| encode part}.join('.')
|
25
|
+
# end
|
15
26
|
|
16
27
|
# JWTear's logo
|
17
28
|
def self.banner
|
18
|
-
%Q{\n
|
29
|
+
%Q{\n 888888 888 888 88888888888
|
19
30
|
"88b 888 o 888 888
|
20
31
|
888 888 d8b 888 888
|
21
32
|
888 888 d888b 888 888 .d88b. 8888b. 888d888
|
data/lib/jwtear/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwtear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- KING SABRI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: JWTear, command-line tool and library to parse, create and manipulate
|
14
14
|
JWT tokens for security testing purposes.
|