jose 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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