jwa 0.1.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 +7 -0
- data/.codeclimate.yml +15 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.rubocop.yml +16 -0
- data/.travis.yml +15 -0
- data/Gemfile +4 -0
- data/LICENSE.md +23 -0
- data/README.md +26 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/jwa.gemspec +27 -0
- data/lib/jwa.rb +16 -0
- data/lib/jwa/algorithms.rb +2 -0
- data/lib/jwa/algorithms/content_encryption.rb +29 -0
- data/lib/jwa/algorithms/content_encryption/a128_cbc_hs256.rb +29 -0
- data/lib/jwa/algorithms/content_encryption/a128_gcm.rb +25 -0
- data/lib/jwa/algorithms/content_encryption/a192_cbc_hs384.rb +29 -0
- data/lib/jwa/algorithms/content_encryption/a192_gcm.rb +25 -0
- data/lib/jwa/algorithms/content_encryption/a256_cbc_hs512.rb +29 -0
- data/lib/jwa/algorithms/content_encryption/a256_gcm.rb +25 -0
- data/lib/jwa/algorithms/content_encryption/aes_cbc_hs.rb +85 -0
- data/lib/jwa/algorithms/content_encryption/aes_gcm.rb +64 -0
- data/lib/jwa/algorithms/key_management.rb +56 -0
- data/lib/jwa/algorithms/key_management/a128_gcm_kw.rb +21 -0
- data/lib/jwa/algorithms/key_management/a128_kw.rb +21 -0
- data/lib/jwa/algorithms/key_management/a192_gcm_kw.rb +21 -0
- data/lib/jwa/algorithms/key_management/a192_kw.rb +21 -0
- data/lib/jwa/algorithms/key_management/a256_gcm_kw.rb +21 -0
- data/lib/jwa/algorithms/key_management/a256_kw.rb +21 -0
- data/lib/jwa/algorithms/key_management/aes_gcm_kw.rb +26 -0
- data/lib/jwa/algorithms/key_management/aes_kw.rb +100 -0
- data/lib/jwa/algorithms/key_management/ecdh_es.rb +45 -0
- data/lib/jwa/algorithms/key_management/ecdh_es_a128_kw.rb +25 -0
- data/lib/jwa/algorithms/key_management/ecdh_es_a192_kw.rb +25 -0
- data/lib/jwa/algorithms/key_management/ecdh_es_a256_kw.rb +25 -0
- data/lib/jwa/algorithms/key_management/ecdh_es_kw.rb +23 -0
- data/lib/jwa/algorithms/key_management/pbes2.rb +27 -0
- data/lib/jwa/algorithms/key_management/pbes_hs256_a128_kw.rb +25 -0
- data/lib/jwa/algorithms/key_management/pbes_hs384_a192_kw.rb +25 -0
- data/lib/jwa/algorithms/key_management/pbes_hs512_a256_kw.rb +25 -0
- data/lib/jwa/algorithms/key_management/rsa15.rb +20 -0
- data/lib/jwa/algorithms/key_management/rsa_oaep.rb +20 -0
- data/lib/jwa/cipher.rb +17 -0
- data/lib/jwa/support/concat_kdf.rb +29 -0
- data/lib/jwa/support/pbkdf2.rb +48 -0
- data/lib/jwa/version.rb +3 -0
- data/spec/jwa/algorithms/content_encryption/a128_cbc_hs256_spec.rb +30 -0
- data/spec/jwa/algorithms/content_encryption/a128_gcm_spec.rb +42 -0
- data/spec/jwa/algorithms/content_encryption/a192_cbc_hs384_spec.rb +34 -0
- data/spec/jwa/algorithms/content_encryption/a192_gcm_spec.rb +49 -0
- data/spec/jwa/algorithms/content_encryption/a256_cbc_hs512_spec.rb +35 -0
- data/spec/jwa/algorithms/content_encryption/a256_gcm_spec.rb +61 -0
- data/spec/jwa/algorithms/content_encryption/aes_cbc_hs_shared.rb +96 -0
- data/spec/jwa/algorithms/content_encryption/aes_gcm_shared.rb +60 -0
- data/spec/jwa/algorithms/content_encryption_spec.rb +7 -0
- data/spec/jwa/algorithms/key_management/a128_kw_spec.rb +43 -0
- data/spec/jwa/algorithms/key_management/a192_kw_spec.rb +29 -0
- data/spec/jwa/algorithms/key_management/a256_kw_spec.rb +29 -0
- data/spec/jwa/algorithms/key_management/ecdh_es_spec.rb +36 -0
- data/spec/jwa/algorithms/key_management/pbes2_hs256_a128_kw_spec.rb +27 -0
- data/spec/jwa/algorithms/key_management/pbes2_hs384_a192_kw_spec.rb +32 -0
- data/spec/jwa/algorithms/key_management/pbes2_hs512_a256_kw_spec.rb +32 -0
- data/spec/jwa/algorithms/key_management/rsa15_spec.rb +44 -0
- data/spec/jwa/algorithms/key_management/rsa_oaep_spec.rb +44 -0
- data/spec/jwa/algorithms/key_management_spec.rb +7 -0
- data/spec/jwa/cipher_spec.rb +7 -0
- data/spec/jwa/support/concat_kdf_spec.rb +32 -0
- data/spec/jwa/support/pbkdf2_spec.rb +111 -0
- data/spec/jwa_spec.rb +5 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/ec1.json +7 -0
- data/spec/support/ec2.json +7 -0
- data/spec/support/hex_helpers.rb +9 -0
- data/spec/support/oct16.json +4 -0
- data/spec/support/oct24.json +4 -0
- data/spec/support/oct32.json +4 -0
- data/spec/support/rsa1.json +11 -0
- data/spec/support/rsa2.json +11 -0
- metadata +193 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'jwa/cipher'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module ContentEncryption
|
|
6
|
+
# Abstract AES in Galois Counter mode for different key sizes.
|
|
7
|
+
module AesGcm
|
|
8
|
+
attr_reader :key, :iv
|
|
9
|
+
|
|
10
|
+
def initialize(key, iv = nil)
|
|
11
|
+
@key = key
|
|
12
|
+
@iv = iv || SecureRandom.random_bytes(12)
|
|
13
|
+
|
|
14
|
+
if @key.length != self.class.key_length
|
|
15
|
+
raise ArgumentError, "Invalid Key. Expected length: #{self.class.key_length}. Actual: #{@key.length}."
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if @iv.length != 12
|
|
19
|
+
raise ArgumentError, "Invalid IV. Expected length: 12. Actual: #{@iv.length}."
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def encrypt(plaintext, authenticated_data)
|
|
24
|
+
setup_cipher(:encrypt, authenticated_data)
|
|
25
|
+
ciphertext = cipher.update(plaintext) + cipher.final
|
|
26
|
+
|
|
27
|
+
[ciphertext, cipher.auth_tag]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def decrypt(ciphertext, authenticated_data, tag)
|
|
31
|
+
setup_cipher(:decrypt, authenticated_data, tag)
|
|
32
|
+
cipher.update(ciphertext) + cipher.final
|
|
33
|
+
rescue OpenSSL::Cipher::CipherError
|
|
34
|
+
raise JWA::BadDecrypt, 'Invalid ciphertext or authentication tag'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def setup_cipher(direction, auth_data, tag = nil)
|
|
38
|
+
cipher.send(direction)
|
|
39
|
+
cipher.key = @key
|
|
40
|
+
cipher.iv = @iv
|
|
41
|
+
cipher.auth_tag = tag if tag
|
|
42
|
+
cipher.auth_data = auth_data
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def cipher
|
|
46
|
+
@cipher ||= Cipher.for(self.class.cipher_name)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.included(base)
|
|
50
|
+
base.extend(ClassMethods)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
module ClassMethods
|
|
54
|
+
def available?
|
|
55
|
+
Cipher.for(cipher_name)
|
|
56
|
+
true
|
|
57
|
+
rescue NotImplementedError
|
|
58
|
+
false
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/rsa15'
|
|
2
|
+
require 'jwa/algorithms/key_management/rsa_oaep'
|
|
3
|
+
|
|
4
|
+
require 'jwa/algorithms/key_management/a128_kw'
|
|
5
|
+
require 'jwa/algorithms/key_management/a192_kw'
|
|
6
|
+
require 'jwa/algorithms/key_management/a256_kw'
|
|
7
|
+
|
|
8
|
+
require 'jwa/algorithms/key_management/ecdh_es'
|
|
9
|
+
require 'jwa/algorithms/key_management/ecdh_es_a128_kw'
|
|
10
|
+
require 'jwa/algorithms/key_management/ecdh_es_a192_kw'
|
|
11
|
+
require 'jwa/algorithms/key_management/ecdh_es_a256_kw'
|
|
12
|
+
|
|
13
|
+
require 'jwa/algorithms/key_management/a128_gcm_kw'
|
|
14
|
+
require 'jwa/algorithms/key_management/a192_gcm_kw'
|
|
15
|
+
require 'jwa/algorithms/key_management/a256_gcm_kw'
|
|
16
|
+
|
|
17
|
+
require 'jwa/algorithms/key_management/pbes_hs256_a128_kw'
|
|
18
|
+
require 'jwa/algorithms/key_management/pbes_hs384_a192_kw'
|
|
19
|
+
require 'jwa/algorithms/key_management/pbes_hs512_a256_kw'
|
|
20
|
+
|
|
21
|
+
module JWA
|
|
22
|
+
module Algorithms
|
|
23
|
+
module KeyManagement
|
|
24
|
+
KNOWN_ALGS = {
|
|
25
|
+
'RSA1_5' => Rsa15,
|
|
26
|
+
'RSA-OAEP' => RsaOaep,
|
|
27
|
+
'RSA-OAEP-256' => nil,
|
|
28
|
+
|
|
29
|
+
'A128KW' => A128Kw,
|
|
30
|
+
'A192KW' => A192Kw,
|
|
31
|
+
'A256KW' => A256Kw,
|
|
32
|
+
|
|
33
|
+
'dir' => nil,
|
|
34
|
+
|
|
35
|
+
'ECDH-ES' => EcdhEs,
|
|
36
|
+
'ECDH-ES+A128KW' => EcdhEs,
|
|
37
|
+
'ECDH-ES+A192KW' => EcdhEs,
|
|
38
|
+
'ECDH-ES+A256KW' => EcdhEs,
|
|
39
|
+
|
|
40
|
+
'A128GCMKW' => A128GcmKw,
|
|
41
|
+
'A192GCMKW' => A192GcmKw,
|
|
42
|
+
'A256GCMKW' => A256GcmKw,
|
|
43
|
+
|
|
44
|
+
'PBES2-HS256+A128KW' => Pbes2Hs256A128Kw,
|
|
45
|
+
'PBES2-HS384+A192KW' => Pbes2Hs384A192Kw,
|
|
46
|
+
'PBES2-HS512+A256KW' => Pbes2Hs512A256Kw
|
|
47
|
+
}.freeze
|
|
48
|
+
|
|
49
|
+
class << self
|
|
50
|
+
def for(name)
|
|
51
|
+
KNOWN_ALGS[name]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/aes_gcm_kw'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
class A128GcmKw
|
|
7
|
+
include AesGcmKw
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def key_length
|
|
11
|
+
16
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cipher
|
|
15
|
+
A128Gcm
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/aes_kw'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
class A128Kw
|
|
7
|
+
include AesKw
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def key_length
|
|
11
|
+
16
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cipher_name
|
|
15
|
+
'AES-128-ECB'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/aes_gcm_kw'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
class A192GcmKw
|
|
7
|
+
include AesGcmKw
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def key_length
|
|
11
|
+
24
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cipher
|
|
15
|
+
A192Gcm
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/aes_kw'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
class A192Kw
|
|
7
|
+
include AesKw
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def key_length
|
|
11
|
+
24
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cipher_name
|
|
15
|
+
'AES-192-ECB'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/aes_gcm_kw'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
class A256GcmKw
|
|
7
|
+
include AesGcmKw
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def key_length
|
|
11
|
+
32
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cipher
|
|
15
|
+
A256Gcm
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/aes_kw'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
class A256Kw
|
|
7
|
+
include AesKw
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def key_length
|
|
11
|
+
32
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cipher_name
|
|
15
|
+
'AES-256-ECB'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module JWA
|
|
2
|
+
module Algorithms
|
|
3
|
+
module KeyManagement
|
|
4
|
+
module AesGcmKw
|
|
5
|
+
def initialize(key, iv = nil)
|
|
6
|
+
@key = key
|
|
7
|
+
@iv = iv
|
|
8
|
+
|
|
9
|
+
if @key.length != self.class.key_length
|
|
10
|
+
raise ArgumentError, "Invalid Key. Expected length: #{self.class.key_length}. Actual: #{@key.length}."
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def encrypt(plaintext)
|
|
15
|
+
cipher = self.class.cipher.new(@key, @iv)
|
|
16
|
+
cipher.encrypt(plaintext, '')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def decrypt(ciphertext, tag)
|
|
20
|
+
cipher = self.class.cipher.new(@key, @iv)
|
|
21
|
+
cipher.decrypt(ciphertext, '', tag)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'jwa/cipher'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
# Generic AES Key Wrapping algorithm for any key size.
|
|
7
|
+
module AesKw
|
|
8
|
+
attr_reader :key, :iv
|
|
9
|
+
|
|
10
|
+
def initialize(key, iv = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6")
|
|
11
|
+
@key = key.force_encoding('ASCII-8BIT')
|
|
12
|
+
@iv = iv.force_encoding('ASCII-8BIT')
|
|
13
|
+
|
|
14
|
+
if @key.length != self.class.key_length
|
|
15
|
+
raise ArgumentError, "Invalid Key. Expected length: #{self.class.key_length}. Actual: #{@key.length}."
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def encrypt(plaintext)
|
|
20
|
+
a = @iv
|
|
21
|
+
r = plaintext.force_encoding('ASCII-8BIT').scan(/.{8}/m)
|
|
22
|
+
|
|
23
|
+
6.times do |j|
|
|
24
|
+
a, r = kw_encrypt_round(j, a, r)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
([a] + r).join
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def kw_encrypt_round(j, a, r)
|
|
31
|
+
r.length.times do |i|
|
|
32
|
+
b = encrypt_round(a + r[i]).chars
|
|
33
|
+
|
|
34
|
+
a, r[i] = a_ri(b)
|
|
35
|
+
|
|
36
|
+
a = xor(a, (r.length * j) + i + 1)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
[a, r]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def decrypt(ciphertext)
|
|
43
|
+
c = ciphertext.force_encoding('ASCII-8BIT').scan(/.{8}/m)
|
|
44
|
+
a, *r = c
|
|
45
|
+
|
|
46
|
+
5.downto(0) do |j|
|
|
47
|
+
a, r = kw_decrypt_round(j, a, r)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if a != @iv
|
|
51
|
+
raise StandardError, 'The encrypted key has been tampered. Do not use this key.'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
r.join
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def kw_decrypt_round(j, a, r)
|
|
58
|
+
r.length.downto(1) do |i|
|
|
59
|
+
a = xor(a, (r.length * j) + i)
|
|
60
|
+
|
|
61
|
+
b = decrypt_round(a + r[i - 1]).chars
|
|
62
|
+
|
|
63
|
+
a, r[i - 1] = a_ri(b)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
[a, r]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def a_ri(b)
|
|
70
|
+
[b.first(8).join, b.to_a.last(8).join]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def cipher
|
|
74
|
+
@cipher ||= Cipher.for(self.class.cipher_name)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def encrypt_round(data)
|
|
78
|
+
cipher.encrypt
|
|
79
|
+
cipher.key = @key
|
|
80
|
+
cipher.padding = 0
|
|
81
|
+
cipher.update(data) + cipher.final
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def decrypt_round(data)
|
|
85
|
+
cipher.decrypt
|
|
86
|
+
cipher.key = @key
|
|
87
|
+
cipher.padding = 0
|
|
88
|
+
cipher.update(data) + cipher.final
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def xor(data, t)
|
|
92
|
+
t = ([0] * (data.length - 1)) + [t]
|
|
93
|
+
data = data.chars.map(&:ord)
|
|
94
|
+
|
|
95
|
+
data.zip(t).map { |a, b| (a ^ b).chr }.join
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# This implementation is protected by the attack described at:
|
|
2
|
+
# http://blogs.adobe.com/security/2017/03/critical-vulnerability-uncovered-in-json-encryption.html
|
|
3
|
+
#
|
|
4
|
+
# The Ruby wrapper around OpenSSL raises an OpenSSL::PKey::EC::Point error if an attempt is made to
|
|
5
|
+
# initialize a public key with coordinates that do not reside on the wanted curve.
|
|
6
|
+
|
|
7
|
+
module JWA
|
|
8
|
+
module Algorithms
|
|
9
|
+
module KeyManagement
|
|
10
|
+
class EcdhEs
|
|
11
|
+
def initialize(ephemeral_key, enc_algorithm, apu, apv)
|
|
12
|
+
@ephemeral_key = ephemeral_key
|
|
13
|
+
@key_length = enc_algorithm.key_length * 8
|
|
14
|
+
|
|
15
|
+
algorithm_id = length_encode(enc_algorithm.enc_name)
|
|
16
|
+
apu = length_encode(apu)
|
|
17
|
+
apv = length_encode(apv)
|
|
18
|
+
supp_pub_info = [@key_length].pack('N')
|
|
19
|
+
supp_priv_info = ''
|
|
20
|
+
|
|
21
|
+
@info = algorithm_id + apu + apv + supp_pub_info + supp_priv_info
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# This is technically not an encryption, but to keep the same interface
|
|
25
|
+
# with other classes, let's name it this way.
|
|
26
|
+
def encrypt(public_key)
|
|
27
|
+
z = @ephemeral_key.dh_compute_key(public_key)
|
|
28
|
+
|
|
29
|
+
concat_kdf = Support::ConcatKDF.new(Digest::SHA256.new)
|
|
30
|
+
concat_kdf.run(z, @info, @key_length)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def decrypt(public_key)
|
|
34
|
+
encrypt(public_key)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def length_encode(s)
|
|
40
|
+
[s.length].pack('N') + s
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'jwa/algorithms/key_management/ecdh_es_kw'
|
|
2
|
+
|
|
3
|
+
module JWA
|
|
4
|
+
module Algorithms
|
|
5
|
+
module KeyManagement
|
|
6
|
+
class EcdhEsA128Kw
|
|
7
|
+
include EcdhEsKw
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
def alg_name
|
|
11
|
+
'ECDH-ES+A128KW'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def shared_key_length
|
|
15
|
+
16
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def kw_class
|
|
19
|
+
A128Kw
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|