jose 0.1.0 → 0.2.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.
- 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
|