jose 1.1.1 → 1.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
  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