sandal 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5ea79b1b4960ee68f883439155f86e455f840297
4
- data.tar.gz: 88fe766c7e0dd6f42ffe8cc9e362bd4f9d4dcf1c
3
+ metadata.gz: e87dc3dc16b78944fbce50e48565012d79f087f6
4
+ data.tar.gz: 59b76ed79701856db73f2967da1818063fa58400
5
5
  SHA512:
6
- metadata.gz: 8caf814bd10d413690942fde42d319a9b1d65afcef90c3ebf19f27f35b731e2d48c4d4225fb0700a60c9841c98ea46a6e34c610b40d93cf5584c605b6144621a
7
- data.tar.gz: 978832491980e5e85b83bdac17e4c615cddc01594600785db0e7b7a621d459b7955003ab0352dac65ba803ded8890780cb609895528a6f35f60e107938dc8be6
6
+ metadata.gz: 2ebe5600b88a9026de7b5056b0d26832f259adb47556a5cbe7eb51d07e6ec9eddc08ae289769ce260bf053d424521cb21c4cd394c273bf11d084fab7c2122b3d
7
+ data.tar.gz: 78a7d2f1a4a13330719adb344534882ee8652dcf26ad3966c3f9532a61682daaddcc409fee36d7e5f008d1c0f5f4b2a9defc2ec9fff44a4f685b65d3c3633c8c
@@ -13,7 +13,6 @@ require "sandal/util"
13
13
  #
14
14
  # Currently supports draft-07 of the JWT spec, and draft-10 of the JWS and JWE specs.
15
15
  module Sandal
16
- extend Sandal::Util
17
16
 
18
17
  # The base error for all errors raised by this library.
19
18
  class Error < StandardError; end
@@ -112,9 +111,9 @@ module Sandal
112
111
 
113
112
  payload = MultiJson.dump(payload) unless payload.is_a?(String)
114
113
 
115
- sec_input = [header, payload].map { |p| jwt_base64_encode(p) }.join(".")
114
+ sec_input = [header, payload].map { |p| Sandal::Util.jwt_base64_encode(p) }.join(".")
116
115
  signature = signer.sign(sec_input)
117
- [sec_input, jwt_base64_encode(signature)].join(".")
116
+ [sec_input, Sandal::Util.jwt_base64_encode(signature)].join(".")
118
117
  end
119
118
 
120
119
  # Creates an encrypted JSON Web Token.
@@ -206,7 +205,7 @@ module Sandal
206
205
 
207
206
  # Decodes the parts of a token.
208
207
  def self.decode_token_parts(parts)
209
- parts = parts.map { |part| jwt_base64_decode(part) }
208
+ parts = parts.map { |part| Sandal::Util.jwt_base64_decode(part) }
210
209
  parts[0] = MultiJson.load(parts[0])
211
210
  parts
212
211
  rescue
@@ -12,7 +12,7 @@ module Sandal
12
12
  def self.token_parts(token)
13
13
  parts = token.is_a?(Array) ? token : token.split(".")
14
14
  raise ArgumentError unless parts.length == 5
15
- decoded_parts = parts.map { |part| jwt_base64_decode(part) }
15
+ decoded_parts = parts.map { |part| Sandal::Util.jwt_base64_decode(part) }
16
16
  return parts, decoded_parts
17
17
  rescue ArgumentError
18
18
  raise Sandal::InvalidTokenError, "Invalid token encoding."
@@ -6,7 +6,6 @@ module Sandal
6
6
 
7
7
  # Base implementation of the A*CBC-HS* family of encryption methods.
8
8
  class ACBC_HS
9
- include Sandal::Util
10
9
 
11
10
  # The JWA name of the encryption method.
12
11
  attr_reader :name
@@ -44,13 +43,13 @@ module Sandal
44
43
  cipher.iv = iv = SecureRandom.random_bytes(16)
45
44
  ciphertext = cipher.update(payload) + cipher.final
46
45
 
47
- auth_data = jwt_base64_encode(header)
46
+ auth_data = Sandal::Util.jwt_base64_encode(header)
48
47
  auth_data_length = [auth_data.length * 8].pack("Q>")
49
48
  mac_input = [auth_data, iv, ciphertext, auth_data_length].join
50
49
  mac = OpenSSL::HMAC.digest(@digest, mac_key, mac_input)
51
50
  auth_tag = mac[0...(mac.length / 2)]
52
51
 
53
- remainder = [encrypted_key, iv, ciphertext, auth_tag].map { |part| jwt_base64_encode(part) }
52
+ remainder = [encrypted_key, iv, ciphertext, auth_tag].map { |part| Sandal::Util.jwt_base64_encode(part) }
54
53
  [auth_data, *remainder].join(".")
55
54
  end
56
55
 
@@ -6,7 +6,6 @@ module Sandal
6
6
 
7
7
  # Base implementation of the A*GCM family of encryption methods.
8
8
  class AGCM
9
- include Sandal::Util
10
9
 
11
10
  @@iv_size = 96
12
11
  @@auth_tag_size = 128
@@ -41,12 +40,12 @@ module Sandal
41
40
  cipher.key = key
42
41
  cipher.iv = iv = SecureRandom.random_bytes(@@iv_size / 8)
43
42
 
44
- auth_data = jwt_base64_encode(header)
43
+ auth_data = Sandal::Util.jwt_base64_encode(header)
45
44
  cipher.auth_data = auth_data
46
45
 
47
46
  ciphertext = cipher.update(payload) + cipher.final
48
47
  remaining_parts = [encrypted_key, iv, ciphertext, cipher.auth_tag(@@auth_tag_size / 8)]
49
- remaining_parts.map! { |part| jwt_base64_encode(part) }
48
+ remaining_parts.map! { |part| Sandal::Util.jwt_base64_encode(part) }
50
49
  [auth_data, *remaining_parts].join(".")
51
50
  end
52
51
 
@@ -5,7 +5,6 @@ module Sandal
5
5
 
6
6
  # Base implementation of the HMAC-SHA family of signature algorithms.
7
7
  class HS
8
- include Sandal::Util
9
8
 
10
9
  # The JWA name of the algorithm.
11
10
  attr_reader :name
@@ -36,7 +35,7 @@ module Sandal
36
35
  # @param payload [String] The payload of the token.
37
36
  # @return [Boolean] true if the signature is correct; otherwise false.
38
37
  def valid?(signature, payload)
39
- jwt_strings_equal?(sign(payload), signature)
38
+ Sandal::Util.jwt_strings_equal?(sign(payload), signature)
40
39
  end
41
40
 
42
41
  end
@@ -5,8 +5,6 @@ module Sandal
5
5
  # Implements some JWT utility functions. Shouldn't be needed by most people
6
6
  # but may be useful if you're developing an extension to the library.
7
7
  module Util
8
-
9
- private
10
8
 
11
9
  # A string equality function that compares Unicode codepoints, and also
12
10
  # doesn't short-circuit the equality check to help protect against timing
@@ -19,7 +17,7 @@ module Sandal
19
17
  # @param a [String] The first string.
20
18
  # @param b [String] The second string.
21
19
  # @return [Boolean] true if the strings are equal; otherwise false.
22
- def jwt_strings_equal?(a, b)
20
+ def self.jwt_strings_equal?(a, b)
23
21
  return true if a.object_id == b.object_id
24
22
  return false if a.nil? || b.nil? || a.length != b.length
25
23
  a.codepoints.zip(b.codepoints).reduce(0) { |r, (x, y)| r |= x ^ y } == 0
@@ -29,7 +27,7 @@ module Sandal
29
27
  #
30
28
  # @param s [String] The string to encode.
31
29
  # @return [String] The encoded base64 string.
32
- def jwt_base64_encode(s)
30
+ def self.jwt_base64_encode(s)
33
31
  Base64.urlsafe_encode64(s).gsub(/=+$/, "")
34
32
  end
35
33
 
@@ -38,7 +36,7 @@ module Sandal
38
36
  # @param s [String] The base64 string to decode.
39
37
  # @return [String] The decoded string.
40
38
  # @raise [ArgumentError] The base64 string is invalid or contains padding.
41
- def jwt_base64_decode(s)
39
+ def self.jwt_base64_decode(s)
42
40
  if s.end_with?("=")
43
41
  raise ArgumentError, "Base64 strings must not contain padding."
44
42
  end
@@ -1,4 +1,4 @@
1
1
  module Sandal
2
2
  # The semantic version of the library.
3
- VERSION = "0.5.0"
3
+ VERSION = "0.5.1"
4
4
  end
@@ -1,33 +1,33 @@
1
1
  ($LOAD_PATH << File.expand_path("../lib", __FILE__)).uniq!
2
- require 'sandal/version'
2
+ require "sandal/version"
3
3
 
4
4
  Gem::Specification.new do |s|
5
- s.name = 'sandal'
5
+ s.name = "sandal"
6
6
  s.version = Sandal::VERSION
7
- s.summary = 'A JSON Web Token (JWT) library.'
8
- s.description = 'A ruby library for creating and reading JSON Web Tokens (JWT), supporting JSON Web Signatures (JWS) and JSON Web Encryption (JWE).'
9
- s.author = 'Greg Beech'
10
- s.email = 'greg@gregbeech.com'
11
- s.homepage = 'http://rubygems.org/gems/sandal'
12
- s.license = 'MIT'
7
+ s.summary = "A JSON Web Token (JWT) library."
8
+ s.description = "A ruby library for creating and reading JSON Web Tokens (JWT), supporting JSON Web Signatures (JWS) and JSON Web Encryption (JWE)."
9
+ s.author = "Greg Beech"
10
+ s.email = "greg@gregbeech.com"
11
+ s.homepage = "http://rubygems.org/gems/sandal"
12
+ s.license = "MIT"
13
13
 
14
14
  s.files = `git ls-files`.split($/)
15
15
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
16
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
- s.require_paths = ['lib']
18
- s.extra_rdoc_files = ['README.md', 'LICENSE.md']
17
+ s.require_paths = ["lib"]
18
+ s.extra_rdoc_files = ["README.md", "LICENSE.md", "CHANGELOG.md"]
19
19
 
20
- s.add_runtime_dependency 'multi_json', '~> 1.7'
21
- s.add_runtime_dependency 'jruby-openssl', '~> 0.7', '>= 0.7.3' if RUBY_PLATFORM == 'java'
20
+ s.add_runtime_dependency "multi_json", "~> 1.7"
21
+ s.add_runtime_dependency "jruby-openssl", "~> 0.7", ">= 0.7.3" if RUBY_PLATFORM == "java"
22
22
 
23
- s.add_development_dependency 'bundler', '>= 1.3'
24
- s.add_development_dependency 'rake', '>= 10.0'
25
- s.add_development_dependency 'rspec', '>= 2.13'
26
- s.add_development_dependency 'simplecov', '>= 0.7'
27
- s.add_development_dependency 'coveralls', '>= 0.6'
28
- s.add_development_dependency 'yard', '>= 0.8'
29
- s.add_development_dependency 'redcarpet', '>= 2.2' unless RUBY_PLATFORM == 'java' # for yard
30
- s.add_development_dependency 'kramdown', '>= 1.0' if RUBY_PLATFORM == 'java' # for yard
23
+ s.add_development_dependency "bundler", ">= 1.3"
24
+ s.add_development_dependency "rake", ">= 10.0"
25
+ s.add_development_dependency "rspec", ">= 2.13"
26
+ s.add_development_dependency "simplecov", ">= 0.7"
27
+ s.add_development_dependency "coveralls", ">= 0.6"
28
+ s.add_development_dependency "yard", ">= 0.8"
29
+ s.add_development_dependency "redcarpet", ">= 2.2" unless RUBY_PLATFORM == "java" # for yard
30
+ s.add_development_dependency "kramdown", ">= 1.0" if RUBY_PLATFORM == "java" # for yard
31
31
 
32
- s.requirements << 'openssl 1.0.1c for EC signature methods'
32
+ s.requirements << "openssl 1.0.1c for EC signature methods"
33
33
  end
@@ -1,8 +1,6 @@
1
1
  require "helper"
2
2
  require "openssl"
3
3
 
4
- include Sandal::Util
5
-
6
4
  shared_examples "encryption and decryption" do |enc_class|
7
5
 
8
6
  it "can encrypt and decrypt a content master key" do
@@ -1,8 +1,6 @@
1
1
  require "helper"
2
2
  require "openssl"
3
3
 
4
- include Sandal::Util
5
-
6
4
  # EC isn't implemented in jruby-openssl at the moment
7
5
  if defined? Sandal::Sig::ES
8
6
 
@@ -111,7 +109,7 @@ describe Sandal::Sig::ES do
111
109
  r = make_bn([14, 209, 33, 83, 121, 99, 108, 72, 60, 47, 127, 21, 88, 7, 212, 2, 163, 178, 40, 3, 58, 249, 124, 126, 23, 129, 154, 195, 22, 158, 166, 101])
112
110
  s = make_bn([197, 10, 7, 211, 140, 60, 112, 229, 216, 241, 45, 175, 8, 74, 84, 128, 166, 101, 144, 197, 242, 147, 80, 154, 143, 63, 127, 138, 131, 163, 84, 213])
113
111
  signature = Sandal::Sig::ES.encode_jws_signature(r, s, 256)
114
- base64_signature = jwt_base64_encode(signature)
112
+ base64_signature = Sandal::Util.jwt_base64_encode(signature)
115
113
  base64_signature.should == "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q"
116
114
  end
117
115
 
@@ -119,7 +117,7 @@ describe Sandal::Sig::ES do
119
117
  r = make_bn([1, 220, 12, 129, 231, 171, 194, 209, 232, 135, 233, 117, 247, 105, 122, 210, 26, 125, 192, 1, 217, 21, 82, 91, 45, 240, 255, 83, 19, 34, 239, 71, 48, 157, 147, 152, 105, 18, 53, 108, 163, 214, 68, 231, 62, 153, 150, 106, 194, 164, 246, 72, 143, 138, 24, 50, 129, 223, 133, 206, 209, 172, 63, 237, 119, 109])
120
118
  s = make_bn([0, 111, 6, 105, 44, 5, 41, 208, 128, 61, 152, 40, 92, 61, 152, 4, 150, 66, 60, 69, 247, 196, 170, 81, 193, 199, 78, 59, 194, 169, 16, 124, 9, 143, 42, 142, 131, 48, 206, 238, 34, 175, 83, 203, 220, 159, 3, 107, 155, 22, 27, 73, 111, 68, 68, 21, 238, 144, 229, 232, 148, 188, 222, 59, 242, 103])
121
119
  signature = Sandal::Sig::ES.encode_jws_signature(r, s, 521)
122
- base64_signature = jwt_base64_encode(signature)
120
+ base64_signature = Sandal::Util.jwt_base64_encode(signature)
123
121
  base64_signature.should == "AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn"
124
122
  end
125
123
 
@@ -144,7 +142,7 @@ describe Sandal::Sig::ES256 do
144
142
  y = make_bn([199, 241, 68, 205, 27, 189, 155, 126, 135, 44, 223, 237, 185, 238, 185, 244, 179, 105, 93, 110, 169, 11, 36, 173, 138, 70, 35, 40, 133, 136, 229, 173])
145
143
  d = make_bn([142, 155, 16, 158, 113, 144, 152, 191, 152, 4, 135, 223, 31, 93, 119, 233, 203, 41, 96, 110, 190, 210, 38, 59, 95, 87, 194, 19, 223, 132, 244, 178])
146
144
  data = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ"
147
- signature = jwt_base64_decode("DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q")
145
+ signature = Sandal::Util.jwt_base64_decode("DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q")
148
146
 
149
147
  group = OpenSSL::PKey::EC::Group.new("prime256v1")
150
148
  public_key = OpenSSL::PKey::EC.new(group)
@@ -186,7 +184,7 @@ describe Sandal::Sig::ES512 do
186
184
  y = make_bn([0, 52, 166, 68, 14, 55, 103, 80, 210, 55, 31, 209, 189, 194, 200, 243, 183, 29, 47, 78, 229, 234, 52, 50, 200, 21, 204, 163, 21, 96, 254, 93, 147, 135, 236, 119, 75, 85, 131, 134, 48, 229, 203, 191, 90, 140, 190, 10, 145, 221, 0, 100, 198, 153, 154, 31, 110, 110, 103, 250, 221, 237, 228, 200, 200, 246])
187
185
  d = make_bn([1, 142, 105, 111, 176, 52, 80, 88, 129, 221, 17, 11, 72, 62, 184, 125, 50, 206, 73, 95, 227, 107, 55, 69, 237, 242, 216, 202, 228, 240, 242, 83, 159, 70, 21, 160, 233, 142, 171, 82, 179, 192, 197, 234, 196, 206, 7, 81, 133, 168, 231, 187, 71, 222, 172, 29, 29, 231, 123, 204, 246, 97, 53, 230, 61, 130] )
188
186
  data = "eyJhbGciOiJFUzUxMiJ9.UGF5bG9hZA"
189
- signature = jwt_base64_decode("AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn")
187
+ signature = Sandal::Util.jwt_base64_decode("AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn")
190
188
 
191
189
  group = OpenSSL::PKey::EC::Group.new("secp521r1")
192
190
  public_key = OpenSSL::PKey::EC.new(group)
@@ -2,24 +2,22 @@ require 'helper'
2
2
  require 'openssl'
3
3
  require 'benchmark'
4
4
 
5
- include Sandal::Util
6
-
7
5
  describe Sandal::Util do
8
6
 
9
7
  context '#jwt_base64_decode' do
10
8
 
11
9
  it 'decodes base64 as per JWT example 6.1' do
12
10
  encoded = 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ'
13
- val = jwt_base64_decode(encoded)
11
+ val = Sandal::Util.jwt_base64_decode(encoded)
14
12
  val.should == %!{"iss":"joe",\r\n "exp":1300819380,\r\n "http://example.com/is_root":true}!
15
13
  end
16
14
 
17
15
  it 'raises an ArgumentError if base64 strings contain padding' do
18
- expect { jwt_base64_decode('eyJpc3MiOiJq=') }.to raise_error ArgumentError
16
+ expect { Sandal::Util.jwt_base64_decode('eyJpc3MiOiJq=') }.to raise_error ArgumentError
19
17
  end
20
18
 
21
19
  it 'raises an ArgumentError if base64 strings are invalid' do
22
- expect { jwt_base64_decode('not valid base64') }.to raise_error ArgumentError
20
+ expect { Sandal::Util.jwt_base64_decode('not valid base64') }.to raise_error ArgumentError
23
21
  end
24
22
 
25
23
  end
@@ -28,7 +26,7 @@ describe Sandal::Util do
28
26
 
29
27
  it 'encodes base64 as per JWT example 6.1' do
30
28
  src = %!{"iss":"joe",\r\n "exp":1300819380,\r\n "http://example.com/is_root":true}!
31
- encoded = jwt_base64_encode(src)
29
+ encoded = Sandal::Util.jwt_base64_encode(src)
32
30
  encoded.should == 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ'
33
31
  end
34
32
 
@@ -37,31 +35,31 @@ describe Sandal::Util do
37
35
  context '#jwt_strings_equal?' do
38
36
 
39
37
  it 'compares nil strings as equal' do
40
- jwt_strings_equal?(nil, nil).should == true
38
+ Sandal::Util.jwt_strings_equal?(nil, nil).should == true
41
39
  end
42
40
 
43
41
  it 'compares empty strings as equal' do
44
- jwt_strings_equal?('', '').should == true
42
+ Sandal::Util.jwt_strings_equal?('', '').should == true
45
43
  end
46
44
 
47
45
  it 'compares nil strings as unequal to empty strings' do
48
- jwt_strings_equal?(nil, '').should == false
49
- jwt_strings_equal?('', nil).should == false
46
+ Sandal::Util.jwt_strings_equal?(nil, '').should == false
47
+ Sandal::Util.jwt_strings_equal?('', nil).should == false
50
48
  end
51
49
 
52
50
  it 'compares equal strings as equal' do
53
- jwt_strings_equal?('hello', 'hello').should == true
54
- jwt_strings_equal?('a longer string', 'a longer string').should == true
51
+ Sandal::Util.jwt_strings_equal?('hello', 'hello').should == true
52
+ Sandal::Util.jwt_strings_equal?('a longer string', 'a longer string').should == true
55
53
  end
56
54
 
57
55
  it 'compares unequal strings as unequal' do
58
- jwt_strings_equal?('hello', 'world').should == false
59
- jwt_strings_equal?('a longer string', 'a different longer string').should == false
56
+ Sandal::Util.jwt_strings_equal?('hello', 'world').should == false
57
+ Sandal::Util.jwt_strings_equal?('a longer string', 'a different longer string').should == false
60
58
  end
61
59
 
62
60
  it 'compares strings without short-circuiting', :timing_dependent do
63
61
  measure_equals = -> a, b do
64
- Benchmark.realtime { 100.times { jwt_strings_equal?(a, b) } }
62
+ Benchmark.realtime { 100.times { Sandal::Util.jwt_strings_equal?(a, b) } }
65
63
  end
66
64
  ref = 'a' * 10000
67
65
  cmp1 = ('a' * 9999) + 'b'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sandal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Beech
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-07 00:00:00.000000000 Z
11
+ date: 2013-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -130,6 +130,7 @@ extensions: []
130
130
  extra_rdoc_files:
131
131
  - README.md
132
132
  - LICENSE.md
133
+ - CHANGELOG.md
133
134
  files:
134
135
  - .coveralls.yml
135
136
  - .gitignore