jwa 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|