jose 1.1.1 → 1.1.2

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: 0d737f594b6ef3c926a323bc2c06b797ce24fc09
4
- data.tar.gz: 8a4989e67d3dcbea62c84f1f60a40b41f3ca5a74
3
+ metadata.gz: aa018b696c9f264acc7691bb2ae92a7e48ec95e7
4
+ data.tar.gz: c07468825b96248e7e15376711e573913f0d33ce
5
5
  SHA512:
6
- metadata.gz: 5f079c8178b435afd07a54c61e415b84ac4f9c0197b7961adde3313e460088a1b979a3d79f8308d4a64be686d5d4da7dba4af1bce38dc918c198102898717279
7
- data.tar.gz: 569191e6793162f0ca29a9efa2d45fd09208f629b8e2e043ca08db21c4590f58c15aec92af220b7ad32bc2f8a3bc29819ef5efe1cdd81d2bb58bacdca8002e46
6
+ metadata.gz: 41a28230b46f5e9ea6ef56c7c8bdc2f353f7472f18faea6923d39326eb8d87f77a3ae247d22181ef5a4babe550cab1db31361e657d066959e8629a6df87c8e6d
7
+ data.tar.gz: 00c55722c8dc85d65c53a7628abdd9baa4c536d409249dd5de4487a7b3d8e34254035151526cbedf520809401153604f7c301705274d70d02fbc05fe1665a4e2
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.2 (2016-07-07)
4
+
5
+ * Enhancements
6
+ * Improved handling of RSA private keys in SMF (Straightforward Method) form to CRT (Chinese Remainder Theorem) form, see [potatosalad/erlang-jose#19](https://github.com/potatosalad/erlang-jose/issues/19) This is especially useful for keys produced by Java programs using the `RSAPrivateKeySpec` API as mentioned in [Section 9.3 of RFC 7517](https://tools.ietf.org/html/rfc7517#section-9.3).
7
+ * Updated EdDSA operations to comply with draft 04 of [draft-ietf-jose-cfrg-curves-04](https://tools.ietf.org/html/draft-ietf-jose-cfrg-curves-04).
8
+
9
+ * Fixes
10
+ * Fixed compression encoding bug for `{"zip":"DEF"}` operations (thanks to [@amadden734](https://github.com/amadden734) see [#3](https://github.com/potatosalad/ruby-jose/pull/3))
11
+
3
12
  ## 1.1.1 (2016-05-27)
4
13
 
5
14
  * Enhancements
@@ -21,6 +21,7 @@ Here are the supported options for the `alg` parameter, grouped by similar funci
21
21
  - [`Ed25519ph`](http://www.rubydoc.info/gems/jose/JOSE/JWS#EdDSA-25519-group)
22
22
  - [`Ed448`](http://www.rubydoc.info/gems/jose/JOSE/JWS#EdDSA-448-group)
23
23
  - [`Ed448ph`](http://www.rubydoc.info/gems/jose/JOSE/JWS#EdDSA-448-group)
24
+ - [`EdDSA`](http://www.rubydoc.info/gems/jose/JOSE/JWS#EdDSA-group)
24
25
  - HMAC using SHA-2
25
26
  - [`HS256`](http://www.rubydoc.info/gems/jose/JOSE/JWS#HMACSHA2-group)
26
27
  - [`HS384`](http://www.rubydoc.info/gems/jose/JOSE/JWS#HMACSHA2-group)
@@ -104,6 +104,7 @@ module JOSE
104
104
  # # "Ed25519ph",
105
105
  # # "Ed448",
106
106
  # # "Ed448ph",
107
+ # # "EdDSA",
107
108
  # # "ES256",
108
109
  # # "ES384",
109
110
  # # "ES512",
@@ -161,6 +162,7 @@ module JOSE
161
162
  'Ed25519ph',
162
163
  'Ed448',
163
164
  'Ed448ph',
165
+ 'EdDSA',
164
166
  'ES256',
165
167
  'ES384',
166
168
  'ES512',
@@ -1,4 +1,4 @@
1
- class JOSE::JWE::ZIP_DEF
1
+ class JOSE::JWE::ZIP_DEF < Struct.new(nil)
2
2
 
3
3
  # JOSE::JWE callbacks
4
4
 
@@ -18,11 +18,19 @@ class JOSE::JWE::ZIP_DEF
18
18
  # JOSE::JWE::ZIP callbacks
19
19
 
20
20
  def compress(plain_text)
21
- return Zlib.deflate(plain_text)
21
+ zstream = Zlib::Deflate.new(nil, -Zlib::MAX_WBITS)
22
+ buf = zstream.deflate(plain_text, Zlib::FINISH)
23
+ zstream.finish
24
+ zstream.close
25
+ return buf
22
26
  end
23
27
 
24
28
  def uncompress(cipher_text)
25
- return Zlib.inflate(cipher_text)
29
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
30
+ buf = zstream.inflate(cipher_text)
31
+ zstream.finish
32
+ zstream.close
33
+ return buf
26
34
  end
27
35
 
28
36
  end
@@ -78,8 +78,8 @@ class JOSE::JWK::KTY_OKP_Ed25519 < Struct.new(:okp)
78
78
  return JOSE::JWK::KTY.key_encryptor(self, fields, key)
79
79
  end
80
80
 
81
- def sign(message, digest_type)
82
- raise ArgumentError, "'digest_type' must be :Ed25519" if digest_type != :Ed25519
81
+ def sign(message, sign_type)
82
+ raise ArgumentError, "'sign_type' must be :Ed25519 or :EdDSA" if sign_type != :Ed25519 and sign_type != :EdDSA
83
83
  raise NotImplementedError, "Ed25519 public key cannot be used for signing" if okp.bytesize != SK_BYTES
84
84
  return JOSE::JWA::Curve25519.ed25519_sign(message, okp)
85
85
  end
@@ -88,7 +88,7 @@ class JOSE::JWK::KTY_OKP_Ed25519 < Struct.new(:okp)
88
88
  if okp.bytesize == SK_BYTES and fields and fields['use'] == 'sig' and not fields['alg'].nil?
89
89
  return JOSE::Map['alg' => fields['alg']]
90
90
  elsif okp.bytesize == SK_BYTES
91
- return JOSE::Map['alg' => 'Ed25519']
91
+ return JOSE::Map['alg' => 'EdDSA']
92
92
  else
93
93
  raise ArgumentError, "signing not supported for public keys"
94
94
  end
@@ -98,12 +98,12 @@ class JOSE::JWK::KTY_OKP_Ed25519 < Struct.new(:okp)
98
98
  if fields and fields['use'] == 'sig' and not fields['alg'].nil?
99
99
  return [fields['alg']]
100
100
  else
101
- return ['Ed25519']
101
+ return ['Ed25519', 'EdDSA']
102
102
  end
103
103
  end
104
104
 
105
- def verify(message, digest_type, signature)
106
- raise ArgumentError, "'digest_type' must be :Ed25519" if digest_type != :Ed25519
105
+ def verify(message, sign_type, signature)
106
+ raise ArgumentError, "'sign_type' must be :Ed25519 or :EdDSA" if sign_type != :Ed25519 and sign_type != :EdDSA
107
107
  pk = okp
108
108
  pk = JOSE::JWA::Curve25519.ed25519_secret_to_public(okp) if okp.bytesize == SK_BYTES
109
109
  return JOSE::JWA::Curve25519.ed25519_verify(signature, message, pk)
@@ -79,7 +79,7 @@ class JOSE::JWK::KTY_OKP_Ed25519ph < Struct.new(:okp)
79
79
  end
80
80
 
81
81
  def sign(message, sign_type)
82
- raise ArgumentError, "'sign_type' must be :Ed25519ph" if sign_type != :Ed25519ph
82
+ raise ArgumentError, "'sign_type' must be :Ed25519ph or :EdDSA" if sign_type != :Ed25519ph and sign_type != :EdDSA
83
83
  raise NotImplementedError, "Ed25519ph public key cannot be used for signing" if okp.bytesize != SK_BYTES
84
84
  return JOSE::JWA::Curve25519.ed25519ph_sign(message, okp)
85
85
  end
@@ -88,7 +88,7 @@ class JOSE::JWK::KTY_OKP_Ed25519ph < Struct.new(:okp)
88
88
  if okp.bytesize == SK_BYTES and fields and fields['use'] == 'sig' and not fields['alg'].nil?
89
89
  return JOSE::Map['alg' => fields['alg']]
90
90
  elsif okp.bytesize == SK_BYTES
91
- return JOSE::Map['alg' => 'Ed25519ph']
91
+ return JOSE::Map['alg' => 'EdDSA']
92
92
  else
93
93
  raise ArgumentError, "signing not supported for public keys"
94
94
  end
@@ -98,12 +98,12 @@ class JOSE::JWK::KTY_OKP_Ed25519ph < Struct.new(:okp)
98
98
  if fields and fields['use'] == 'sig' and not fields['alg'].nil?
99
99
  return [fields['alg']]
100
100
  else
101
- return ['Ed25519ph']
101
+ return ['Ed25519ph', 'EdDSA']
102
102
  end
103
103
  end
104
104
 
105
105
  def verify(message, sign_type, signature)
106
- raise ArgumentError, "'sign_type' must be :Ed25519ph" if sign_type != :Ed25519ph
106
+ raise ArgumentError, "'sign_type' must be :Ed25519ph or :EdDSA" if sign_type != :Ed25519ph and sign_type != :EdDSA
107
107
  pk = okp
108
108
  pk = JOSE::JWA::Curve25519.ed25519ph_secret_to_public(okp) if okp.bytesize == SK_BYTES
109
109
  return JOSE::JWA::Curve25519.ed25519ph_verify(signature, message, pk)
@@ -78,8 +78,8 @@ class JOSE::JWK::KTY_OKP_Ed448 < Struct.new(:okp)
78
78
  return JOSE::JWK::KTY.key_encryptor(self, fields, key)
79
79
  end
80
80
 
81
- def sign(message, digest_type)
82
- raise ArgumentError, "'digest_type' must be :Ed448" if digest_type != :Ed448
81
+ def sign(message, sign_type)
82
+ raise ArgumentError, "'sign_type' must be :Ed448 or :EdDSA" if sign_type != :Ed448 and sign_type != :EdDSA
83
83
  raise NotImplementedError, "Ed448 public key cannot be used for signing" if okp.bytesize != SK_BYTES
84
84
  return JOSE::JWA::Curve448.ed448_sign(message, okp)
85
85
  end
@@ -88,7 +88,7 @@ class JOSE::JWK::KTY_OKP_Ed448 < Struct.new(:okp)
88
88
  if okp.bytesize == SK_BYTES and fields and fields['use'] == 'sig' and not fields['alg'].nil?
89
89
  return JOSE::Map['alg' => fields['alg']]
90
90
  elsif okp.bytesize == SK_BYTES
91
- return JOSE::Map['alg' => 'Ed448']
91
+ return JOSE::Map['alg' => 'EdDSA']
92
92
  else
93
93
  raise ArgumentError, "signing not supported for public keys"
94
94
  end
@@ -98,12 +98,12 @@ class JOSE::JWK::KTY_OKP_Ed448 < Struct.new(:okp)
98
98
  if fields and fields['use'] == 'sig' and not fields['alg'].nil?
99
99
  return [fields['alg']]
100
100
  else
101
- return ['Ed448']
101
+ return ['Ed448', 'EdDSA']
102
102
  end
103
103
  end
104
104
 
105
- def verify(message, digest_type, signature)
106
- raise ArgumentError, "'digest_type' must be :Ed448" if digest_type != :Ed448
105
+ def verify(message, sign_type, signature)
106
+ raise ArgumentError, "'sign_type' must be :Ed448 or :EdDSA" if sign_type != :Ed448 and sign_type != :EdDSA
107
107
  pk = okp
108
108
  pk = JOSE::JWA::Curve448.ed448_secret_to_public(okp) if okp.bytesize == SK_BYTES
109
109
  return JOSE::JWA::Curve448.ed448_verify(signature, message, pk)
@@ -78,8 +78,8 @@ class JOSE::JWK::KTY_OKP_Ed448ph < Struct.new(:okp)
78
78
  return JOSE::JWK::KTY.key_encryptor(self, fields, key)
79
79
  end
80
80
 
81
- def sign(message, digest_type)
82
- raise ArgumentError, "'digest_type' must be :Ed448ph" if digest_type != :Ed448ph
81
+ def sign(message, sign_type)
82
+ raise ArgumentError, "'sign_type' must be :Ed448ph or :EdDSA" if sign_type != :Ed448ph and sign_type != :EdDSA
83
83
  raise NotImplementedError, "Ed448ph public key cannot be used for signing" if okp.bytesize != SK_BYTES
84
84
  return JOSE::JWA::Curve448.ed448ph_sign(message, okp)
85
85
  end
@@ -88,7 +88,7 @@ class JOSE::JWK::KTY_OKP_Ed448ph < Struct.new(:okp)
88
88
  if okp.bytesize == SK_BYTES and fields and fields['use'] == 'sig' and not fields['alg'].nil?
89
89
  return JOSE::Map['alg' => fields['alg']]
90
90
  elsif okp.bytesize == SK_BYTES
91
- return JOSE::Map['alg' => 'Ed448ph']
91
+ return JOSE::Map['alg' => 'EdDSA']
92
92
  else
93
93
  raise ArgumentError, "signing not supported for public keys"
94
94
  end
@@ -98,12 +98,12 @@ class JOSE::JWK::KTY_OKP_Ed448ph < Struct.new(:okp)
98
98
  if fields and fields['use'] == 'sig' and not fields['alg'].nil?
99
99
  return [fields['alg']]
100
100
  else
101
- return ['Ed448ph']
101
+ return ['Ed448ph', 'EdDSA']
102
102
  end
103
103
  end
104
104
 
105
- def verify(message, digest_type, signature)
106
- raise ArgumentError, "'digest_type' must be :Ed448ph" if digest_type != :Ed448ph
105
+ def verify(message, sign_type, signature)
106
+ raise ArgumentError, "'sign_type' must be :Ed448ph or :EdDSA" if sign_type != :Ed448ph and sign_type != :EdDSA
107
107
  pk = okp
108
108
  pk = JOSE::JWA::Curve448.ed448ph_secret_to_public(okp) if okp.bytesize == SK_BYTES
109
109
  return JOSE::JWA::Curve448.ed448ph_verify(signature, message, pk)
@@ -19,7 +19,11 @@ class JOSE::JWK::KTY_RSA < Struct.new(:key)
19
19
  rsa.iqmp = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['qi']), 2)
20
20
  return JOSE::JWK::KTY_RSA.new(JOSE::JWK::PKeyProxy.new(rsa)), fields.except('kty', 'd', 'dp', 'dq', 'e', 'n', 'p', 'q', 'qi')
21
21
  else
22
- raise ArgumentError, "invalid 'RSA' JWK"
22
+ d = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['d']), 2)
23
+ e = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['e']), 2)
24
+ n = OpenSSL::BN.new(JOSE.urlsafe_decode64(fields['n']), 2)
25
+ rsa = convert_sfm_to_crt(d, e, n)
26
+ return JOSE::JWK::KTY_RSA.new(JOSE::JWK::PKeyProxy.new(rsa)), fields.except('kty', 'd', 'dp', 'dq', 'e', 'n', 'p', 'q', 'qi')
23
27
  end
24
28
  else
25
29
  rsa = OpenSSL::PKey::RSA.new
@@ -200,4 +204,64 @@ class JOSE::JWK::KTY_RSA < Struct.new(:key)
200
204
  return JOSE::JWK::PEM.to_binary(key, password)
201
205
  end
202
206
 
207
+ # Internal functions
208
+
209
+ private
210
+ def self.convert_sfm_to_crt(d, e, n)
211
+ ktot = d * e - 1
212
+ t = convert_sfm_to_crt_find_t(ktot)
213
+ a = 2.to_bn
214
+ k = t
215
+ p = convert_sfm_to_crt_find_p(ktot, t, k, a, n, d)
216
+ q, = n / p
217
+ if q > p
218
+ p, q = q, p
219
+ end
220
+ dp = d % (p - 1)
221
+ dq = d % (q - 1)
222
+ qi = q.mod_inverse(p)
223
+ rsa = OpenSSL::PKey::RSA.new
224
+ rsa.d = d
225
+ rsa.dmp1 = dp
226
+ rsa.dmq1 = dq
227
+ rsa.e = e
228
+ rsa.n = n
229
+ rsa.p = p
230
+ rsa.q = q
231
+ rsa.iqmp = qi
232
+ return rsa
233
+ end
234
+
235
+ def self.convert_sfm_to_crt_find_t(ktot)
236
+ t = ktot
237
+ loop do
238
+ if t > 0 and (t % 2) == 0
239
+ t, = t / 2
240
+ else
241
+ break
242
+ end
243
+ end
244
+ return t
245
+ end
246
+
247
+ def self.convert_sfm_to_crt_find_p(ktot, t, k, a, n, d)
248
+ p = nil
249
+ loop do
250
+ break if not p.nil?
251
+ loop do
252
+ break if not p.nil?
253
+ break if k >= ktot
254
+ c = a.mod_exp(k, n)
255
+ if c != 1 and c != (n - 1) and c.mod_exp(2, n) == 1
256
+ p = (c + 1).gcd(n)
257
+ else
258
+ k = k * 2
259
+ end
260
+ end
261
+ break if not p.nil?
262
+ k = t
263
+ a = a + 2
264
+ end
265
+ return p
266
+ end
203
267
  end
@@ -59,6 +59,7 @@ module JOSE
59
59
  # * `"Ed25519ph"`
60
60
  # * `"Ed448"`
61
61
  # * `"Ed448ph"`
62
+ # * `"EdDSA"`
62
63
  # * `"ES256"`
63
64
  # * `"ES384"`
64
65
  # * `"ES512"`
@@ -115,6 +116,18 @@ module JOSE
115
116
  # JOSE::JWS.verify(jwk_ed448ph, signed_ed448ph).first
116
117
  # # => true
117
118
  #
119
+ # ### <a name="EdDSA-group">EdDSA</a>
120
+ #
121
+ # # EdDSA works with Ed25519, Ed25519ph, Ed448, and Ed448ph keys.
122
+ # # However, it defaults to Ed25519 for key generation.
123
+ # jwk_eddsa = JOSE::JWS.generate_key({ "alg" => "EdDSA" })
124
+ #
125
+ # # EdDSA
126
+ # signed_eddsa = JOSE::JWS.sign(jwk_eddsa, "{}", { "alg" => "EdDSA" }).compact
127
+ # # => "eyJhbGciOiJFZERTQSJ9.e30.rhb5ZY7MllNbW9q-SCn_NglhYtaRGMXEUDj6BvJjltOt19tEI_1wFrVK__jL91i9hO7WtVqRH_OfHiilnO1CAQ"
128
+ # JOSE::JWS.verify(jwk_eddsa, signed_eddsa).first
129
+ # # => true
130
+ #
118
131
  # ### <a name="ECDSA-group">ES256, ES384, and ES512</a>
119
132
  #
120
133
  # !!!ruby
@@ -681,7 +694,13 @@ module JOSE
681
694
 
682
695
  private
683
696
 
684
- EDDSA_ALG_LIST = ['Ed25519'.freeze, 'Ed25519ph'.freeze, 'Ed448'.freeze, 'Ed448ph'.freeze].freeze
697
+ EDDSA_ALG_LIST = [
698
+ 'Ed25519'.freeze,
699
+ 'Ed25519ph'.freeze,
700
+ 'Ed448'.freeze,
701
+ 'Ed448ph'.freeze,
702
+ 'EdDSA'.freeze
703
+ ].freeze
685
704
 
686
705
  def self.from_fields(jws, modules)
687
706
  if jws.fields.has_key?('b64')
@@ -12,6 +12,8 @@ class JOSE::JWS::ALG_EDDSA < Struct.new(:sign_type)
12
12
  return new(:Ed448), fields.delete('alg')
13
13
  when 'Ed448ph'
14
14
  return new(:Ed448ph), fields.delete('alg')
15
+ when 'EdDSA'
16
+ return new(:EdDSA), fields.delete('alg')
15
17
  else
16
18
  raise ArgumentError, "invalid 'alg' for JWS: #{fields['alg'].inspect}"
17
19
  end
@@ -25,7 +27,8 @@ class JOSE::JWS::ALG_EDDSA < Struct.new(:sign_type)
25
27
  # JOSE::JWS::ALG callbacks
26
28
 
27
29
  def generate_key(fields)
28
- return JOSE::JWS::ALG.generate_key([:okp, sign_type], sign_type.to_s)
30
+ okp_type = sign_type == :EdDSA ? :Ed25519 : sign_type
31
+ return JOSE::JWS::ALG.generate_key([:okp, okp_type], sign_type.to_s)
29
32
  end
30
33
 
31
34
  def sign(jwk, message)
@@ -1,3 +1,3 @@
1
1
  module JOSE
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jose
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Bennett
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-27 00:00:00.000000000 Z
11
+ date: 2016-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hamster