jose 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/jose/jwk/kty.rb CHANGED
@@ -31,4 +31,10 @@ end
31
31
 
32
32
  require 'jose/jwk/kty_ec'
33
33
  require 'jose/jwk/kty_oct'
34
+ require 'jose/jwk/kty_okp_ed25519'
35
+ require 'jose/jwk/kty_okp_ed25519ph'
36
+ require 'jose/jwk/kty_okp_ed448'
37
+ require 'jose/jwk/kty_okp_ed448ph'
38
+ require 'jose/jwk/kty_okp_x25519'
39
+ require 'jose/jwk/kty_okp_x448'
34
40
  require 'jose/jwk/kty_rsa'
@@ -0,0 +1,112 @@
1
+ class JOSE::JWK::KTY_OKP_Ed25519 < Struct.new(:okp)
2
+
3
+ SECRET_BYTES = 32
4
+ PK_BYTES = 32
5
+ SK_BYTES = SECRET_BYTES + PK_BYTES
6
+
7
+ # JOSE::JWK callbacks
8
+
9
+ def self.from_map(fields)
10
+ if fields['kty'] == 'OKP' and fields['crv'] == 'Ed25519' and fields['x'].is_a?(String)
11
+ pk = JOSE.urlsafe_decode64(fields['x'])
12
+ secret = nil
13
+ if fields['d'].is_a?(String)
14
+ secret = JOSE.urlsafe_decode64(fields['d'])
15
+ end
16
+ if pk.bytesize == PK_BYTES and (secret.nil? or secret.bytesize == SECRET_BYTES)
17
+ if secret.nil?
18
+ return JOSE::JWK::KTY_OKP_Ed25519.new(pk), fields.except('kty', 'crv', 'x')
19
+ else
20
+ return JOSE::JWK::KTY_OKP_Ed25519.new(secret + pk), fields.except('kty', 'crv', 'x', 'd')
21
+ end
22
+ end
23
+ end
24
+ raise ArgumentError, "invalid 'OKP' crv 'Ed25519' JWK"
25
+ end
26
+
27
+ def to_key
28
+ return okp
29
+ end
30
+
31
+ def to_map(fields)
32
+ if okp.bytesize == SK_BYTES
33
+ secret, pk = okp[0, SECRET_BYTES], okp[SECRET_BYTES, SK_BYTES]
34
+ return fields.
35
+ put('crv', 'Ed25519').
36
+ put('d', JOSE.urlsafe_encode64(secret)).
37
+ put('kty', 'OKP').
38
+ put('x', JOSE.urlsafe_encode64(pk))
39
+ else
40
+ pk = okp
41
+ return fields.
42
+ put('crv', 'Ed25519').
43
+ put('kty', 'OKP').
44
+ put('x', JOSE.urlsafe_encode64(pk))
45
+ end
46
+ end
47
+
48
+ def to_public_map(fields)
49
+ return to_map(fields).except('d')
50
+ end
51
+
52
+ def to_thumbprint_map(fields)
53
+ return to_public_map(fields).slice('crv', 'kty', 'x')
54
+ end
55
+
56
+ # JOSE::JWK::KTY callbacks
57
+
58
+ def self.generate_key(okp_params)
59
+ secret = nil
60
+ if okp_params.is_a?(Array) and (okp_params.length == 2 or okp_params.length == 3) and okp_params[0] == :okp and okp_params[1] == :Ed25519
61
+ secret = okp_params[2] if okp_params.length == 3
62
+ elsif okp_params.is_a?(String)
63
+ secret = okp_params
64
+ end
65
+ if secret.nil? or (secret.is_a?(String) and secret.bytesize == SECRET_BYTES)
66
+ return from_okp([:Ed25519, JOSE::JWA::Curve25519.ed25519_keypair(secret)[1]])
67
+ else
68
+ raise ArgumentError, "'secret' must be nil or a String of #{SECRET_BYTES} bytes"
69
+ end
70
+ end
71
+
72
+ def generate_key(fields)
73
+ kty, other_fields = JOSE::JWK::KTY_OKP_Ed25519.generate_key([:okp, :Ed25519])
74
+ return kty, fields.delete('kid').merge(other_fields)
75
+ end
76
+
77
+ def key_encryptor(fields, key)
78
+ return JOSE::JWK::KTY.key_encryptor(self, fields, key)
79
+ end
80
+
81
+ def sign(message, digest_type)
82
+ raise ArgumentError, "'digest_type' must be :Ed25519" if digest_type != :Ed25519
83
+ raise NotImplementedError, "Ed25519 public key cannot be used for signing" if okp.bytesize != SK_BYTES
84
+ return JOSE::JWA::Curve25519.ed25519_sign(message, okp)
85
+ end
86
+
87
+ def signer(fields = nil, plain_text = nil)
88
+ return JOSE::Map['alg' => 'Ed25519']
89
+ end
90
+
91
+ def verify(message, digest_type, signature)
92
+ raise ArgumentError, "'digest_type' must be :Ed25519" if digest_type != :Ed25519
93
+ pk = okp
94
+ pk = JOSE::JWA::Curve25519.ed25519_secret_to_public(okp) if okp.bytesize == SK_BYTES
95
+ return JOSE::JWA::Curve25519.ed25519_verify(signature, message, pk)
96
+ end
97
+
98
+ # API functions
99
+
100
+ def self.from_okp(okp)
101
+ if okp.is_a?(Array) and okp.length == 2 and okp[0] == :Ed25519 and okp[1].is_a?(String) and (okp[1].bytesize == PK_BYTES or okp[1].bytesize == SK_BYTES)
102
+ return JOSE::JWK::KTY_OKP_Ed25519.new(okp[1]), JOSE::Map[]
103
+ else
104
+ raise ArgumentError, "'okp' must be an Array in the form of [:Ed25519, String]"
105
+ end
106
+ end
107
+
108
+ def to_okp
109
+ return [:Ed25519, okp]
110
+ end
111
+
112
+ end
@@ -0,0 +1,112 @@
1
+ class JOSE::JWK::KTY_OKP_Ed25519ph < Struct.new(:okp)
2
+
3
+ SECRET_BYTES = 32
4
+ PK_BYTES = 32
5
+ SK_BYTES = SECRET_BYTES + PK_BYTES
6
+
7
+ # JOSE::JWK callbacks
8
+
9
+ def self.from_map(fields)
10
+ if fields['kty'] == 'OKP' and fields['crv'] == 'Ed25519ph' and fields['x'].is_a?(String)
11
+ pk = JOSE.urlsafe_decode64(fields['x'])
12
+ secret = nil
13
+ if fields['d'].is_a?(String)
14
+ secret = JOSE.urlsafe_decode64(fields['d'])
15
+ end
16
+ if pk.bytesize == PK_BYTES and (secret.nil? or secret.bytesize == SECRET_BYTES)
17
+ if secret.nil?
18
+ return JOSE::JWK::KTY_OKP_Ed25519ph.new(pk), fields.except('kty', 'crv', 'x')
19
+ else
20
+ return JOSE::JWK::KTY_OKP_Ed25519ph.new(secret + pk), fields.except('kty', 'crv', 'x', 'd')
21
+ end
22
+ end
23
+ end
24
+ raise ArgumentError, "invalid 'OKP' crv 'Ed25519ph' JWK"
25
+ end
26
+
27
+ def to_key
28
+ return okp
29
+ end
30
+
31
+ def to_map(fields)
32
+ if okp.bytesize == SK_BYTES
33
+ secret, pk = okp[0, SECRET_BYTES], okp[SECRET_BYTES, SK_BYTES]
34
+ return fields.
35
+ put('crv', 'Ed25519ph').
36
+ put('d', JOSE.urlsafe_encode64(secret)).
37
+ put('kty', 'OKP').
38
+ put('x', JOSE.urlsafe_encode64(pk))
39
+ else
40
+ pk = okp
41
+ return fields.
42
+ put('crv', 'Ed25519ph').
43
+ put('kty', 'OKP').
44
+ put('x', JOSE.urlsafe_encode64(pk))
45
+ end
46
+ end
47
+
48
+ def to_public_map(fields)
49
+ return to_map(fields).except('d')
50
+ end
51
+
52
+ def to_thumbprint_map(fields)
53
+ return to_public_map(fields).slice('crv', 'kty', 'x')
54
+ end
55
+
56
+ # JOSE::JWK::KTY callbacks
57
+
58
+ def self.generate_key(okp_params)
59
+ secret = nil
60
+ if okp_params.is_a?(Array) and (okp_params.length == 2 or okp_params.length == 3) and okp_params[0] == :okp and okp_params[1] == :Ed25519ph
61
+ secret = okp_params[2] if okp_params.length == 3
62
+ elsif okp_params.is_a?(String)
63
+ secret = okp_params
64
+ end
65
+ if secret.nil? or (secret.is_a?(String) and secret.bytesize == SECRET_BYTES)
66
+ return from_okp([:Ed25519ph, JOSE::JWA::Curve25519.ed25519ph_keypair(secret)[1]])
67
+ else
68
+ raise ArgumentError, "'secret' must be nil or a String of #{SECRET_BYTES} bytes"
69
+ end
70
+ end
71
+
72
+ def generate_key(fields)
73
+ kty, other_fields = JOSE::JWK::KTY_OKP_Ed25519ph.generate_key([:okp, :Ed25519ph])
74
+ return kty, fields.delete('kid').merge(other_fields)
75
+ end
76
+
77
+ def key_encryptor(fields, key)
78
+ return JOSE::JWK::KTY.key_encryptor(self, fields, key)
79
+ end
80
+
81
+ def sign(message, sign_type)
82
+ raise ArgumentError, "'sign_type' must be :Ed25519ph" if sign_type != :Ed25519ph
83
+ raise NotImplementedError, "Ed25519ph public key cannot be used for signing" if okp.bytesize != SK_BYTES
84
+ return JOSE::JWA::Curve25519.ed25519ph_sign(message, okp)
85
+ end
86
+
87
+ def signer(fields = nil, plain_text = nil)
88
+ return JOSE::Map['alg' => 'Ed25519ph']
89
+ end
90
+
91
+ def verify(message, sign_type, signature)
92
+ raise ArgumentError, "'sign_type' must be :Ed25519ph" if sign_type != :Ed25519ph
93
+ pk = okp
94
+ pk = JOSE::JWA::Curve25519.ed25519ph_secret_to_public(okp) if okp.bytesize == SK_BYTES
95
+ return JOSE::JWA::Curve25519.ed25519ph_verify(signature, message, pk)
96
+ end
97
+
98
+ # API functions
99
+
100
+ def self.from_okp(okp)
101
+ if okp.is_a?(Array) and okp.length == 2 and okp[0] == :Ed25519ph and okp[1].is_a?(String) and (okp[1].bytesize == PK_BYTES or okp[1].bytesize == SK_BYTES)
102
+ return JOSE::JWK::KTY_OKP_Ed25519ph.new(okp[1]), JOSE::Map[]
103
+ else
104
+ raise ArgumentError, "'okp' must be an Array in the form of [:Ed25519ph, String]"
105
+ end
106
+ end
107
+
108
+ def to_okp
109
+ return [:Ed25519, okp]
110
+ end
111
+
112
+ end
@@ -0,0 +1,121 @@
1
+ class JOSE::JWK::KTY_OKP_Ed448 < Struct.new(:okp)
2
+
3
+ SECRET_BYTES = 57
4
+ LEGACY_SECRET_BYTES = 32
5
+ PK_BYTES = 57
6
+ SK_BYTES = SECRET_BYTES + PK_BYTES
7
+ LEGACY_SK_BYTES = LEGACY_SECRET_BYTES + PK_BYTES
8
+
9
+ # JOSE::JWK callbacks
10
+
11
+ def self.from_map(fields)
12
+ if fields['kty'] == 'OKP' and fields['crv'] == 'Ed448' and fields['x'].is_a?(String)
13
+ pk = JOSE.urlsafe_decode64(fields['x'])
14
+ secret = nil
15
+ if fields['d'].is_a?(String)
16
+ secret = JOSE.urlsafe_decode64(fields['d'])
17
+ end
18
+ if pk.bytesize == PK_BYTES and (secret.nil? or secret.bytesize == SECRET_BYTES or secret.bytesize == LEGACY_SECRET_BYTES)
19
+ if secret.nil?
20
+ return JOSE::JWK::KTY_OKP_Ed448.new(pk), fields.except('kty', 'crv', 'x')
21
+ else
22
+ return JOSE::JWK::KTY_OKP_Ed448.new(secret + pk), fields.except('kty', 'crv', 'x', 'd')
23
+ end
24
+ end
25
+ end
26
+ raise ArgumentError, "invalid 'OKP' crv 'Ed448' JWK"
27
+ end
28
+
29
+ def to_key
30
+ return okp
31
+ end
32
+
33
+ def to_map(fields)
34
+ if okp.bytesize == SK_BYTES
35
+ secret, pk = okp[0, SECRET_BYTES], okp[SECRET_BYTES, SK_BYTES]
36
+ return fields.
37
+ put('crv', 'Ed448').
38
+ put('d', JOSE.urlsafe_encode64(secret)).
39
+ put('kty', 'OKP').
40
+ put('x', JOSE.urlsafe_encode64(pk))
41
+ elsif okp.bytesize == LEGACY_SK_BYTES
42
+ secret, pk = okp[0, LEGACY_SECRET_BYTES], okp[LEGACY_SECRET_BYTES, LEGACY_SK_BYTES]
43
+ return fields.
44
+ put('crv', 'Ed448').
45
+ put('d', JOSE.urlsafe_encode64(secret)).
46
+ put('kty', 'OKP').
47
+ put('x', JOSE.urlsafe_encode64(pk))
48
+ else
49
+ pk = okp
50
+ return fields.
51
+ put('crv', 'Ed448').
52
+ put('kty', 'OKP').
53
+ put('x', JOSE.urlsafe_encode64(pk))
54
+ end
55
+ end
56
+
57
+ def to_public_map(fields)
58
+ return to_map(fields).except('d')
59
+ end
60
+
61
+ def to_thumbprint_map(fields)
62
+ return to_public_map(fields).slice('crv', 'kty', 'x')
63
+ end
64
+
65
+ # JOSE::JWK::KTY callbacks
66
+
67
+ def self.generate_key(okp_params)
68
+ secret = nil
69
+ if okp_params.is_a?(Array) and (okp_params.length == 2 or okp_params.length == 3) and okp_params[0] == :okp and okp_params[1] == :Ed448
70
+ secret = okp_params[2] if okp_params.length == 3
71
+ elsif okp_params.is_a?(String)
72
+ secret = okp_params
73
+ end
74
+ if secret.nil? or (secret.is_a?(String) and (secret.bytesize == SECRET_BYTES or secret.bytesize == LEGACY_SECRET_BYTES))
75
+ return from_okp([:Ed448, JOSE::JWA::Curve448.ed448_keypair(secret)[1]])
76
+ else
77
+ raise ArgumentError, "'secret' must be nil or a String of #{SECRET_BYTES} bytes"
78
+ end
79
+ end
80
+
81
+ def generate_key(fields)
82
+ kty, other_fields = JOSE::JWK::KTY_OKP_Ed448.generate_key([:okp, :Ed448])
83
+ return kty, fields.delete('kid').merge(other_fields)
84
+ end
85
+
86
+ def key_encryptor(fields, key)
87
+ return JOSE::JWK::KTY.key_encryptor(self, fields, key)
88
+ end
89
+
90
+ def sign(message, digest_type)
91
+ raise ArgumentError, "'digest_type' must be :Ed448" if digest_type != :Ed448
92
+ raise NotImplementedError, "Ed448 public key cannot be used for signing" if okp.bytesize != SK_BYTES and okp.bytesize != LEGACY_SK_BYTES
93
+ return JOSE::JWA::Curve448.ed448_sign(message, okp)
94
+ end
95
+
96
+ def signer(fields = nil, plain_text = nil)
97
+ return JOSE::Map['alg' => 'Ed448']
98
+ end
99
+
100
+ def verify(message, digest_type, signature)
101
+ raise ArgumentError, "'digest_type' must be :Ed448" if digest_type != :Ed448
102
+ pk = okp
103
+ pk = JOSE::JWA::Curve448.ed448_secret_to_public(okp) if okp.bytesize == SK_BYTES or okp.bytesize == LEGACY_SK_BYTES
104
+ return JOSE::JWA::Curve448.ed448_verify(signature, message, pk)
105
+ end
106
+
107
+ # API functions
108
+
109
+ def self.from_okp(okp)
110
+ if okp.is_a?(Array) and okp.length == 2 and okp[0] == :Ed448 and okp[1].is_a?(String) and (okp[1].bytesize == PK_BYTES or okp[1].bytesize == SK_BYTES or okp[1].bytesize == LEGACY_SK_BYTES)
111
+ return JOSE::JWK::KTY_OKP_Ed448.new(okp[1]), JOSE::Map[]
112
+ else
113
+ raise ArgumentError, "'okp' must be an Array in the form of [:Ed448, String]"
114
+ end
115
+ end
116
+
117
+ def to_okp
118
+ return [:Ed448, okp]
119
+ end
120
+
121
+ end
@@ -0,0 +1,121 @@
1
+ class JOSE::JWK::KTY_OKP_Ed448ph < Struct.new(:okp)
2
+
3
+ SECRET_BYTES = 57
4
+ LEGACY_SECRET_BYTES = 32
5
+ PK_BYTES = 57
6
+ SK_BYTES = SECRET_BYTES + PK_BYTES
7
+ LEGACY_SK_BYTES = LEGACY_SECRET_BYTES + PK_BYTES
8
+
9
+ # JOSE::JWK callbacks
10
+
11
+ def self.from_map(fields)
12
+ if fields['kty'] == 'OKP' and fields['crv'] == 'Ed448ph' and fields['x'].is_a?(String)
13
+ pk = JOSE.urlsafe_decode64(fields['x'])
14
+ secret = nil
15
+ if fields['d'].is_a?(String)
16
+ secret = JOSE.urlsafe_decode64(fields['d'])
17
+ end
18
+ if pk.bytesize == PK_BYTES and (secret.nil? or secret.bytesize == SECRET_BYTES or secret.bytesize == LEGACY_SECRET_BYTES)
19
+ if secret.nil?
20
+ return JOSE::JWK::KTY_OKP_Ed448ph.new(pk), fields.except('kty', 'crv', 'x')
21
+ else
22
+ return JOSE::JWK::KTY_OKP_Ed448ph.new(secret + pk), fields.except('kty', 'crv', 'x', 'd')
23
+ end
24
+ end
25
+ end
26
+ raise ArgumentError, "invalid 'OKP' crv 'Ed448ph' JWK"
27
+ end
28
+
29
+ def to_key
30
+ return okp
31
+ end
32
+
33
+ def to_map(fields)
34
+ if okp.bytesize == SK_BYTES
35
+ secret, pk = okp[0, SECRET_BYTES], okp[SECRET_BYTES, SK_BYTES]
36
+ return fields.
37
+ put('crv', 'Ed448ph').
38
+ put('d', JOSE.urlsafe_encode64(secret)).
39
+ put('kty', 'OKP').
40
+ put('x', JOSE.urlsafe_encode64(pk))
41
+ elsif okp.bytesize == LEGACY_SK_BYTES
42
+ secret, pk = okp[0, LEGACY_SECRET_BYTES], okp[LEGACY_SECRET_BYTES, LEGACY_SK_BYTES]
43
+ return fields.
44
+ put('crv', 'Ed448ph').
45
+ put('d', JOSE.urlsafe_encode64(secret)).
46
+ put('kty', 'OKP').
47
+ put('x', JOSE.urlsafe_encode64(pk))
48
+ else
49
+ pk = okp
50
+ return fields.
51
+ put('crv', 'Ed448ph').
52
+ put('kty', 'OKP').
53
+ put('x', JOSE.urlsafe_encode64(pk))
54
+ end
55
+ end
56
+
57
+ def to_public_map(fields)
58
+ return to_map(fields).except('d')
59
+ end
60
+
61
+ def to_thumbprint_map(fields)
62
+ return to_public_map(fields).slice('crv', 'kty', 'x')
63
+ end
64
+
65
+ # JOSE::JWK::KTY callbacks
66
+
67
+ def self.generate_key(okp_params)
68
+ secret = nil
69
+ if okp_params.is_a?(Array) and (okp_params.length == 2 or okp_params.length == 3) and okp_params[0] == :okp and okp_params[1] == :Ed448ph
70
+ secret = okp_params[2] if okp_params.length == 3
71
+ elsif okp_params.is_a?(String)
72
+ secret = okp_params
73
+ end
74
+ if secret.nil? or (secret.is_a?(String) and (secret.bytesize == SECRET_BYTES or secret.bytesize == LEGACY_SECRET_BYTES))
75
+ return from_okp([:Ed448ph, JOSE::JWA::Curve448.ed448ph_keypair(secret)[1]])
76
+ else
77
+ raise ArgumentError, "'secret' must be nil or a String of #{SECRET_BYTES} bytes"
78
+ end
79
+ end
80
+
81
+ def generate_key(fields)
82
+ kty, other_fields = JOSE::JWK::KTY_OKP_Ed448ph.generate_key([:okp, :Ed448ph])
83
+ return kty, fields.delete('kid').merge(other_fields)
84
+ end
85
+
86
+ def key_encryptor(fields, key)
87
+ return JOSE::JWK::KTY.key_encryptor(self, fields, key)
88
+ end
89
+
90
+ def sign(message, digest_type)
91
+ raise ArgumentError, "'digest_type' must be :Ed448ph" if digest_type != :Ed448ph
92
+ raise NotImplementedError, "Ed448ph public key cannot be used for signing" if okp.bytesize != SK_BYTES and okp.bytesize != LEGACY_SK_BYTES
93
+ return JOSE::JWA::Curve448.ed448ph_sign(message, okp)
94
+ end
95
+
96
+ def signer(fields = nil, plain_text = nil)
97
+ return JOSE::Map['alg' => 'Ed448ph']
98
+ end
99
+
100
+ def verify(message, digest_type, signature)
101
+ raise ArgumentError, "'digest_type' must be :Ed448ph" if digest_type != :Ed448ph
102
+ pk = okp
103
+ pk = JOSE::JWA::Curve448.ed448ph_secret_to_public(okp) if okp.bytesize == SK_BYTES or okp.bytesize == LEGACY_SK_BYTES
104
+ return JOSE::JWA::Curve448.ed448ph_verify(signature, message, pk)
105
+ end
106
+
107
+ # API functions
108
+
109
+ def self.from_okp(okp)
110
+ if okp.is_a?(Array) and okp.length == 2 and okp[0] == :Ed448ph and okp[1].is_a?(String) and (okp[1].bytesize == PK_BYTES or okp[1].bytesize == SK_BYTES or okp[1].bytesize == LEGACY_SK_BYTES)
111
+ return JOSE::JWK::KTY_OKP_Ed448ph.new(okp[1]), JOSE::Map[]
112
+ else
113
+ raise ArgumentError, "'okp' must be an Array in the form of [:Ed448ph, String]"
114
+ end
115
+ end
116
+
117
+ def to_okp
118
+ return [:Ed448ph, okp]
119
+ end
120
+
121
+ end