ruby-paseto 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a482c0e04e6f3a60a6bf1151dcfdfb32cab306d580f7d392ca7c2740f15e3d6
4
- data.tar.gz: a79d3252e153592445148cd375a5ffc26f5ac4b9d511ca8d7e7843257df8d932
3
+ metadata.gz: c5a6ccf377d7535330c1b0bf829685b548afc257e9a4e6b24b746e3e311485f2
4
+ data.tar.gz: ce2ebaa4d4d354cbc6c1145aa129e4b143f352b6346bff34462c6c729b2b9951
5
5
  SHA512:
6
- metadata.gz: 54caf50c77a71306c37a5fe7867d9b4151e7ba45f381f02a247bccec6f2b3008449a3d52830acfb702bc439518d5d5d8bf6ef84bdd7b7d9f5066fac84cd552db
7
- data.tar.gz: 72de66afb63eb7f82dc96fb1e87527410f7d6d3726942f5043ff143aee91270c768eed56d99df03301d86bbb507e83853ea72eab3ee192bf3b9d8faea7cef593
6
+ metadata.gz: 68befb60265a2a408f6066aebafd118477eaeaa6c0161b120e1550199e473b27713ba68c2e042f3e13e338aca648edfbc198b7584ae513b4c9b3a78cedd282ba
7
+ data.tar.gz: 8e3ed014b61f2b71e9f04a0b9ab06fd6d5485735f33670ee4d75e92425e4905072d73cc9271808601d64537192c218b2429f65166069257f31f187355770e4fd
data/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2023-01-02
3
+ ## [0.1.2]
4
+
5
+ - Fixed versioning in 0.1.1 changelog
6
+ - Removed support for ruby/openssl < 3.0.2
7
+
8
+ ## [0.1.1] - 2023-01-02
4
9
 
5
10
  - Relax the version constraint on openssl depedency
6
11
 
@@ -24,7 +24,7 @@ module Paseto
24
24
  end
25
25
 
26
26
  sig { params(input: String).returns(Interface::Key) }
27
- def generate(input) # rubocop:disable Metrics/MethodLength
27
+ def generate(input) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
28
28
  case self
29
29
  in K3LocalWrap | K3LocalPBKW | K3Local if input.bytesize == 32
30
30
  V3::Local.new(ikm: input)
data/lib/paseto/util.rb CHANGED
@@ -98,8 +98,7 @@ module Paseto
98
98
  def self.openssl?(major, minor = 0, fix = 0, patch = 0)
99
99
  return false if OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
100
100
 
101
- OpenSSL::OPENSSL_VERSION_NUMBER >=
102
- (major * 0x10000000) + (minor * 0x100000) + (fix * 0x1000) + (patch * 0x10)
101
+ (major * 0x10000000) + (minor * 0x100000) + (fix * 0x1000) + (patch * 0x10) <= OpenSSL::OPENSSL_VERSION_NUMBER
103
102
  end
104
103
  end
105
104
  end
@@ -131,74 +131,12 @@ module Paseto
131
131
 
132
132
  private
133
133
 
134
- # TODO: Figure out how to get SimpleCov to cover this consistently. With OSSL1.1.1, most of
135
- # this doesn't run. With OSSL3, check_key never raises...
136
- # :nocov:
137
-
138
- # The openssl gem as of 3.0.0 will prefer EVP_PKEY_public_check over EC_KEY_check_key
139
- # whenever the EVP api is available, which is always for the library here as we're requiring
140
- # 3.0.0 or greater. However, this has some problems.
141
- #
142
- # The behavior of EVP_PKEY_public_check is different between 1.1.1 and 3.x. Specifically,
143
- # it no longer calls the custom verifier method in EVP_PKEY_METHOD, and only checks the
144
- # correctness of the public component. This leads to a problem when calling EC#key_check,
145
- # as the private component is NEVER verified for an ECDSA key through the APIs that the gem
146
- # makes available to us.
147
- #
148
- # Until this is fixed in ruby/openssl, I am working around this by implementing the algorithm
149
- # used by EVP_PKEY_pairwise_check through the OpenSSL API.
150
- #
151
- # BUG: https://github.com/ruby/openssl/issues/563
152
- # https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_public_check.html
153
- # https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_public_check.html
154
134
  sig(:final) { returns(T::Boolean) }
155
135
  def custom_check_key
156
- begin
157
- @key.check_key
158
- rescue StandardError
159
- return false
160
- end
161
-
162
- return true unless private? && Util.openssl?(3)
163
-
164
- priv_key = @key.private_key
165
- group = @key.group
166
-
167
- # int ossl_ec_key_private_check(const EC_KEY *eckey)
168
- # {
169
- # ...
170
- # if (BN_cmp(eckey->priv_key, BN_value_one()) < 0
171
- # || BN_cmp(eckey->priv_key, eckey->group->order) >= 0) {
172
- # ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
173
- # return 0;
174
- # }
175
- # ...
176
- # }
177
- #
178
- # https://github.com/openssl/openssl/blob/5ac7cfb56211d18596e3c35baa942542f3c0189a/crypto/ec/ec_key.c#L510
179
- # private keys must be in range [1, order-1]
180
- return false if priv_key < OpenSSL::BN.new(1) || priv_key > group.order
181
-
182
- # int ossl_ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx)
183
- # {
184
- # ...
185
- # if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) {
186
- # ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
187
- # goto err;
188
- # }
189
- # if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
190
- # ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
191
- # goto err;
192
- # }
193
- # ...
194
- # }
195
- #
196
- # https://github.com/openssl/openssl/blob/5ac7cfb56211d18596e3c35baa942542f3c0189a/crypto/ec/ec_key.c#L529
197
- # Check generator * priv_key = pub_key
198
- @key.public_key == group.generator.mul(priv_key)
136
+ @key.check_key
137
+ rescue StandardError
138
+ false
199
139
  end
200
-
201
- # :nocov:
202
140
  end
203
141
  end
204
142
  end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Paseto
5
- VERSION = '0.1.1'
5
+ VERSION = '0.1.2'
6
6
  end
data/paseto.gemspec CHANGED
@@ -38,21 +38,9 @@ Gem::Specification.new do |spec|
38
38
  spec.require_paths = ['lib']
39
39
 
40
40
  spec.add_runtime_dependency 'multi_json', '~> 1.15.0'
41
- spec.add_runtime_dependency 'openssl', '~> 3.0'
41
+ spec.add_runtime_dependency 'openssl', '~> 3', '>= 3.0.2'
42
42
  spec.add_runtime_dependency 'sorbet-runtime'
43
43
  spec.add_runtime_dependency 'zeitwerk'
44
44
 
45
- spec.add_development_dependency 'appraisal'
46
- spec.add_development_dependency 'bundler', '~> 2'
47
- spec.add_development_dependency 'rake'
48
- spec.add_development_dependency 'rspec'
49
- spec.add_development_dependency 'rubocop', '~> 1.38.0'
50
- spec.add_development_dependency 'rubocop-performance', '~> 1.15.0'
51
- spec.add_development_dependency 'rubocop-rspec', '~> 2.14.2'
52
- spec.add_development_dependency 'rubocop-sorbet', '~> 0.6.11'
53
- spec.add_development_dependency 'simplecov'
54
- spec.add_development_dependency 'sorbet'
55
- spec.add_development_dependency 'timecop'
56
-
57
45
  spec.metadata['rubygems_mfa_required'] = 'true'
58
46
  end
@@ -6,7 +6,7 @@
6
6
 
7
7
  # An output formatter used internally by the lexer.
8
8
  #
9
- # source://irb//lib/irb/notifier.rb#17
9
+ # source://irb//lib/irb/notifier.rb#11
10
10
  module IRB::Notifier
11
11
  private
12
12
 
@@ -19,7 +19,7 @@ module IRB::Notifier
19
19
  # expressions will be sent directly to STDOUT without any additional
20
20
  # formatting.
21
21
  #
22
- # source://irb//lib/irb/notifier.rb#37
22
+ # source://irb//lib/irb/notifier.rb#31
23
23
  def def_notifier(prefix = T.unsafe(nil), output_method = T.unsafe(nil)); end
24
24
 
25
25
  class << self
@@ -32,7 +32,7 @@ module IRB::Notifier
32
32
  # expressions will be sent directly to STDOUT without any additional
33
33
  # formatting.
34
34
  #
35
- # source://irb//lib/irb/notifier.rb#37
35
+ # source://irb//lib/irb/notifier.rb#31
36
36
  def def_notifier(prefix = T.unsafe(nil), output_method = T.unsafe(nil)); end
37
37
  end
38
38
  end
@@ -41,20 +41,20 @@ end
41
41
  # LeveledNotifier to inherit. It provides several wrapper methods for the
42
42
  # OutputMethod object used by the Notifier.
43
43
  #
44
- # source://irb//lib/irb/notifier.rb#45
44
+ # source://irb//lib/irb/notifier.rb#39
45
45
  class IRB::Notifier::AbstractNotifier
46
46
  # Creates a new Notifier object
47
47
  #
48
48
  # @return [AbstractNotifier] a new instance of AbstractNotifier
49
49
  #
50
- # source://irb//lib/irb/notifier.rb#47
50
+ # source://irb//lib/irb/notifier.rb#41
51
51
  def initialize(prefix, base_notifier); end
52
52
 
53
53
  # Execute the given block if notifications are enabled.
54
54
  #
55
55
  # @yield [@base_notifier]
56
56
  #
57
- # source://irb//lib/irb/notifier.rb#105
57
+ # source://irb//lib/irb/notifier.rb#99
58
58
  def exec_if; end
59
59
 
60
60
  # A wrapper method used to determine whether notifications are enabled.
@@ -63,14 +63,14 @@ class IRB::Notifier::AbstractNotifier
63
63
  #
64
64
  # @return [Boolean]
65
65
  #
66
- # source://irb//lib/irb/notifier.rb#59
66
+ # source://irb//lib/irb/notifier.rb#53
67
67
  def notify?; end
68
68
 
69
69
  # Same as #ppx, except it uses the #prefix given during object
70
70
  # initialization.
71
71
  # See OutputMethod#ppx for more detail.
72
72
  #
73
- # source://irb//lib/irb/notifier.rb#88
73
+ # source://irb//lib/irb/notifier.rb#82
74
74
  def pp(*objs); end
75
75
 
76
76
  # Same as #pp, except it concatenates the given +prefix+ with the #prefix
@@ -78,33 +78,33 @@ class IRB::Notifier::AbstractNotifier
78
78
  #
79
79
  # See OutputMethod#ppx for more detail.
80
80
  #
81
- # source://irb//lib/irb/notifier.rb#98
81
+ # source://irb//lib/irb/notifier.rb#92
82
82
  def ppx(prefix, *objs); end
83
83
 
84
84
  # The +prefix+ for this Notifier, which is appended to all objects being
85
85
  # inspected during output.
86
86
  #
87
- # source://irb//lib/irb/notifier.rb#54
87
+ # source://irb//lib/irb/notifier.rb#48
88
88
  def prefix; end
89
89
 
90
90
  # See OutputMethod#print for more detail.
91
91
  #
92
- # source://irb//lib/irb/notifier.rb#64
92
+ # source://irb//lib/irb/notifier.rb#58
93
93
  def print(*opts); end
94
94
 
95
95
  # See OutputMethod#printf for more detail.
96
96
  #
97
- # source://irb//lib/irb/notifier.rb#74
97
+ # source://irb//lib/irb/notifier.rb#68
98
98
  def printf(format, *opts); end
99
99
 
100
100
  # See OutputMethod#printn for more detail.
101
101
  #
102
- # source://irb//lib/irb/notifier.rb#69
102
+ # source://irb//lib/irb/notifier.rb#63
103
103
  def printn(*opts); end
104
104
 
105
105
  # See OutputMethod#puts for more detail.
106
106
  #
107
- # source://irb//lib/irb/notifier.rb#79
107
+ # source://irb//lib/irb/notifier.rb#73
108
108
  def puts(*objs); end
109
109
  end
110
110
 
@@ -119,14 +119,14 @@ end
119
119
  # object you create, sibling notifiers can be initialized with
120
120
  # #def_notifier.
121
121
  #
122
- # source://irb//lib/irb/notifier.rb#122
122
+ # source://irb//lib/irb/notifier.rb#114
123
123
  class IRB::Notifier::CompositeNotifier < ::IRB::Notifier::AbstractNotifier
124
124
  # Create a new composite notifier object with the given +prefix+, and
125
125
  # +base_notifier+ to use for output.
126
126
  #
127
127
  # @return [CompositeNotifier] a new instance of CompositeNotifier
128
128
  #
129
- # source://irb//lib/irb/notifier.rb#123
129
+ # source://irb//lib/irb/notifier.rb#117
130
130
  def initialize(prefix, base_notifier); end
131
131
 
132
132
  # Creates a new LeveledNotifier in the composite #notifiers group.
@@ -136,12 +136,12 @@ class IRB::Notifier::CompositeNotifier < ::IRB::Notifier::AbstractNotifier
136
136
  #
137
137
  # This method returns the newly created instance.
138
138
  #
139
- # source://irb//lib/irb/notifier.rb#139
139
+ # source://irb//lib/irb/notifier.rb#133
140
140
  def def_notifier(level, prefix = T.unsafe(nil)); end
141
141
 
142
142
  # Returns the leveled notifier for this object
143
143
  #
144
- # source://irb//lib/irb/notifier.rb#146
144
+ # source://irb//lib/irb/notifier.rb#140
145
145
  def level; end
146
146
 
147
147
  # Sets the leveled notifier for this object.
@@ -159,12 +159,12 @@ class IRB::Notifier::CompositeNotifier < ::IRB::Notifier::AbstractNotifier
159
159
  # found in the existing #notifiers Array, or an instance of
160
160
  # AbstractNotifier
161
161
  #
162
- # source://irb//lib/irb/notifier.rb#163
162
+ # source://irb//lib/irb/notifier.rb#157
163
163
  def level=(value); end
164
164
 
165
165
  # Returns the leveled notifier for this object
166
166
  #
167
- # source://irb//lib/irb/notifier.rb#146
167
+ # source://irb//lib/irb/notifier.rb#140
168
168
  def level_notifier; end
169
169
 
170
170
  # Sets the leveled notifier for this object.
@@ -182,35 +182,35 @@ class IRB::Notifier::CompositeNotifier < ::IRB::Notifier::AbstractNotifier
182
182
  # found in the existing #notifiers Array, or an instance of
183
183
  # AbstractNotifier
184
184
  #
185
- # source://irb//lib/irb/notifier.rb#163
185
+ # source://irb//lib/irb/notifier.rb#157
186
186
  def level_notifier=(value); end
187
187
 
188
188
  # List of notifiers in the group
189
189
  #
190
- # source://irb//lib/irb/notifier.rb#131
190
+ # source://irb//lib/irb/notifier.rb#125
191
191
  def notifiers; end
192
192
  end
193
193
 
194
- # source://irb//lib/irb/notifier.rb#18
194
+ # source://irb//lib/irb/notifier.rb#12
195
195
  class IRB::Notifier::ErrUndefinedNotifier < ::StandardError
196
196
  # @return [ErrUndefinedNotifier] a new instance of ErrUndefinedNotifier
197
197
  #
198
- # source://irb//lib/irb/notifier.rb#19
198
+ # source://irb//lib/irb/notifier.rb#13
199
199
  def initialize(val); end
200
200
  end
201
201
 
202
- # source://irb//lib/irb/notifier.rb#23
202
+ # source://irb//lib/irb/notifier.rb#17
203
203
  class IRB::Notifier::ErrUnrecognizedLevel < ::StandardError
204
204
  # @return [ErrUnrecognizedLevel] a new instance of ErrUnrecognizedLevel
205
205
  #
206
- # source://irb//lib/irb/notifier.rb#24
206
+ # source://irb//lib/irb/notifier.rb#18
207
207
  def initialize(val); end
208
208
  end
209
209
 
210
210
  # A leveled notifier is comparable to the composite group from
211
211
  # CompositeNotifier#notifiers.
212
212
  #
213
- # source://irb//lib/irb/notifier.rb#181
213
+ # source://irb//lib/irb/notifier.rb#175
214
214
  class IRB::Notifier::LeveledNotifier < ::IRB::Notifier::AbstractNotifier
215
215
  include ::Comparable
216
216
 
@@ -223,7 +223,7 @@ class IRB::Notifier::LeveledNotifier < ::IRB::Notifier::AbstractNotifier
223
223
  #
224
224
  # @return [LeveledNotifier] a new instance of LeveledNotifier
225
225
  #
226
- # source://irb//lib/irb/notifier.rb#190
226
+ # source://irb//lib/irb/notifier.rb#184
227
227
  def initialize(base, level, prefix); end
228
228
 
229
229
  # Compares the level of this notifier object with the given +other+
@@ -231,12 +231,12 @@ class IRB::Notifier::LeveledNotifier < ::IRB::Notifier::AbstractNotifier
231
231
  #
232
232
  # See the Comparable module for more information.
233
233
  #
234
- # source://irb//lib/irb/notifier.rb#203
234
+ # source://irb//lib/irb/notifier.rb#197
235
235
  def <=>(other); end
236
236
 
237
237
  # The current level of this notifier object
238
238
  #
239
- # source://irb//lib/irb/notifier.rb#197
239
+ # source://irb//lib/irb/notifier.rb#191
240
240
  def level; end
241
241
 
242
242
  # Whether to output messages to the output method, depending on the level
@@ -244,7 +244,7 @@ class IRB::Notifier::LeveledNotifier < ::IRB::Notifier::AbstractNotifier
244
244
  #
245
245
  # @return [Boolean]
246
246
  #
247
- # source://irb//lib/irb/notifier.rb#209
247
+ # source://irb//lib/irb/notifier.rb#203
248
248
  def notify?; end
249
249
  end
250
250
 
@@ -254,13 +254,13 @@ end
254
254
  # This notifier is used as the +zero+ index, or level +0+, for
255
255
  # CompositeNotifier#notifiers, and will not output messages of any sort.
256
256
  #
257
- # source://irb//lib/irb/notifier.rb#220
257
+ # source://irb//lib/irb/notifier.rb#213
258
258
  class IRB::Notifier::NoMsgNotifier < ::IRB::Notifier::LeveledNotifier
259
259
  # Creates a new notifier that should not be used to output messages.
260
260
  #
261
261
  # @return [NoMsgNotifier] a new instance of NoMsgNotifier
262
262
  #
263
- # source://irb//lib/irb/notifier.rb#221
263
+ # source://irb//lib/irb/notifier.rb#215
264
264
  def initialize; end
265
265
 
266
266
  # Ensures notifications are ignored, see AbstractNotifier#notify? for
@@ -268,7 +268,7 @@ class IRB::Notifier::NoMsgNotifier < ::IRB::Notifier::LeveledNotifier
268
268
  #
269
269
  # @return [Boolean]
270
270
  #
271
- # source://irb//lib/irb/notifier.rb#229
271
+ # source://irb//lib/irb/notifier.rb#223
272
272
  def notify?; end
273
273
  end
274
274
 
@@ -276,7 +276,7 @@ end
276
276
  # IRB::Notifier. You can define your own output method to use with Irb.new,
277
277
  # or Context.new
278
278
  #
279
- # source://irb//lib/irb/output-method.rb#17
279
+ # source://irb//lib/irb/output-method.rb#11
280
280
  class IRB::OutputMethod
281
281
  # Returns an array of the given +format+ and +opts+ to be used by
282
282
  # Kernel#sprintf, if there was a successful Regexp match in the given
@@ -289,14 +289,14 @@ class IRB::OutputMethod
289
289
  # #<length modifier>(hh|h|l|ll|L|q|j|z|t)
290
290
  # <conversion specifier>[diouxXeEfgGcsb%]
291
291
  #
292
- # source://irb//lib/irb/output-method.rb#54
292
+ # source://irb//lib/irb/output-method.rb#48
293
293
  def parse_printf_format(format, opts); end
294
294
 
295
295
  # Prints the given +objs+ calling Object#inspect on each.
296
296
  #
297
297
  # See #puts for more detail.
298
298
  #
299
- # source://irb//lib/irb/output-method.rb#70
299
+ # source://irb//lib/irb/output-method.rb#64
300
300
  def pp(*objs); end
301
301
 
302
302
  # Prints the given +objs+ calling Object#inspect on each and appending the
@@ -304,7 +304,7 @@ class IRB::OutputMethod
304
304
  #
305
305
  # See #puts for more detail.
306
306
  #
307
- # source://irb//lib/irb/output-method.rb#78
307
+ # source://irb//lib/irb/output-method.rb#72
308
308
  def ppx(prefix, *objs); end
309
309
 
310
310
  # Open this method to implement your own output method, raises a
@@ -312,31 +312,31 @@ class IRB::OutputMethod
312
312
  #
313
313
  # @raise [NotImplementedError]
314
314
  #
315
- # source://irb//lib/irb/output-method.rb#26
315
+ # source://irb//lib/irb/output-method.rb#20
316
316
  def print(*opts); end
317
317
 
318
318
  # Extends IO#printf to format the given +opts+ for Kernel#sprintf using
319
319
  # #parse_printf_format
320
320
  #
321
- # source://irb//lib/irb/output-method.rb#37
321
+ # source://irb//lib/irb/output-method.rb#31
322
322
  def printf(format, *opts); end
323
323
 
324
324
  # Prints the given +opts+, with a newline delimiter.
325
325
  #
326
- # source://irb//lib/irb/output-method.rb#31
326
+ # source://irb//lib/irb/output-method.rb#25
327
327
  def printn(*opts); end
328
328
 
329
329
  # Calls #print on each element in the given +objs+, followed by a newline
330
330
  # character.
331
331
  #
332
- # source://irb//lib/irb/output-method.rb#60
332
+ # source://irb//lib/irb/output-method.rb#54
333
333
  def puts(*objs); end
334
334
  end
335
335
 
336
- # source://irb//lib/irb/output-method.rb#18
336
+ # source://irb//lib/irb/output-method.rb#12
337
337
  class IRB::OutputMethod::NotImplementedError < ::StandardError
338
338
  # @return [NotImplementedError] a new instance of NotImplementedError
339
339
  #
340
- # source://irb//lib/irb/output-method.rb#19
340
+ # source://irb//lib/irb/output-method.rb#13
341
341
  def initialize(val); end
342
342
  end
@@ -4,10 +4,10 @@
4
4
  # This is an autogenerated file for types exported from the `oj` gem.
5
5
  # Please instead update this file by running `bin/tapioca gem oj`.
6
6
 
7
- # source://json/2.6.3/lib/json/common.rb#35
7
+ # source://json/2.6.3/json/common.rb#35
8
8
  JSON::Parser = JSON::Ext::Parser
9
9
 
10
- # source://json/2.6.3/lib/json/common.rb#73
10
+ # source://json/2.6.3/json/common.rb#73
11
11
  JSON::State = JSON::Ext::Generator::State
12
12
 
13
13
  # source://oj//lib/oj.rb#2
@@ -24,6 +24,7 @@ module Oj
24
24
  def generate(*_arg0); end
25
25
  def load(*_arg0); end
26
26
  def load_file(*_arg0); end
27
+ def mem_report; end
27
28
  def mimic_JSON(*_arg0); end
28
29
  def object_load(*_arg0); end
29
30
  def optimize_rails; end
@@ -50,6 +51,7 @@ module Oj
50
51
  def generate(*_arg0); end
51
52
  def load(*_arg0); end
52
53
  def load_file(*_arg0); end
54
+ def mem_report; end
53
55
  def mimic_JSON(*_arg0); end
54
56
 
55
57
  # Loads mimic-ed JSON paths. Used by Oj.mimic_JSON().