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.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +15 -0
  3. data/.gitignore +17 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +16 -0
  6. data/.travis.yml +15 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.md +23 -0
  9. data/README.md +26 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/jwa.gemspec +27 -0
  14. data/lib/jwa.rb +16 -0
  15. data/lib/jwa/algorithms.rb +2 -0
  16. data/lib/jwa/algorithms/content_encryption.rb +29 -0
  17. data/lib/jwa/algorithms/content_encryption/a128_cbc_hs256.rb +29 -0
  18. data/lib/jwa/algorithms/content_encryption/a128_gcm.rb +25 -0
  19. data/lib/jwa/algorithms/content_encryption/a192_cbc_hs384.rb +29 -0
  20. data/lib/jwa/algorithms/content_encryption/a192_gcm.rb +25 -0
  21. data/lib/jwa/algorithms/content_encryption/a256_cbc_hs512.rb +29 -0
  22. data/lib/jwa/algorithms/content_encryption/a256_gcm.rb +25 -0
  23. data/lib/jwa/algorithms/content_encryption/aes_cbc_hs.rb +85 -0
  24. data/lib/jwa/algorithms/content_encryption/aes_gcm.rb +64 -0
  25. data/lib/jwa/algorithms/key_management.rb +56 -0
  26. data/lib/jwa/algorithms/key_management/a128_gcm_kw.rb +21 -0
  27. data/lib/jwa/algorithms/key_management/a128_kw.rb +21 -0
  28. data/lib/jwa/algorithms/key_management/a192_gcm_kw.rb +21 -0
  29. data/lib/jwa/algorithms/key_management/a192_kw.rb +21 -0
  30. data/lib/jwa/algorithms/key_management/a256_gcm_kw.rb +21 -0
  31. data/lib/jwa/algorithms/key_management/a256_kw.rb +21 -0
  32. data/lib/jwa/algorithms/key_management/aes_gcm_kw.rb +26 -0
  33. data/lib/jwa/algorithms/key_management/aes_kw.rb +100 -0
  34. data/lib/jwa/algorithms/key_management/ecdh_es.rb +45 -0
  35. data/lib/jwa/algorithms/key_management/ecdh_es_a128_kw.rb +25 -0
  36. data/lib/jwa/algorithms/key_management/ecdh_es_a192_kw.rb +25 -0
  37. data/lib/jwa/algorithms/key_management/ecdh_es_a256_kw.rb +25 -0
  38. data/lib/jwa/algorithms/key_management/ecdh_es_kw.rb +23 -0
  39. data/lib/jwa/algorithms/key_management/pbes2.rb +27 -0
  40. data/lib/jwa/algorithms/key_management/pbes_hs256_a128_kw.rb +25 -0
  41. data/lib/jwa/algorithms/key_management/pbes_hs384_a192_kw.rb +25 -0
  42. data/lib/jwa/algorithms/key_management/pbes_hs512_a256_kw.rb +25 -0
  43. data/lib/jwa/algorithms/key_management/rsa15.rb +20 -0
  44. data/lib/jwa/algorithms/key_management/rsa_oaep.rb +20 -0
  45. data/lib/jwa/cipher.rb +17 -0
  46. data/lib/jwa/support/concat_kdf.rb +29 -0
  47. data/lib/jwa/support/pbkdf2.rb +48 -0
  48. data/lib/jwa/version.rb +3 -0
  49. data/spec/jwa/algorithms/content_encryption/a128_cbc_hs256_spec.rb +30 -0
  50. data/spec/jwa/algorithms/content_encryption/a128_gcm_spec.rb +42 -0
  51. data/spec/jwa/algorithms/content_encryption/a192_cbc_hs384_spec.rb +34 -0
  52. data/spec/jwa/algorithms/content_encryption/a192_gcm_spec.rb +49 -0
  53. data/spec/jwa/algorithms/content_encryption/a256_cbc_hs512_spec.rb +35 -0
  54. data/spec/jwa/algorithms/content_encryption/a256_gcm_spec.rb +61 -0
  55. data/spec/jwa/algorithms/content_encryption/aes_cbc_hs_shared.rb +96 -0
  56. data/spec/jwa/algorithms/content_encryption/aes_gcm_shared.rb +60 -0
  57. data/spec/jwa/algorithms/content_encryption_spec.rb +7 -0
  58. data/spec/jwa/algorithms/key_management/a128_kw_spec.rb +43 -0
  59. data/spec/jwa/algorithms/key_management/a192_kw_spec.rb +29 -0
  60. data/spec/jwa/algorithms/key_management/a256_kw_spec.rb +29 -0
  61. data/spec/jwa/algorithms/key_management/ecdh_es_spec.rb +36 -0
  62. data/spec/jwa/algorithms/key_management/pbes2_hs256_a128_kw_spec.rb +27 -0
  63. data/spec/jwa/algorithms/key_management/pbes2_hs384_a192_kw_spec.rb +32 -0
  64. data/spec/jwa/algorithms/key_management/pbes2_hs512_a256_kw_spec.rb +32 -0
  65. data/spec/jwa/algorithms/key_management/rsa15_spec.rb +44 -0
  66. data/spec/jwa/algorithms/key_management/rsa_oaep_spec.rb +44 -0
  67. data/spec/jwa/algorithms/key_management_spec.rb +7 -0
  68. data/spec/jwa/cipher_spec.rb +7 -0
  69. data/spec/jwa/support/concat_kdf_spec.rb +32 -0
  70. data/spec/jwa/support/pbkdf2_spec.rb +111 -0
  71. data/spec/jwa_spec.rb +5 -0
  72. data/spec/spec_helper.rb +22 -0
  73. data/spec/support/ec1.json +7 -0
  74. data/spec/support/ec2.json +7 -0
  75. data/spec/support/hex_helpers.rb +9 -0
  76. data/spec/support/oct16.json +4 -0
  77. data/spec/support/oct24.json +4 -0
  78. data/spec/support/oct32.json +4 -0
  79. data/spec/support/rsa1.json +11 -0
  80. data/spec/support/rsa2.json +11 -0
  81. 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,7 @@
1
+ describe JWA::Algorithms::ContentEncryption do
2
+ describe '.for' do
3
+ it 'returns a class for a given encryption method name' do
4
+ expect(described_class.for('A128GCM')).to be JWA::Algorithms::ContentEncryption::A128Gcm
5
+ end
6
+ end
7
+ 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