josebuilder 0.0.5 → 0.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e8502f7a92c455fcf01dd5269f74db124200011
4
- data.tar.gz: b0afffb20bc1c2e647d1cb51d9c9bf062d9d2303
3
+ metadata.gz: 829439b805873f4fc7316f4cb4cff959f0d3a575
4
+ data.tar.gz: e38b3821283ce3f1d46fb318b32b6fbee46f3de6
5
5
  SHA512:
6
- metadata.gz: c4d842b799cdf5e7717272796986cc990c91b5222ad992933870ea01fc666ed74591c631c60a568530c6030186787efb76273b9905569616cf71e75bdbe0b4a1
7
- data.tar.gz: 644cc1935b7dfb29bacd67007f67edb4c9db1826e6badf4667c1098c24505e2283b8ca908e087aae93ecc0903f320b3b6f65114a2f46ef8fb977dd1903ee669a
6
+ metadata.gz: 14c50307fab5e8a189c8ac785453d8eedcba47f07018c6aad24522f0132adfc3c096e322ef2d249b1fbf11f3326cec1901a6f167b8e26d0ad63294f8436c018c
7
+ data.tar.gz: 235e76fcfafc51970b4097409058e0ce1fe9db87f730d6a995569b12fb644b3c126d94170c2b6aea2960f4b60924b9ff1fe3d9ce3e2cce4915f20b3bd6e58fd4
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'josebuilder'
3
+ s.version = '0.0.6'
4
+ s.authors = ['Nguyen Ngo Dinh']
5
+ s.email = ['nguyenngodinh@outlook.com']
6
+ s.summary = 'Create JSON Signature and encryption structures'
7
+ s.description = "json signature and encryption builder"
8
+ s.homepage = 'https://github.com/nguyenngodinh/josebuilder'
9
+ s.license = 'MIT'
10
+
11
+ s.required_ruby_version = '>= 1.9.3'
12
+
13
+ s.add_dependency 'activesupport', '>= 3.0.0', '< 5'
14
+ s.add_dependency 'multi_json', '~> 1.2'
15
+ s.add_runtime_dependency 'jwt', '~> 1.4', '>= 1.4.1'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ end
19
+
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate josebuilder Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,63 @@
1
+ require 'rails/generators/resource_helpers'
2
+ require 'rails/generators/named_base'
3
+
4
+ class JosebuilderGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ argument :resource_name, :type => :string, :default => "defaultResourceName"
8
+ argument :secret, :type => :string, :default => "secret"
9
+ argument :algorithm, :type => :string, :default => "HS256"
10
+
11
+ class_option :signature, :type => :boolean, :default => true,
12
+ :description => "include signature"
13
+ class_option :encryption, :type => :boolean, :default => false,
14
+ :description => "include encryption"
15
+ class_option :combination, :type => :boolean, :default => false,
16
+ :description => "combine digital signature and encryption"
17
+
18
+ def generate_json_web_signature_file
19
+ ["index", "show"].each do |view|
20
+ file = filename_with_directory(view)
21
+ template filename_with_extensions(view), file
22
+ end if options.signature?
23
+ end
24
+
25
+
26
+ private
27
+
28
+ def get_secret
29
+ secret
30
+ end
31
+ def file_name
32
+ resource_name.underscore
33
+ end
34
+
35
+ def filename_with_extensions(name)
36
+ [name, :json, :jbuilder] * '.'
37
+ end
38
+
39
+ def pluralize(count, singular, plural = nil)
40
+ word = if (count == 1 || count =~ /^1(\.0+)?$/)
41
+ singular
42
+ else
43
+ plural || singular.pluralize
44
+ end
45
+
46
+ "#{count || 0} #{word}"
47
+ end
48
+
49
+ def filename_with_directory(file_name)
50
+ file_name = filename_with_extensions(file_name)
51
+ File.join('app/views', controller_file_path, file_name)
52
+ end
53
+
54
+ def controller_file_path
55
+ pluralize_without_count(2, resource_name)
56
+ end
57
+ def pluralize_without_count(count, noun, text=nil)
58
+ if count!=0
59
+ count == 1? "#{noun}#{text}": "#{noun.pluralize}#{text}"
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,7 @@
1
+ json.header = {alg: "<%= algorithm %>", typ: "JWS"}
2
+ json.payload do
3
+ json.array!(@<%= controller_file_path %>) do |<%= file_name %>|
4
+ json.<%= file_name %> = <%= file_name %>.as_json
5
+ end
6
+ end
7
+ json.signature = JWS.encode(@<%= controller_file_path %>.to_a.as_json, "<%= secret %>", "<%= algorithm %>")
@@ -0,0 +1,3 @@
1
+ json.header = {alg: "<%= algorithm %>", typ: "JWT"}
2
+ json.payload = @<%= file_name %>.as_json
3
+ json.signature = JWT.encode(@<%= file_name %>.as_json, "<%= secret %>", "<%= algorithm %>")
data/lib/jose/json.rb ADDED
@@ -0,0 +1,15 @@
1
+ module JWS
2
+ module Json
3
+ require 'json'
4
+
5
+ def decode_json(encoded_json)
6
+ JSON.parse(encoded_json)
7
+ rescue JSON::ParseError
8
+ raise JOSE::DecodeError.new("Invalid encoding")
9
+ end
10
+
11
+ def encode_json(raw)
12
+ JSON.generate(raw)
13
+ end
14
+ end
15
+ end
File without changes
data/lib/jws.rb ADDED
@@ -0,0 +1,127 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+ require 'jose/json'
4
+
5
+ module JWS
6
+ class DecodeError < StandardError; end
7
+ class VerificationError < DecodeError; end
8
+ extend JWS::Json
9
+
10
+ module_function
11
+
12
+ def sign(algorithm, msg, key)
13
+ if ['HS256', 'HS384', 'HS512'].include?(algorithm)
14
+ sign_hmac(algorithm, msg, key)
15
+ else
16
+ raise NotImplementedError.new("Unsupported signing mehtod")
17
+ end
18
+ end
19
+
20
+ def sign_hmac(algorithm, msg, key)
21
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'Sha')), key, msg)
22
+ end
23
+
24
+ def base64url_decode(str)
25
+ str += '=' *(4 - str.length.modulo(4))
26
+ Base64.decode64(str.tr('-_', '+/'))
27
+ end
28
+
29
+ def base64url_encode(str)
30
+ Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
31
+ end
32
+
33
+ def encoded_header(algorithm='HS256', header_fields={})
34
+ header = {'typ' => 'JWS', 'alg' => algorithm}.merge(header_fields)
35
+ base64url_encode(encode_json(header))
36
+ end
37
+
38
+ def encoded_payload(payload)
39
+ base64url_encode(encode_json(payload))
40
+ end
41
+
42
+ def encoded_signature(signing_input, key, algorithm)
43
+ if algorithm == 'none'
44
+ ''
45
+ else
46
+ signature = sign(algorithm, signing_input, key)
47
+ base64url_encode(signature)
48
+ end
49
+ end
50
+
51
+ def encode(payload, key, algorithm='HS256', header_fields={})
52
+ algorithm ||= 'none'
53
+ segments = []
54
+ segments << encoded_header(algorithm, header_fields)
55
+ segments << encoded_payload(payload)
56
+ segments << encoded_signature(segments.join('.'), key, algorithm)
57
+ segments.join('.')
58
+ end
59
+
60
+ def raw_segments(jws, verify=true)
61
+ segments = jws.split('.')
62
+ required_number_of_segments = verify ? [3] :[2,3]
63
+ raise JWS::DecodeError.new('Not enough or too many segments') unless required_number_of_segments.include? segments.length
64
+ segments
65
+ end
66
+
67
+ def decode_header_and_payload(header_segment, payload_segment)
68
+ header = decode_json(base64url_decode(header_segment))
69
+ payload = decode_json(base64url_decode(payload_segment))
70
+ [header, payload]
71
+ end
72
+
73
+ def decoded_segments(jws, verify=true)
74
+ header_segment, payload_segment, crypto_segment = raw_segments(jws, verify)
75
+ header, payload = decode_header_and_payload(header_segment, payload_segment)
76
+ signature = base64url_decode(crypto_segment.to_s) if verify
77
+ signing_input = [header_segment, payload_segment].join('.')
78
+ [header, payload, signature, signing_input]
79
+ end
80
+
81
+ def decode(jws, key=nil, verify=true, options={}, &keyfinder)
82
+ raise JWS::DecodeError.new('Nil JSON Web Signature') unless jws
83
+ header, payload, signature, signing_input = decoded_segments(jws, verify)
84
+ raise JWS::DecodeError.new('Not enough or too many segments') unless header && payload
85
+
86
+ if verify
87
+ algo, key = signature_algorithm_and_key(header, key, &keyfinder)
88
+ if options[:algorithm] && algo != options[:algorithm]
89
+ raise JWS::IncorrectAlgorithm.new('Expected a different algorithm')
90
+ end
91
+ verify_signature(algo, key, signing_input, signature)
92
+ end
93
+
94
+ return payload, header
95
+ end
96
+
97
+ def signature_algorithm_and_key(header, key, &keyfinder)
98
+ if keyfinder
99
+ key = keyfinder.call(header)
100
+ end
101
+ [header['alg'], key]
102
+ end
103
+
104
+ def verify_signature(algo, key, signing_input, signature)
105
+ begin
106
+ if ['HS256', 'HS384', 'HS512'].include?(algo)
107
+ raise JWS::VerificationError.new('Signature verification failed') unless secure_compare(signature, sign_hmac(algo, signing_input, key))
108
+ else
109
+ raise JWS::VerificationError.new('Algorithm not supported')
110
+ end
111
+ rescue OpenSSL::Pkey::PkeyError
112
+ raise JWS::VerificationError.new('Signature verification failed')
113
+ ensure
114
+ OpenSSL.errors.clear
115
+ end
116
+ end
117
+
118
+ def secure_compare(a, b)
119
+ return false if a.nil? || b.nil? || a.empty? || b.empty? || a.bytesize != b.bytesize
120
+ l = a.unpack "C#{a.bytesize}"
121
+
122
+ res = 0
123
+ b.each_byte { |byte| res |= byte ^ l.shift }
124
+ res == 0
125
+ end
126
+
127
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: josebuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nguyen Ngo Dinh
@@ -70,7 +70,20 @@ email:
70
70
  executables: []
71
71
  extensions: []
72
72
  extra_rdoc_files: []
73
- files: []
73
+ files:
74
+ - josebuilder-0.0.0.gem
75
+ - josebuilder-0.0.1.gem
76
+ - josebuilder-0.0.2.gem
77
+ - josebuilder-0.0.3.gem
78
+ - josebuilder-0.0.4.gem
79
+ - josebuilder.gemspec
80
+ - lib/jose/generators/josebuilder/USAGE
81
+ - lib/jose/generators/josebuilder/josebuilder_generator.rb
82
+ - lib/jose/generators/josebuilder/templates/index.json.jbuilder
83
+ - lib/jose/generators/josebuilder/templates/show.json.jbuilder
84
+ - lib/jose/json.rb
85
+ - lib/josebuilder.rb
86
+ - lib/jws.rb
74
87
  homepage: https://github.com/nguyenngodinh/josebuilder
75
88
  licenses:
76
89
  - MIT