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,35 @@
|
|
|
1
|
+
require_relative './aes_cbc_hs_shared'
|
|
2
|
+
|
|
3
|
+
describe JWA::Algorithms::ContentEncryption::A256CbcHs512 do
|
|
4
|
+
include_examples 'AES-CBC-HS' do
|
|
5
|
+
let(:key) do
|
|
6
|
+
'00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
|
|
7
|
+
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
|
|
8
|
+
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
|
|
9
|
+
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:ciphertext) do
|
|
13
|
+
'4a ff aa ad b7 8c 31 c5 da 4b 1b 59 0d 10 ff bd
|
|
14
|
+
3d d8 d5 d3 02 42 35 26 91 2d a0 37 ec bc c7 bd
|
|
15
|
+
82 2c 30 1d d6 7c 37 3b cc b5 84 ad 3e 92 79 c2
|
|
16
|
+
e6 d1 2a 13 74 b7 7f 07 75 53 df 82 94 10 44 6b
|
|
17
|
+
36 eb d9 70 66 29 6a e6 42 7e a7 5c 2e 08 46 a1
|
|
18
|
+
1a 09 cc f5 37 0d c8 0b fe cb ad 28 c7 3f 09 b3
|
|
19
|
+
a3 b7 5e 66 2a 25 94 41 0a e4 96 b2 e2 e6 60 9e
|
|
20
|
+
31 e6 e0 2c c8 37 f0 53 d2 1f 37 ff 4f 51 95 0b
|
|
21
|
+
be 26 38 d0 9d d7 a4 93 09 30 80 6d 07 03 b1 f6'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:tag) do
|
|
25
|
+
'4d d3 b4 c0 88 a7 f4 5c 21 68 39 64 5b 20 12 bf
|
|
26
|
+
2e 62 69 a8 c5 6a 81 6d bc 1b 26 77 61 95 5b c5'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe '.enc_name' do
|
|
31
|
+
it 'equals A256CBC-HS512' do
|
|
32
|
+
expect(described_class.enc_name).to eq 'A256CBC-HS512'
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require_relative './aes_gcm_shared'
|
|
2
|
+
|
|
3
|
+
# Test vector from JWE spec
|
|
4
|
+
describe JWA::Algorithms::ContentEncryption::A256Gcm do
|
|
5
|
+
include_examples 'AES-GCM' do
|
|
6
|
+
let(:plaintext) do
|
|
7
|
+
int_byte_array_to_bytes(
|
|
8
|
+
[84, 104, 101, 32, 116, 114, 117, 101, 32, 115, 105, 103, 110, 32,
|
|
9
|
+
111, 102, 32, 105, 110, 116, 101, 108, 108, 105, 103, 101, 110, 99,
|
|
10
|
+
101, 32, 105, 115, 32, 110, 111, 116, 32, 107, 110, 111, 119, 108,
|
|
11
|
+
101, 100, 103, 101, 32, 98, 117, 116, 32, 105, 109, 97, 103, 105,
|
|
12
|
+
110, 97, 116, 105, 111, 110, 46]
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
let(:authenticated_data) do
|
|
17
|
+
int_byte_array_to_bytes(
|
|
18
|
+
[101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 48, 69,
|
|
19
|
+
116, 84, 48, 70, 70, 85, 67, 73, 115, 73, 109, 86, 117, 89, 121, 73,
|
|
20
|
+
54, 73, 107, 69, 121, 78, 84, 90, 72, 81, 48, 48, 105, 102, 81]
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:key) do
|
|
25
|
+
int_byte_array_to_bytes(
|
|
26
|
+
[177, 161, 244, 128, 84, 143, 225, 115, 63, 180, 3, 255, 107, 154,
|
|
27
|
+
212, 246, 138, 7, 110, 91, 112, 46, 34, 105, 47, 130, 203, 46, 122,
|
|
28
|
+
234, 64, 252]
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
let(:iv) do
|
|
33
|
+
int_byte_array_to_bytes(
|
|
34
|
+
[227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219]
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
let(:ciphertext) do
|
|
39
|
+
int_byte_array_to_bytes(
|
|
40
|
+
[229, 236, 166, 241, 53, 191, 115, 196, 174, 43, 73, 109, 39, 122,
|
|
41
|
+
233, 96, 140, 206, 120, 52, 51, 237, 48, 11, 190, 219, 186, 80, 111,
|
|
42
|
+
104, 50, 142, 47, 167, 59, 61, 181, 127, 196, 21, 40, 82, 242, 32,
|
|
43
|
+
123, 143, 168, 226, 73, 216, 176, 144, 138, 247, 106, 60, 16, 205,
|
|
44
|
+
160, 109, 64, 63, 192]
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
let(:tag) do
|
|
49
|
+
int_byte_array_to_bytes(
|
|
50
|
+
[92, 80, 104, 49, 133, 25, 161, 215, 173, 101, 219, 211, 136, 91,
|
|
51
|
+
210, 145]
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe '.enc_name' do
|
|
57
|
+
it 'equals A256GCM' do
|
|
58
|
+
expect(described_class.enc_name).to eq 'A256GCM'
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
shared_examples 'AES-CBC-HS' do
|
|
2
|
+
let(:plaintext) do
|
|
3
|
+
'41 20 63 69 70 68 65 72 20 73 79 73 74 65 6d 20
|
|
4
|
+
6d 75 73 74 20 6e 6f 74 20 62 65 20 72 65 71 75
|
|
5
|
+
69 72 65 64 20 74 6f 20 62 65 20 73 65 63 72 65
|
|
6
|
+
74 2c 20 61 6e 64 20 69 74 20 6d 75 73 74 20 62
|
|
7
|
+
65 20 61 62 6c 65 20 74 6f 20 66 61 6c 6c 20 69
|
|
8
|
+
6e 74 6f 20 74 68 65 20 68 61 6e 64 73 20 6f 66
|
|
9
|
+
20 74 68 65 20 65 6e 65 6d 79 20 77 69 74 68 6f
|
|
10
|
+
75 74 20 69 6e 63 6f 6e 76 65 6e 69 65 6e 63 65'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
let(:authenticated_data) do
|
|
14
|
+
'54 68 65 20 73 65 63 6f 6e 64 20 70 72 69 6e 63
|
|
15
|
+
69 70 6c 65 20 6f 66 20 41 75 67 75 73 74 65 20
|
|
16
|
+
4b 65 72 63 6b 68 6f 66 66 73'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:iv) { '1a f3 8c 2d c2 b9 6f fd d8 66 94 09 23 41 bc 04' }
|
|
20
|
+
|
|
21
|
+
let(:b_plaintext) { hex_string_to_bytes(plaintext) }
|
|
22
|
+
let(:b_authenticated_data) { hex_string_to_bytes(authenticated_data) }
|
|
23
|
+
let(:b_key) { hex_string_to_bytes(key) }
|
|
24
|
+
let(:b_iv) { hex_string_to_bytes(iv) }
|
|
25
|
+
let(:b_ciphertext) { hex_string_to_bytes(ciphertext) }
|
|
26
|
+
let(:b_tag) { hex_string_to_bytes(tag) }
|
|
27
|
+
|
|
28
|
+
subject { described_class.new(b_key, b_iv) }
|
|
29
|
+
|
|
30
|
+
it 'encrypts according to RFC7518' do
|
|
31
|
+
ciphertext, tag = subject.encrypt(b_plaintext, b_authenticated_data)
|
|
32
|
+
|
|
33
|
+
expect(ciphertext).to eq(b_ciphertext)
|
|
34
|
+
expect(tag).to eq(b_tag)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'decrypt according to RFC7518' do
|
|
38
|
+
plaintext = subject.decrypt(b_ciphertext, b_authenticated_data, b_tag)
|
|
39
|
+
|
|
40
|
+
expect(plaintext).to eq(b_plaintext)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'raises when provided a wrong key size' do
|
|
44
|
+
expect do
|
|
45
|
+
described_class.new(b_key + "\x00", b_iv)
|
|
46
|
+
end.to raise_error(ArgumentError)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'raises when provided a wrong iv size' do
|
|
50
|
+
expect do
|
|
51
|
+
described_class.new(b_key, b_iv + "\x00")
|
|
52
|
+
end.to raise_error(ArgumentError)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'exposes the used key' do
|
|
56
|
+
expect(subject.key).to eq b_key
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'exposes the used iv' do
|
|
60
|
+
ins = described_class.new(b_key)
|
|
61
|
+
expect(ins.iv).to_not be_nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe '#available?' do
|
|
65
|
+
context 'when the cipher is not available' do
|
|
66
|
+
it 'is false' do
|
|
67
|
+
allow(JWA::Cipher).to receive(:for) { raise NotImplementedError }
|
|
68
|
+
expect(described_class.available?).to be_falsey
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'when the cipher is available' do
|
|
73
|
+
it 'is true' do
|
|
74
|
+
allow(JWA::Cipher).to receive(:for)
|
|
75
|
+
expect(described_class.available?).to be_truthy
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'raises an error if the tag is corrupt' do
|
|
81
|
+
expect do
|
|
82
|
+
subject.decrypt(b_ciphertext, b_authenticated_data, 'random data')
|
|
83
|
+
end.to raise_error(JWA::BadDecrypt)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'raises an error if the signature pass, but decryption fails' do
|
|
87
|
+
# The second half of the key influcences only decryption, but not signature checking
|
|
88
|
+
key = b_key.dup
|
|
89
|
+
key[-1] = "\x00"
|
|
90
|
+
|
|
91
|
+
ins = described_class.new(key, b_iv)
|
|
92
|
+
expect do
|
|
93
|
+
ins.decrypt(b_ciphertext, b_authenticated_data, b_tag)
|
|
94
|
+
end.to raise_error(JWA::BadDecrypt)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
shared_examples 'AES-GCM' do
|
|
2
|
+
subject { described_class.new(key, iv) }
|
|
3
|
+
|
|
4
|
+
it 'encrypts according to the Test Case' do
|
|
5
|
+
r_ciphertext, r_tag = subject.encrypt(plaintext, authenticated_data)
|
|
6
|
+
|
|
7
|
+
expect(r_ciphertext).to eq(ciphertext)
|
|
8
|
+
expect(r_tag).to eq(tag)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'decrypt according to the Test Case' do
|
|
12
|
+
r_plaintext = subject.decrypt(ciphertext, authenticated_data, tag)
|
|
13
|
+
|
|
14
|
+
expect(r_plaintext).to eq(plaintext)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'raises when provided a wrong key size' do
|
|
18
|
+
expect do
|
|
19
|
+
described_class.new(key + "\x00", iv)
|
|
20
|
+
end.to raise_error(ArgumentError)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'raises when provided a wrong iv size' do
|
|
24
|
+
expect do
|
|
25
|
+
described_class.new(key, iv + "\x00")
|
|
26
|
+
end.to raise_error(ArgumentError)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'exposes the used key' do
|
|
30
|
+
expect(subject.key).to eq key
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'exposes the used iv' do
|
|
34
|
+
ins = described_class.new(key)
|
|
35
|
+
expect(ins.iv).to_not be_nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe '#available?' do
|
|
39
|
+
context 'when the cipher is not available' do
|
|
40
|
+
it 'is false' do
|
|
41
|
+
allow(JWA::Cipher).to receive(:for) { raise NotImplementedError }
|
|
42
|
+
expect(described_class.available?).to be_falsey
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'when the cipher is available' do
|
|
47
|
+
it 'is true' do
|
|
48
|
+
allow(JWA::Cipher).to receive(:for)
|
|
49
|
+
expect(described_class.available?).to be_truthy
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'raises an error if decryption fails' do
|
|
55
|
+
ins = described_class.new("\x00" * described_class.key_length, iv)
|
|
56
|
+
expect do
|
|
57
|
+
ins.decrypt(ciphertext, authenticated_data, tag)
|
|
58
|
+
end.to raise_error(JWA::BadDecrypt)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
describe JWA::Algorithms::KeyManagement::A128Kw do
|
|
2
|
+
let(:jwk) { JWK::Key.from_json(File.read('spec/support/oct16.json')) }
|
|
3
|
+
|
|
4
|
+
let(:plaintext) do
|
|
5
|
+
int_byte_array_to_bytes([4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106,
|
|
6
|
+
206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156,
|
|
7
|
+
44, 207])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:ciphertext) do
|
|
11
|
+
int_byte_array_to_bytes([232, 160, 123, 211, 183, 76, 245, 132, 200, 128, 123, 75, 190, 216,
|
|
12
|
+
22, 67, 201, 138, 193, 186, 9, 91, 122, 31, 246, 90, 28, 139, 57, 3,
|
|
13
|
+
76, 124, 193, 11, 98, 37, 173, 61, 104, 57])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'decrypts according to the Test Case (RFC 7516 - Section A.3)' do
|
|
17
|
+
key = jwk.to_s
|
|
18
|
+
|
|
19
|
+
alg = described_class.new(key)
|
|
20
|
+
expect(alg.decrypt(ciphertext)).to eq plaintext
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'encrypts according to the Test Case' do
|
|
24
|
+
key = jwk.to_s
|
|
25
|
+
|
|
26
|
+
alg = described_class.new(key)
|
|
27
|
+
expect(alg.encrypt(plaintext)).to eq ciphertext
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'raises when the iv doesn\'t match' do
|
|
31
|
+
key = jwk.to_s
|
|
32
|
+
|
|
33
|
+
alg = described_class.new(key)
|
|
34
|
+
ciph = alg.encrypt(plaintext)
|
|
35
|
+
|
|
36
|
+
alg2 = described_class.new(key, "\xA5\xA5\xA5\xA5\xA5\xA5\xA5\xA5")
|
|
37
|
+
expect { alg2.decrypt(ciph) }.to raise_error(StandardError)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'raises for wrong key sizes' do
|
|
41
|
+
expect { described_class.new("\x00" * 12) }.to raise_error(ArgumentError)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
describe JWA::Algorithms::KeyManagement::A192Kw do
|
|
2
|
+
let(:jwk) { JWK::Key.from_json(File.read('spec/support/oct24.json')) }
|
|
3
|
+
|
|
4
|
+
let(:plaintext) do
|
|
5
|
+
int_byte_array_to_bytes([4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106,
|
|
6
|
+
206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156,
|
|
7
|
+
44, 207])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:ciphertext) do
|
|
11
|
+
int_byte_array_to_bytes([143, 218, 154, 233, 170, 149, 194, 128, 166, 3, 246, 159, 78, 90, 167,
|
|
12
|
+
0, 22, 179, 29, 231, 11, 77, 104, 42, 102, 115, 158, 61, 247, 117,
|
|
13
|
+
234, 19, 241, 102, 103, 177, 218, 215, 160, 151])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'decrypts according to the Test Case (RFC 7516 - Section A.3)' do
|
|
17
|
+
key = jwk.to_s
|
|
18
|
+
|
|
19
|
+
alg = described_class.new(key)
|
|
20
|
+
expect(alg.decrypt(ciphertext)).to eq plaintext
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'encrypts according to the Test Case' do
|
|
24
|
+
key = jwk.to_s
|
|
25
|
+
|
|
26
|
+
alg = described_class.new(key)
|
|
27
|
+
expect(alg.encrypt(plaintext)).to eq ciphertext
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
describe JWA::Algorithms::KeyManagement::A256Kw do
|
|
2
|
+
let(:jwk) { JWK::Key.from_json(File.read('spec/support/oct32.json')) }
|
|
3
|
+
|
|
4
|
+
let(:plaintext) do
|
|
5
|
+
int_byte_array_to_bytes([4, 211, 31, 197, 84, 157, 252, 254, 11, 100, 157, 250, 63, 170, 106,
|
|
6
|
+
206, 107, 124, 212, 45, 111, 107, 9, 219, 200, 177, 0, 240, 143, 156,
|
|
7
|
+
44, 207])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
let(:ciphertext) do
|
|
11
|
+
int_byte_array_to_bytes([198, 158, 179, 0, 33, 254, 44, 72, 227, 132, 72, 122, 1, 139, 110, 8,
|
|
12
|
+
55, 39, 196, 203, 65, 90, 255, 20, 27, 211, 159, 146, 66, 122, 239, 238,
|
|
13
|
+
145, 174, 248, 60, 215, 107, 251, 14])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'decrypts according to the Test Case (RFC 7516 - Section A.3)' do
|
|
17
|
+
key = jwk.to_s
|
|
18
|
+
|
|
19
|
+
alg = described_class.new(key)
|
|
20
|
+
expect(alg.decrypt(ciphertext)).to eq plaintext
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'encrypts according to the Test Case' do
|
|
24
|
+
key = jwk.to_s
|
|
25
|
+
|
|
26
|
+
alg = described_class.new(key)
|
|
27
|
+
expect(alg.encrypt(plaintext)).to eq ciphertext
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
describe JWA::Algorithms::KeyManagement::EcdhEs do
|
|
2
|
+
let(:alice) { JWK::Key.from_json(File.read('spec/support/ec1.json')) }
|
|
3
|
+
let(:bob) { JWK::Key.from_json(File.read('spec/support/ec2.json')) }
|
|
4
|
+
|
|
5
|
+
let(:expected) do
|
|
6
|
+
int_byte_array_to_bytes([86, 170, 141, 234, 248, 35, 109, 32, 92, 34, 40, 205, 113, 167, 16, 26])
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'resolves alice\'s key according to the spec' do
|
|
10
|
+
alg = described_class.new(alice.to_openssl_key, JWA::Algorithms::ContentEncryption::A128Gcm, 'Alice', 'Bob')
|
|
11
|
+
|
|
12
|
+
begin
|
|
13
|
+
actual = alg.encrypt(bob.to_openssl_key.public_key)
|
|
14
|
+
expect(actual).to eq expected
|
|
15
|
+
rescue Exception => e
|
|
16
|
+
raise e unless defined?(JRUBY_VERSION)
|
|
17
|
+
|
|
18
|
+
$stderr.puts('WARNING: This test fails on jRuby due to incorrect EC Keys implementation. It would still work ' \
|
|
19
|
+
'if the OpenSSL keys were generated instead of loaded.')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'resolves bob\'s key according to the spec' do
|
|
24
|
+
alg = described_class.new(bob.to_openssl_key, JWA::Algorithms::ContentEncryption::A128Gcm, 'Alice', 'Bob')
|
|
25
|
+
|
|
26
|
+
begin
|
|
27
|
+
actual = alg.encrypt(alice.to_openssl_key.public_key)
|
|
28
|
+
expect(actual).to eq expected
|
|
29
|
+
rescue Exception => e
|
|
30
|
+
raise e unless defined?(JRUBY_VERSION)
|
|
31
|
+
|
|
32
|
+
$stderr.puts('WARNING: This test fails on jRuby due to incorrect EC Keys implementation. It would still work ' \
|
|
33
|
+
'if the OpenSSL keys were generated instead of loaded.')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
describe JWA::Algorithms::KeyManagement::Pbes2Hs256A128Kw do
|
|
2
|
+
let(:password) { 'Thus from my lips, by yours, my sin is purged.' }
|
|
3
|
+
let(:salt) { int_byte_array_to_bytes([217, 96, 147, 112, 150, 117, 70, 247, 127, 8, 155, 137, 174, 42, 80, 215]) }
|
|
4
|
+
let(:iterations) { 4096 }
|
|
5
|
+
|
|
6
|
+
let(:plaintext) do
|
|
7
|
+
int_byte_array_to_bytes([111, 27, 25, 52, 66, 29, 20, 78, 92, 176, 56, 240, 65, 208, 82, 112,
|
|
8
|
+
161, 131, 36, 55, 202, 236, 185, 172, 129, 23, 153, 194, 195, 48,
|
|
9
|
+
253, 182])
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:ciphertext) do
|
|
13
|
+
int_byte_array_to_bytes([78, 186, 151, 59, 11, 141, 81, 240, 213, 245, 83, 211, 53, 188, 134,
|
|
14
|
+
188, 66, 125, 36, 200, 222, 124, 5, 103, 249, 52, 117, 184, 140, 81,
|
|
15
|
+
246, 158, 161, 177, 20, 33, 245, 57, 59, 4])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'decrypts according to the Test Case (RFC 7517 - Appendix C)' do
|
|
19
|
+
alg = described_class.new(password, salt, iterations)
|
|
20
|
+
expect(alg.decrypt(ciphertext)).to eq plaintext
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'encrypts according to the Test Case' do
|
|
24
|
+
alg = described_class.new(password, salt, iterations)
|
|
25
|
+
expect(alg.encrypt(plaintext)).to eq ciphertext
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# WARNING:
|
|
2
|
+
# No public test case was found, so this was artificially generated.
|
|
3
|
+
# The ciphertext here is what I expect it to be, not what is known to be correct.
|
|
4
|
+
# Hopefully it's still correct
|
|
5
|
+
|
|
6
|
+
describe JWA::Algorithms::KeyManagement::Pbes2Hs384A192Kw do
|
|
7
|
+
let(:password) { 'Thus from my lips, by yours, my sin is purged.' }
|
|
8
|
+
let(:salt) { int_byte_array_to_bytes([217, 96, 147, 112, 150, 117, 70, 247, 127, 8, 155, 137, 174, 42, 80, 215]) }
|
|
9
|
+
let(:iterations) { 4096 }
|
|
10
|
+
|
|
11
|
+
let(:plaintext) do
|
|
12
|
+
int_byte_array_to_bytes([111, 27, 25, 52, 66, 29, 20, 78, 92, 176, 56, 240, 65, 208, 82, 112,
|
|
13
|
+
161, 131, 36, 55, 202, 236, 185, 172, 129, 23, 153, 194, 195, 48,
|
|
14
|
+
253, 182])
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
let(:ciphertext) do
|
|
18
|
+
int_byte_array_to_bytes([215, 56, 252, 107, 109, 188, 15, 220, 217, 9, 142, 195, 65, 53, 139,
|
|
19
|
+
56, 180, 25, 68, 130, 147, 127, 238, 100, 239, 217, 250, 240, 70, 8,
|
|
20
|
+
35, 18, 242, 142, 239, 238, 250, 130, 221, 180])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'decrypts predictably' do
|
|
24
|
+
alg = described_class.new(password, salt, iterations)
|
|
25
|
+
expect(alg.decrypt(ciphertext)).to eq plaintext
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'encrypts predictably' do
|
|
29
|
+
alg = described_class.new(password, salt, iterations)
|
|
30
|
+
expect(alg.encrypt(plaintext)).to eq ciphertext
|
|
31
|
+
end
|
|
32
|
+
end
|