jose 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +11 -2
- data/CHANGELOG.md +69 -0
- data/README.md +5 -3
- data/jose.gemspec +3 -2
- data/lib/jose.rb +44 -6
- data/lib/jose/jwa.rb +23 -0
- data/lib/jose/jwa/curve25519.rb +102 -0
- data/lib/jose/jwa/curve25519_rbnacl.rb +67 -0
- data/lib/jose/jwa/curve25519_ruby.rb +54 -0
- data/lib/jose/jwa/curve25519_unsupported.rb +52 -0
- data/lib/jose/jwa/curve448.rb +99 -0
- data/lib/jose/jwa/curve448_ruby.rb +54 -0
- data/lib/jose/jwa/curve448_unsupported.rb +52 -0
- data/lib/jose/jwa/ed25519.rb +117 -0
- data/lib/jose/jwa/ed25519_rbnacl.rb +36 -0
- data/lib/jose/jwa/ed448.rb +166 -0
- data/lib/jose/jwa/edwards_point.rb +257 -0
- data/lib/jose/jwa/field_element.rb +161 -0
- data/lib/jose/jwa/sha3.rb +150 -0
- data/lib/jose/jwa/x25519.rb +188 -0
- data/lib/jose/jwa/x25519_rbnacl.rb +35 -0
- data/lib/jose/jwa/x448.rb +188 -0
- data/lib/jose/jwk.rb +74 -0
- data/lib/jose/jwk/kty.rb +6 -0
- data/lib/jose/jwk/kty_okp_ed25519.rb +112 -0
- data/lib/jose/jwk/kty_okp_ed25519ph.rb +112 -0
- data/lib/jose/jwk/kty_okp_ed448.rb +121 -0
- data/lib/jose/jwk/kty_okp_ed448ph.rb +121 -0
- data/lib/jose/jwk/kty_okp_x25519.rb +120 -0
- data/lib/jose/jwk/kty_okp_x448.rb +120 -0
- data/lib/jose/jws.rb +4 -0
- data/lib/jose/jws/alg.rb +1 -0
- data/lib/jose/jws/alg_eddsa.rb +35 -0
- data/lib/jose/version.rb +1 -1
- metadata +45 -7
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
|