jose 0.2.0 → 0.3.0

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.
@@ -67,11 +67,18 @@ class JOSE::JWK::KTY_RSA < Struct.new(:key)
67
67
 
68
68
  # JOSE::JWK::KTY callbacks
69
69
 
70
- def block_encryptor(fields, plain_text)
71
- return JOSE::Map[
72
- 'alg' => 'RSA-OAEP',
73
- 'enc' => 'A128GCM'
74
- ]
70
+ def block_encryptor(fields = nil)
71
+ if fields and fields['use'] == 'enc' and not fields['alg'].nil? and not fields['enc'].nil?
72
+ return JOSE::Map[
73
+ 'alg' => fields['alg'],
74
+ 'enc' => fields['enc']
75
+ ]
76
+ else
77
+ return JOSE::Map[
78
+ 'alg' => 'RSA-OAEP',
79
+ 'enc' => 'A128GCM'
80
+ ]
81
+ end
75
82
  end
76
83
 
77
84
  def decrypt_private(cipher_text, rsa_padding: :rsa_pkcs1_padding, rsa_oaep_md: nil)
@@ -146,8 +153,10 @@ class JOSE::JWK::KTY_RSA < Struct.new(:key)
146
153
  end
147
154
  end
148
155
 
149
- def signer(fields = nil, plain_text = nil)
150
- if key.private?
156
+ def signer(fields = nil)
157
+ if key.private? and fields and fields['use'] == 'sig' and not fields['alg'].nil?
158
+ return JOSE::Map['alg' => fields['alg']]
159
+ elsif key.private?
151
160
  return JOSE::Map['alg' => 'RS256']
152
161
  else
153
162
  raise ArgumentError, "signing not supported for public keys"
@@ -95,8 +95,7 @@ module JOSE
95
95
 
96
96
  def self.expand(binary)
97
97
  if binary.is_a?(String)
98
- parts = binary.split('.')
99
- if parts.length == 3
98
+ if binary.count('.') == 2 and (parts = binary.split('.', 3)).length == 3
100
99
  protected_binary, payload, signature = parts
101
100
  return JOSE::SignedMap[
102
101
  'payload' => payload,
@@ -111,6 +110,32 @@ module JOSE
111
110
  end
112
111
  end
113
112
 
113
+ def self.generate_key(object, modules = {})
114
+ return from(object, modules).generate_key
115
+ end
116
+
117
+ def generate_key
118
+ return alg.generate_key(fields)
119
+ end
120
+
121
+ def self.merge(left, right)
122
+ return from(left).merge(right)
123
+ end
124
+
125
+ def merge(object)
126
+ object = case object
127
+ when JOSE::Map, Hash
128
+ object
129
+ when String
130
+ JOSE.decode(object)
131
+ when JOSE::JWS
132
+ object.to_map
133
+ else
134
+ raise ArgumentError, "'object' must be a Hash, String, or JOSE::JWS"
135
+ end
136
+ return JOSE::JWS.from_map(self.to_map.merge(object))
137
+ end
138
+
114
139
  def self.peek_payload(signed)
115
140
  if signed.is_a?(String)
116
141
  signed = expand(signed)
@@ -163,7 +188,6 @@ module JOSE
163
188
  end
164
189
 
165
190
  def verify(key, plain_text, signature, protected_binary = JOSE.urlsafe_encode64(to_binary))
166
- payload = JOSE.urlsafe_encode64(plain_text)
167
191
  signing_input = signing_input(plain_text, protected_binary)
168
192
  return alg.verify(key, signing_input, signature), plain_text, self
169
193
  end
@@ -2,10 +2,18 @@ module JOSE::JWS::ALG
2
2
 
3
3
  extend self
4
4
 
5
+ def generate_key(parameters, algorithm)
6
+ return JOSE::JWK.generate_key(parameters).merge({
7
+ 'alg' => algorithm,
8
+ 'use' => 'sig'
9
+ })
10
+ end
11
+
5
12
  end
6
13
 
7
14
  require 'jose/jws/alg_ecdsa'
8
15
  require 'jose/jws/alg_eddsa'
9
16
  require 'jose/jws/alg_hmac'
17
+ require 'jose/jws/alg_none'
10
18
  require 'jose/jws/alg_rsa_pkcs1_v1_5'
11
19
  require 'jose/jws/alg_rsa_pss'
@@ -30,6 +30,19 @@ class JOSE::JWS::ALG_ECDSA < Struct.new(:digest)
30
30
 
31
31
  # JOSE::JWS::ALG callbacks
32
32
 
33
+ def generate_key(fields)
34
+ crv, alg = if digest == OpenSSL::Digest::SHA256
35
+ ['P-256', 'ES256']
36
+ elsif digest == OpenSSL::Digest::SHA384
37
+ ['P-384', 'ES384']
38
+ elsif digest == OpenSSL::Digest::SHA512
39
+ ['P-521', 'ES512']
40
+ else
41
+ raise ArgumentError, "unhandled ECDSA digest type: #{digest.inspect}"
42
+ end
43
+ return JOSE::JWS::ALG.generate_key([:ec, crv], alg)
44
+ end
45
+
33
46
  def sign(jwk, message)
34
47
  return jwk.kty.sign(message, digest)
35
48
  end
@@ -24,6 +24,10 @@ class JOSE::JWS::ALG_EDDSA < Struct.new(:sign_type)
24
24
 
25
25
  # JOSE::JWS::ALG callbacks
26
26
 
27
+ def generate_key(fields)
28
+ return JOSE::JWS::ALG.generate_key([:okp, sign_type], sign_type.to_s)
29
+ end
30
+
27
31
  def sign(jwk, message)
28
32
  return jwk.kty.sign(message, sign_type)
29
33
  end
@@ -30,6 +30,19 @@ class JOSE::JWS::ALG_HMAC < Struct.new(:hmac)
30
30
 
31
31
  # JOSE::JWS::ALG callbacks
32
32
 
33
+ def generate_key(fields)
34
+ bytesize, alg = if hmac == OpenSSL::Digest::SHA256
35
+ [32, 'HS256']
36
+ elsif hmac == OpenSSL::Digest::SHA384
37
+ [48, 'HS384']
38
+ elsif hmac == OpenSSL::Digest::SHA512
39
+ [64, 'HS512']
40
+ else
41
+ raise ArgumentError, "unhandled HMAC digest type: #{hmac.inspect}"
42
+ end
43
+ return JOSE::JWS::ALG.generate_key([:oct, bytesize], alg)
44
+ end
45
+
33
46
  def sign(jwk, message)
34
47
  return jwk.kty.sign(message, hmac)
35
48
  end
@@ -0,0 +1,44 @@
1
+ class JOSE::JWS::ALG_none < Struct.new(:none)
2
+
3
+ # JOSE::JWS callbacks
4
+
5
+ def self.from_map(fields)
6
+ case fields['alg']
7
+ when 'none'
8
+ return new(true), fields.delete('alg')
9
+ else
10
+ raise ArgumentError, "invalid 'alg' for JWS: #{fields['alg'].inspect}"
11
+ end
12
+ end
13
+
14
+ def to_map(fields)
15
+ return fields.put('alg', 'none')
16
+ end
17
+
18
+ # JOSE::JWS::ALG callbacks
19
+
20
+ def generate_key(fields)
21
+ raise NotImplementedError
22
+ end
23
+
24
+ def sign(jwk, message)
25
+ if JOSE.__unsecured_signing__
26
+ return ''
27
+ else
28
+ raise NotImplementedError
29
+ end
30
+ end
31
+
32
+ def verify(jwk, message, signature)
33
+ if JOSE.__unsecured_signing__
34
+ if signature == ''
35
+ return true
36
+ else
37
+ return false
38
+ end
39
+ else
40
+ raise NotImplementedError
41
+ end
42
+ end
43
+
44
+ end
@@ -30,6 +30,19 @@ class JOSE::JWS::ALG_RSA_PKCS1_V1_5 < Struct.new(:digest)
30
30
 
31
31
  # JOSE::JWS::ALG callbacks
32
32
 
33
+ def generate_key(fields)
34
+ bitsize, alg = if digest == OpenSSL::Digest::SHA256
35
+ [2048, 'RS256']
36
+ elsif digest == OpenSSL::Digest::SHA384
37
+ [3072, 'RS384']
38
+ elsif digest == OpenSSL::Digest::SHA512
39
+ [4096, 'RS512']
40
+ else
41
+ raise ArgumentError, "unhandled RSA_PKCS1_v1_5 digest type: #{digest.inspect}"
42
+ end
43
+ return JOSE::JWS::ALG.generate_key([:rsa, bitsize], alg)
44
+ end
45
+
33
46
  def sign(jwk, message)
34
47
  return jwk.kty.sign(message, digest, padding: :rsa_pkcs1_padding)
35
48
  end
@@ -30,6 +30,19 @@ class JOSE::JWS::ALG_RSA_PSS < Struct.new(:digest)
30
30
 
31
31
  # JOSE::JWS::ALG callbacks
32
32
 
33
+ def generate_key(fields)
34
+ bitsize, alg = if digest == OpenSSL::Digest::SHA256
35
+ [2048, 'PS256']
36
+ elsif digest == OpenSSL::Digest::SHA384
37
+ [3072, 'PS384']
38
+ elsif digest == OpenSSL::Digest::SHA512
39
+ [4096, 'PS512']
40
+ else
41
+ raise ArgumentError, "unhandled RSA_PSS digest type: #{digest.inspect}"
42
+ end
43
+ return JOSE::JWS::ALG.generate_key([:rsa, bitsize], alg)
44
+ end
45
+
33
46
  def sign(jwk, message)
34
47
  return jwk.kty.sign(message, digest, padding: :rsa_pkcs1_pss_padding)
35
48
  end
@@ -80,7 +80,7 @@ module JOSE
80
80
  plain_text = to_binary
81
81
  if jwe.nil?
82
82
  jwk = JOSE::JWK.from(jwk)
83
- jwe = jwk.kty.block_encryptor(jwk.fields, plain_text)
83
+ jwe = jwk.block_encryptor
84
84
  end
85
85
  if jwe.is_a?(Hash)
86
86
  jwe = JOSE::Map.new(jwe)
@@ -91,6 +91,24 @@ module JOSE
91
91
  return JOSE::JWK.block_encrypt(jwk, plain_text, jwe)
92
92
  end
93
93
 
94
+ def self.merge(left, right)
95
+ return from(left).merge(right)
96
+ end
97
+
98
+ def merge(object)
99
+ object = case object
100
+ when JOSE::Map, Hash
101
+ object
102
+ when String
103
+ JOSE.decode(object)
104
+ when JOSE::JWT
105
+ object.to_map
106
+ else
107
+ raise ArgumentError, "'object' must be a Hash, String, or JOSE::JWT"
108
+ end
109
+ return JOSE::JWT.from_map(self.to_map.merge(object))
110
+ end
111
+
94
112
  def self.peek_payload(signed)
95
113
  return JOSE::Map.new(JOSE.decode(JOSE::JWS.peek_payload(signed)))
96
114
  end
@@ -107,7 +125,7 @@ module JOSE
107
125
  plain_text = to_binary
108
126
  if jws.nil?
109
127
  jwk = JOSE::JWK.from(jwk)
110
- jws = jwk.kty.signer(jwk.fields, plain_text)
128
+ jws = jwk.signer
111
129
  end
112
130
  if jws.is_a?(Hash)
113
131
  jws = JOSE::Map.new(jws)
@@ -1,3 +1,3 @@
1
1
  module JOSE
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
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: 0.2.0
4
+ version: 0.3.0
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-02-25 00:00:00.000000000 Z
11
+ date: 2016-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hamster
@@ -30,28 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.11'
33
+ version: '1.12'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.11'
40
+ version: '1.12'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.5'
47
+ version: '11.1'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.5'
54
+ version: '11.1'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -168,6 +168,7 @@ files:
168
168
  - lib/jose/jws/alg_ecdsa.rb
169
169
  - lib/jose/jws/alg_eddsa.rb
170
170
  - lib/jose/jws/alg_hmac.rb
171
+ - lib/jose/jws/alg_none.rb
171
172
  - lib/jose/jws/alg_rsa_pkcs1_v1_5.rb
172
173
  - lib/jose/jws/alg_rsa_pss.rb
173
174
  - lib/jose/jwt.rb