jwtear 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|