main
1# frozen_string_literal: true
2
3RSpec.describe ::Xml::Kit::Crypto::SymmetricCipher do
4 %w[
5 aes128-cbc
6 aes192-cbc
7 aes256-cbc
8 tripledes-cbc
9 ].each do |algorithm|
10 describe algorithm do
11 let(:xml_algorithm) { "#{::Xml::Kit::Namespaces::XMLENC}#{algorithm}" }
12 let(:openssl_algorithm) { Xml::Kit::Crypto::SymmetricCipher::ALGORITHMS[xml_algorithm].downcase }
13 let(:key) { SecureRandom.random_bytes(cipher.key_len) }
14 let(:iv) { SecureRandom.random_bytes(cipher.iv_len) }
15 let(:cipher) { OpenSSL::Cipher.new(openssl_algorithm) }
16
17 describe 'encrypting and decrypting' do
18 subject { described_class.new(xml_algorithm, key) }
19
20 let(:uuid) { SecureRandom.uuid }
21
22 specify { expect(subject.decrypt(subject.encrypt(uuid))).to eql(uuid) }
23 end
24
25 describe "decrypting #{algorithm} encrypted with the OpenSSL CLI" do
26 subject { described_class.new(xml_algorithm, key, 0) }
27
28 let(:encrypted_file) { Tempfile.new(algorithm).path }
29 let(:original_file) { Tempfile.new("#{algorithm}-original").path }
30 let(:secret) { SecureRandom.hex }
31 let(:data) { (iv.bytes + secret.bytes).pack('c*') }
32
33 context 'when encoded as ASCII' do
34 before do
35 IO.write(original_file, data, encoding: Encoding::ASCII_8BIT)
36 execute_shell([
37 "openssl enc -#{openssl_algorithm} -p -e -A -nosalt",
38 "-in #{original_file}",
39 "-out #{encrypted_file}",
40 "-K #{key.unpack1('H*').upcase}",
41 "-iv #{iv.unpack1('H*').upcase}"
42 ].join(' '))
43 end
44
45 specify do
46 cipher_text = IO.read(encrypted_file, encoding: Encoding::ASCII_8BIT)
47 expect(subject.decrypt(cipher_text)).to eql(secret)
48 end
49 end
50
51 context 'when encoded as UTF-8' do
52 before do
53 IO.write(original_file, data)
54 execute_shell([
55 "openssl enc -#{openssl_algorithm} -p -e -A -nosalt",
56 "-in #{original_file}",
57 "-out #{encrypted_file}",
58 "-K #{key.unpack1('H*').upcase}",
59 "-iv #{iv.unpack1('H*').upcase}"
60 ].join(' '))
61 end
62
63 specify do
64 cipher_text = IO.read(encrypted_file)
65 expect(subject.decrypt(cipher_text)).to eql(secret)
66 end
67 end
68 end
69
70 describe 'when decrypting with the OpenSSL CLI' do
71 subject { described_class.new(xml_algorithm, key) }
72
73 let(:encrypted_file) { Tempfile.new(algorithm).path }
74 let(:decrypted_file) { Tempfile.new("#{algorithm}-decrypted").path }
75 let(:secret) { SecureRandom.hex }
76
77 before do
78 IO.write(encrypted_file, subject.encrypt(secret))
79 execute_shell([
80 "openssl enc -#{openssl_algorithm} -p -d -nosalt",
81 "-in #{encrypted_file}",
82 "-out #{decrypted_file}",
83 "-K #{key.unpack1('H*').upcase}",
84 "-iv #{iv.unpack1('H*').upcase}"
85 ].join(' '))
86 end
87
88 specify { expect(IO.read(decrypted_file)).to end_with(secret) }
89 end
90 end
91 end
92end