sandal 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.md +14 -0
- data/README.md +1 -1
- data/lib/sandal.rb +77 -76
- data/lib/sandal/claims.rb +13 -13
- data/lib/sandal/enc.rb +15 -49
- data/lib/sandal/enc/acbc_hs.rb +97 -52
- data/lib/sandal/enc/agcm.rb +64 -26
- data/lib/sandal/enc/alg.rb +2 -3
- data/lib/sandal/enc/alg/direct.rb +27 -25
- data/lib/sandal/enc/alg/rsa.rb +82 -0
- data/lib/sandal/sig.rb +12 -12
- data/lib/sandal/sig/es.rb +43 -25
- data/lib/sandal/sig/hs.rb +21 -8
- data/lib/sandal/sig/rs.rb +34 -23
- data/lib/sandal/util.rb +7 -7
- data/lib/sandal/version.rb +1 -1
- data/spec/helper.rb +1 -0
- data/spec/sample_keys.rb +28 -0
- data/spec/sandal/claims_spec.rb +4 -4
- data/spec/sandal/enc/a128cbc_hs256_spec.rb +15 -39
- data/spec/sandal/enc/a128gcm_spec.rb +13 -6
- data/spec/sandal/enc/a256cbc_hs512_spec.rb +13 -4
- data/spec/sandal/enc/a256gcm_spec.rb +15 -37
- data/spec/sandal/enc/alg/direct_spec.rb +27 -33
- data/spec/sandal/enc/alg/rsa_spec.rb +100 -0
- data/spec/sandal/enc/shared_examples.rb +93 -21
- data/spec/sandal/sig/es_spec.rb +145 -188
- data/spec/sandal/sig/hs_spec.rb +73 -18
- data/spec/sandal/sig/rs_spec.rb +81 -78
- metadata +7 -6
- data/lib/sandal/enc/alg/rsa1_5.rb +0 -47
- data/lib/sandal/enc/alg/rsa_oaep.rb +0 -48
- data/spec/sandal/enc/alg/rsa1_5_spec.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ea79b1b4960ee68f883439155f86e455f840297
|
4
|
+
data.tar.gz: 88fe766c7e0dd6f42ffe8cc9e362bd4f9d4dcf1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8caf814bd10d413690942fde42d319a9b1d65afcef90c3ebf19f27f35b731e2d48c4d4225fb0700a60c9841c98ea46a6e34c610b40d93cf5584c605b6144621a
|
7
|
+
data.tar.gz: 978832491980e5e85b83bdac17e4c615cddc01594600785db0e7b7a621d459b7955003ab0352dac65ba803ded8890780cb609895528a6f35f60e107938dc8be6
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.5.0 (07 June 2013)
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
- Updated to JWT draft-08 specification, and corresponding JWE, JWS and JWA drafts.
|
6
|
+
- Added a KeyError class for when invalid keys are given to the library.
|
7
|
+
- Added an ExpiredTokenError class to make handling the common case of expired tokens easier.
|
8
|
+
- Added a NAME constant to all classes with a JWA name to save user having to hard-code the name string.
|
9
|
+
|
10
|
+
Breaking changes:
|
11
|
+
|
12
|
+
- Tokens are not backwards compatible with previous versions of the library due to changes in the specification.
|
13
|
+
- Dropped support for Ruby 1.9.2; supported platforms are now 1.9.3, 2.0.0, JRuby (head) and Rubinius (head).
|
14
|
+
|
1
15
|
## 0.4.0 (30 April 2013)
|
2
16
|
|
3
17
|
Features:
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Sandal [![Build Status](https://travis-ci.org/gregbeech/sandal.png?branch=master)](https://travis-ci.org/gregbeech/sandal) [![Coverage Status](https://coveralls.io/repos/gregbeech/sandal/badge.png?branch=master)](https://coveralls.io/r/gregbeech/sandal) [![Code Climate](https://codeclimate.com/github/gregbeech/sandal.png)](https://codeclimate.com/github/gregbeech/sandal) [![Dependency Status](https://gemnasium.com/gregbeech/sandal.png)](https://gemnasium.com/gregbeech/sandal)
|
2
2
|
|
3
|
-
A Ruby library for creating and reading [JSON Web Tokens (JWT) draft-
|
3
|
+
A Ruby library for creating and reading [JSON Web Tokens (JWT) draft-08](http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-08), supporting [JSON Web Signatures (JWS) draft-11](http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-11) and [JSON Web Encryption (JWE) draft-11](http://tools.ietf.org/html/draft-ietf-jose-json-web-encryption-11). See the [CHANGELOG](CHANGELOG.md) for version history.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
data/lib/sandal.rb
CHANGED
@@ -1,48 +1,60 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
|
10
|
-
|
11
|
-
# A library for creating and reading JSON Web Tokens (JWT), supporting JSON Web
|
12
|
-
#
|
1
|
+
require "multi_json"
|
2
|
+
require "openssl"
|
3
|
+
require "zlib"
|
4
|
+
require "sandal/version"
|
5
|
+
require "sandal/claims"
|
6
|
+
require "sandal/enc"
|
7
|
+
require "sandal/sig"
|
8
|
+
require "sandal/util"
|
9
|
+
|
10
|
+
|
11
|
+
# A library for creating and reading JSON Web Tokens (JWT), supporting JSON Web Signatures (JWS) and JSON Web Encryption
|
12
|
+
# (JWE).
|
13
13
|
#
|
14
|
-
# Currently supports draft-
|
15
|
-
# specs.
|
14
|
+
# Currently supports draft-07 of the JWT spec, and draft-10 of the JWS and JWE specs.
|
16
15
|
module Sandal
|
17
16
|
extend Sandal::Util
|
18
17
|
|
18
|
+
# The base error for all errors raised by this library.
|
19
|
+
class Error < StandardError; end
|
20
|
+
|
21
|
+
# The error that is raised when a key provided for signing/encryption/etc. is invalid.
|
22
|
+
class KeyError < Error; end
|
23
|
+
|
24
|
+
# The error that is raised when there is a problem with a token.
|
25
|
+
class TokenError < Error; end
|
26
|
+
|
19
27
|
# The error that is raised when a token is invalid.
|
20
|
-
class
|
28
|
+
class InvalidTokenError < TokenError; end
|
21
29
|
|
22
30
|
# The error that is raised when a claim within a token is invalid.
|
23
|
-
class ClaimError <
|
31
|
+
class ClaimError < InvalidTokenError; end
|
32
|
+
|
33
|
+
# The error that is raised when the token has expired.
|
34
|
+
class ExpiredTokenError < ClaimError; end
|
35
|
+
|
36
|
+
# The error that is raised when a token is unsupported (e.g. the algorithm used to encrypt the token is not supported
|
37
|
+
# by this library or by the Ruby platform it is executing on).
|
38
|
+
class UnsupportedTokenError < TokenError; end
|
24
39
|
|
25
40
|
# The default options for token handling.
|
26
41
|
#
|
27
42
|
# ignore_exp::
|
28
|
-
# Whether to ignore the expiry date of the token. This setting is just to
|
29
|
-
#
|
43
|
+
# Whether to ignore the expiry date of the token. This setting is just to help get things working and should always
|
44
|
+
# be false in real apps!
|
30
45
|
# ignore_nbf::
|
31
|
-
# Whether to ignore the not-before date of the token. This setting is just
|
32
|
-
#
|
46
|
+
# Whether to ignore the not-before date of the token. This setting is just to help get things working and should
|
47
|
+
# always be false in real apps!
|
33
48
|
# ignore_signature::
|
34
|
-
# Whether to ignore the signature of signed (JWS) tokens. This setting is
|
35
|
-
#
|
49
|
+
# Whether to ignore the signature of signed (JWS) tokens. This setting is just tohelp get things working and should
|
50
|
+
# always be false in real apps!
|
36
51
|
# max_clock_skew::
|
37
|
-
# The maximum clock skew, in seconds, when validating times. If your server
|
38
|
-
#
|
39
|
-
# take that into account. It probably shouldn't be more than about 300.
|
52
|
+
# The maximum clock skew, in seconds, when validating times. If your server time is out of sync with the token
|
53
|
+
# server then this can be increased to take that into account. It probably shouldn't be more than about 300.
|
40
54
|
# valid_iss::
|
41
|
-
# A list of valid token issuers, if validation of the issuer claim is
|
42
|
-
# required.
|
55
|
+
# A list of valid token issuers, if validation of the issuer claim is required.
|
43
56
|
# valid_aud::
|
44
|
-
# A list of valid audiences, if validation of the audience claim is
|
45
|
-
# required.
|
57
|
+
# A list of valid audiences, if validation of the audience claim is required.
|
46
58
|
DEFAULT_OPTIONS = {
|
47
59
|
ignore_exp: false,
|
48
60
|
ignore_nbf: false,
|
@@ -54,8 +66,7 @@ module Sandal
|
|
54
66
|
|
55
67
|
# Overrides the default options.
|
56
68
|
#
|
57
|
-
# @param defaults [Hash] The options to override (see {DEFAULT_OPTIONS} for
|
58
|
-
# details).
|
69
|
+
# @param defaults [Hash] The options to override (see {DEFAULT_OPTIONS} for details).
|
59
70
|
# @return [Hash] The new default options.
|
60
71
|
def self.default!(defaults)
|
61
72
|
DEFAULT_OPTIONS.merge!(defaults)
|
@@ -67,7 +78,7 @@ module Sandal
|
|
67
78
|
# @return [Boolean] true if the token is encrypted; otherwise false.
|
68
79
|
def self.is_encrypted?(token)
|
69
80
|
if token.is_a?(String)
|
70
|
-
token.count(
|
81
|
+
token.count(".") == 4
|
71
82
|
else
|
72
83
|
token.count == 5
|
73
84
|
end
|
@@ -79,7 +90,7 @@ module Sandal
|
|
79
90
|
# @return [Boolean] true if the token is signed; otherwise false.
|
80
91
|
def self.is_signed?(token)
|
81
92
|
if token.is_a?(String)
|
82
|
-
!token.end_with?(
|
93
|
+
!token.end_with?(".") && token.count(".") == 2
|
83
94
|
else
|
84
95
|
token.count == 3 && !token[2].nil? && !token[2].empty?
|
85
96
|
end
|
@@ -87,75 +98,65 @@ module Sandal
|
|
87
98
|
|
88
99
|
# Creates a signed JSON Web Token.
|
89
100
|
#
|
90
|
-
# @param payload [String or Hash] The payload of the token. Hashes will be
|
91
|
-
#
|
92
|
-
# @param
|
93
|
-
# unsigned token.
|
94
|
-
# @param header_fields [Hash] Header fields for the token (note: do not
|
95
|
-
# include 'alg').
|
101
|
+
# @param payload [String or Hash] The payload of the token. Hashes will be encoded as JSON.
|
102
|
+
# @param signer [#name,#sign] The token signer, which may be nil for an unsigned token.
|
103
|
+
# @param header_fields [Hash] Header fields for the token (note: do not include "alg").
|
96
104
|
# @return [String] A signed JSON Web Token.
|
97
105
|
def self.encode_token(payload, signer, header_fields = nil)
|
98
106
|
signer ||= Sandal::Sig::NONE
|
99
107
|
|
100
108
|
header = {}
|
101
|
-
header[
|
109
|
+
header["alg"] = signer.name
|
102
110
|
header = header_fields.merge(header) if header_fields
|
103
111
|
header = MultiJson.dump(header)
|
104
112
|
|
105
113
|
payload = MultiJson.dump(payload) unless payload.is_a?(String)
|
106
114
|
|
107
|
-
sec_input = [header, payload].map { |p| jwt_base64_encode(p) }.join(
|
115
|
+
sec_input = [header, payload].map { |p| jwt_base64_encode(p) }.join(".")
|
108
116
|
signature = signer.sign(sec_input)
|
109
|
-
[sec_input, jwt_base64_encode(signature)].join(
|
117
|
+
[sec_input, jwt_base64_encode(signature)].join(".")
|
110
118
|
end
|
111
119
|
|
112
120
|
# Creates an encrypted JSON Web Token.
|
113
121
|
#
|
114
122
|
# @param payload [String] The payload of the token.
|
115
123
|
# @param encrypter [#name,#alg,#encrypt] The token encrypter.
|
116
|
-
# @param header_fields [Hash] Header fields for the token (note: do not
|
117
|
-
# include 'alg' or 'enc').
|
124
|
+
# @param header_fields [Hash] Header fields for the token (note: do not include "alg" or "enc").
|
118
125
|
# @return [String] An encrypted JSON Web Token.
|
119
126
|
def self.encrypt_token(payload, encrypter, header_fields = nil)
|
120
127
|
header = {}
|
121
|
-
header[
|
122
|
-
header[
|
128
|
+
header["enc"] = encrypter.name
|
129
|
+
header["alg"] = encrypter.alg.name
|
123
130
|
header = header_fields.merge(header) if header_fields
|
124
131
|
|
125
|
-
if header.has_key?(
|
126
|
-
unless header[
|
127
|
-
raise ArgumentError,
|
132
|
+
if header.has_key?("zip")
|
133
|
+
unless header["zip"] == "DEF"
|
134
|
+
raise ArgumentError, "Invalid zip algorithm."
|
128
135
|
end
|
129
136
|
payload = Zlib::Deflate.deflate(payload, Zlib::BEST_COMPRESSION)
|
130
137
|
end
|
131
138
|
|
132
|
-
encrypter.encrypt(header, payload)
|
139
|
+
encrypter.encrypt(MultiJson.dump(header), payload)
|
133
140
|
end
|
134
141
|
|
135
|
-
# Decodes and validates a signed and/or encrypted JSON Web Token, recursing
|
136
|
-
#
|
142
|
+
# Decodes and validates a signed and/or encrypted JSON Web Token, recursing into any nested tokens, and returns the
|
143
|
+
# payload.
|
137
144
|
#
|
138
|
-
# The block is called with the token header as the first parameter, and should
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
# options parameter which can be used to override the {DEFAULT_OPTIONS} on a
|
143
|
-
# per-token basis; options are not persisted between yields.
|
145
|
+
# The block is called with the token header as the first parameter, and should return the appropriate signature or
|
146
|
+
# decryption method to either validate the signature or decrypt the token as applicable. When the tokens are nested,
|
147
|
+
# this block will be called once per token. It can optionally have a second options parameter which can be used to
|
148
|
+
# override the {DEFAULT_OPTIONS} on a per-token basis; options are not persisted between yields.
|
144
149
|
#
|
145
150
|
# @param token [String] The encoded JSON Web Token.
|
146
151
|
# @param depth [Integer] The maximum depth of token nesting to decode to.
|
147
152
|
# @yieldparam header [Hash] The JWT header values.
|
148
|
-
# @yieldparam options [Hash] (Optional) A hash that can be used to override
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
# @
|
153
|
-
# otherwise as a String.
|
154
|
-
# @raise [Sandal::ClaimError] One or more claims in the token is invalid.
|
155
|
-
# @raise [Sandal::TokenError] The token format is invalid, or validation of
|
156
|
-
# the token failed.
|
153
|
+
# @yieldparam options [Hash] (Optional) A hash that can be used to override the default options.
|
154
|
+
# @yieldreturn [#valid? or #decrypt] The signature validator if the token is signed, or the token decrypter if the
|
155
|
+
# token is encrypted.
|
156
|
+
# @return [Hash or String] The payload of the token as a Hash if it was JSON, otherwise as a String.
|
157
|
+
# @raise [Sandal::TokenError] The token is invalid or not supported.
|
157
158
|
def self.decode_token(token, depth = 16)
|
158
|
-
parts = token.split(
|
159
|
+
parts = token.split(".")
|
159
160
|
decoded_parts = decode_token_parts(parts)
|
160
161
|
header = decoded_parts[0]
|
161
162
|
|
@@ -163,10 +164,10 @@ module Sandal
|
|
163
164
|
decoder = yield header, options if block_given?
|
164
165
|
|
165
166
|
if is_encrypted?(parts)
|
166
|
-
payload = decoder.decrypt(parts
|
167
|
-
if header.has_key?(
|
168
|
-
unless header[
|
169
|
-
raise Sandal::
|
167
|
+
payload = decoder.decrypt(parts)
|
168
|
+
if header.has_key?("zip")
|
169
|
+
unless header["zip"] == "DEF"
|
170
|
+
raise Sandal::InvalidTokenError, "Invalid zip algorithm."
|
170
171
|
end
|
171
172
|
payload = Zlib::Inflate.inflate(payload)
|
172
173
|
end
|
@@ -177,7 +178,7 @@ module Sandal
|
|
177
178
|
end
|
178
179
|
end
|
179
180
|
|
180
|
-
if header[
|
181
|
+
if header["cty"] == "JWT"
|
181
182
|
if depth > 0
|
182
183
|
if block_given?
|
183
184
|
decode_token(payload, depth - 1, &Proc.new)
|
@@ -197,9 +198,9 @@ module Sandal
|
|
197
198
|
# Decodes and validates a signed JSON Web Token.
|
198
199
|
def self.validate_signature(parts, signature, validator)
|
199
200
|
validator ||= Sandal::Sig::NONE
|
200
|
-
secured_input = parts.take(2).join(
|
201
|
+
secured_input = parts.take(2).join(".")
|
201
202
|
unless validator.valid?(signature, secured_input)
|
202
|
-
raise TokenError,
|
203
|
+
raise TokenError, "Invalid signature."
|
203
204
|
end
|
204
205
|
end
|
205
206
|
|
@@ -209,7 +210,7 @@ module Sandal
|
|
209
210
|
parts[0] = MultiJson.load(parts[0])
|
210
211
|
parts
|
211
212
|
rescue
|
212
|
-
raise TokenError,
|
213
|
+
raise TokenError, "Invalid token encoding."
|
213
214
|
end
|
214
215
|
|
215
216
|
# Parses the content of a token and validates the claims if is JSON claims.
|
data/lib/sandal/claims.rb
CHANGED
@@ -21,14 +21,14 @@ module Sandal
|
|
21
21
|
#
|
22
22
|
# @param max_clock_skew [Numeric] The maximum clock skew, in seconds.
|
23
23
|
# @return [void].
|
24
|
-
# @raise [Sandal::ClaimError] The
|
24
|
+
# @raise [Sandal::ClaimError] The "exp" claim is invalid, or the token has
|
25
25
|
# expired.
|
26
26
|
def validate_exp(max_clock_skew = 0)
|
27
27
|
max_clock_skew ||= 0
|
28
28
|
|
29
|
-
exp = time_claim(
|
29
|
+
exp = time_claim("exp")
|
30
30
|
if exp && exp <= (Time.now - max_clock_skew)
|
31
|
-
raise Sandal::
|
31
|
+
raise Sandal::ExpiredTokenError, "The token has expired."
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -36,14 +36,14 @@ module Sandal
|
|
36
36
|
#
|
37
37
|
# @param max_clock_skew [Numeric] The maximum clock skew, in seconds.
|
38
38
|
# @return [void].
|
39
|
-
# @raise [Sandal::ClaimError] The
|
39
|
+
# @raise [Sandal::ClaimError] The "nbf" claim is invalid, or the token is
|
40
40
|
# not valid yet.
|
41
41
|
def validate_nbf(max_clock_skew = 0)
|
42
42
|
max_clock_skew ||= 0
|
43
43
|
|
44
|
-
nbf = time_claim(
|
44
|
+
nbf = time_claim("nbf")
|
45
45
|
if nbf && nbf > (Time.now + max_clock_skew)
|
46
|
-
raise Sandal::ClaimError,
|
46
|
+
raise Sandal::ClaimError, "The token is not valid yet."
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -51,12 +51,12 @@ module Sandal
|
|
51
51
|
#
|
52
52
|
# @param valid_iss [Array] The valid issuers.
|
53
53
|
# @return [void].
|
54
|
-
# @raise [Sandal::ClaimError] The
|
54
|
+
# @raise [Sandal::ClaimError] The "iss" claim value is not a valid issuer.
|
55
55
|
def validate_iss(valid_iss)
|
56
56
|
return unless valid_iss && valid_iss.length > 0
|
57
57
|
|
58
|
-
unless valid_iss.include?(self[
|
59
|
-
raise Sandal::ClaimError,
|
58
|
+
unless valid_iss.include?(self["iss"])
|
59
|
+
raise Sandal::ClaimError, "The issuer is invalid."
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -64,15 +64,15 @@ module Sandal
|
|
64
64
|
#
|
65
65
|
# @param valid_aud [Array] The valid audiences.
|
66
66
|
# @return [void].
|
67
|
-
# @raise [Sandal::ClaimError] The
|
67
|
+
# @raise [Sandal::ClaimError] The "aud" claim value does not contain a valid
|
68
68
|
# audience.
|
69
69
|
def validate_aud(valid_aud)
|
70
70
|
return unless valid_aud && valid_aud.length > 0
|
71
71
|
|
72
|
-
aud = self[
|
72
|
+
aud = self["aud"]
|
73
73
|
aud = [aud] unless aud.is_a?(Array)
|
74
74
|
unless (aud & valid_aud).length > 0
|
75
|
-
raise Sandal::ClaimError,
|
75
|
+
raise Sandal::ClaimError, "The audence is invalid."
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
@@ -85,7 +85,7 @@ module Sandal
|
|
85
85
|
begin
|
86
86
|
Time.at(claim)
|
87
87
|
rescue
|
88
|
-
raise Sandal::ClaimError, "The
|
88
|
+
raise Sandal::ClaimError, "The "#{name}" claim is invalid."
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
data/lib/sandal/enc.rb
CHANGED
@@ -1,60 +1,26 @@
|
|
1
|
-
require
|
1
|
+
require "openssl"
|
2
|
+
require "sandal/util"
|
2
3
|
|
3
4
|
module Sandal
|
4
5
|
# Contains encryption (JWE) functionality.
|
5
6
|
module Enc
|
6
7
|
|
7
|
-
#
|
8
|
+
# Gets the decoded parts of a JWE token.
|
8
9
|
#
|
9
|
-
# @param
|
10
|
-
# @
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def self.concat_kdf(digest, key, keydatalen, algorithm_id,
|
19
|
-
party_u_info, party_v_info,
|
20
|
-
supp_pub_info = nil, supp_priv_info = nil)
|
21
|
-
digest = OpenSSL::Digest.new(digest) if digest.is_a?(String)
|
22
|
-
rounds = (keydatalen / (digest.digest_length * 8.0)).ceil
|
23
|
-
|
24
|
-
round_input = concat_kdf_round_input(key, keydatalen, algorithm_id,
|
25
|
-
party_u_info, party_v_info,
|
26
|
-
supp_pub_info, supp_priv_info)
|
27
|
-
|
28
|
-
(1..rounds).reduce('') do |output, round|
|
29
|
-
hash = digest.digest([round].pack('N') + round_input)
|
30
|
-
if round == rounds
|
31
|
-
round_bits = keydatalen % (digest.digest_length * 8)
|
32
|
-
hash = hash[0...(round_bits / 8)] unless round_bits == 0
|
33
|
-
end
|
34
|
-
output << hash
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
# The round input for the Concat KDF function (excluding round number).
|
41
|
-
def self.concat_kdf_round_input(key, keydatalen, algorithm_id,
|
42
|
-
party_u_info, party_v_info,
|
43
|
-
supp_pub_info, supp_priv_info)
|
44
|
-
input = ''.force_encoding('binary')
|
45
|
-
input << key.force_encoding('binary')
|
46
|
-
input << [keydatalen].pack('N')
|
47
|
-
input << algorithm_id.force_encoding('binary')
|
48
|
-
input << (party_u_info == 0 ? [0].pack('N') : party_u_info.force_encoding('binary'))
|
49
|
-
input << (party_v_info == 0 ? [0].pack('N') : party_v_info.force_encoding('binary'))
|
50
|
-
input << supp_pub_info.force_encoding('binary') if supp_pub_info
|
51
|
-
input << supp_priv_info.force_encoding('binary') if supp_priv_info
|
52
|
-
input
|
10
|
+
# @param token [String or Array] The token, or encoded token parts.
|
11
|
+
# @return [[Array, Array]] The encoded parts and the decoded parts.
|
12
|
+
def self.token_parts(token)
|
13
|
+
parts = token.is_a?(Array) ? token : token.split(".")
|
14
|
+
raise ArgumentError unless parts.length == 5
|
15
|
+
decoded_parts = parts.map { |part| jwt_base64_decode(part) }
|
16
|
+
return parts, decoded_parts
|
17
|
+
rescue ArgumentError
|
18
|
+
raise Sandal::InvalidTokenError, "Invalid token encoding."
|
53
19
|
end
|
54
20
|
|
55
21
|
end
|
56
22
|
end
|
57
23
|
|
58
|
-
require
|
59
|
-
require
|
60
|
-
require
|
24
|
+
require "sandal/enc/acbc_hs"
|
25
|
+
require "sandal/enc/agcm" unless RUBY_VERSION < "2.0.0"
|
26
|
+
require "sandal/enc/alg"
|