summaryrefslogtreecommitdiff
path: root/spec/xml/kit/crypto/symmetric_cipher_spec.rb
blob: 534bec828cf9be85d691566405a969a838b6639c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# frozen_string_literal: true

RSpec.describe ::Xml::Kit::Crypto::SymmetricCipher do
  %w[
    aes128-cbc
    aes192-cbc
    aes256-cbc
    tripledes-cbc
  ].each do |algorithm|
    describe algorithm do
      let(:xml_algorithm) { "#{::Xml::Kit::Namespaces::XMLENC}#{algorithm}" }
      let(:openssl_algorithm) { Xml::Kit::Crypto::SymmetricCipher::ALGORITHMS[xml_algorithm].downcase }
      let(:key) { SecureRandom.random_bytes(cipher.key_len) }
      let(:iv) { SecureRandom.random_bytes(cipher.iv_len) }
      let(:cipher) { OpenSSL::Cipher.new(openssl_algorithm) }

      describe 'encrypting and decrypting' do
        subject { described_class.new(xml_algorithm, key) }

        let(:uuid) { SecureRandom.uuid }

        specify { expect(subject.decrypt(subject.encrypt(uuid))).to eql(uuid) }
      end

      describe "decrypting #{algorithm} encrypted with the OpenSSL CLI" do
        subject { described_class.new(xml_algorithm, key, 0) }

        let(:encrypted_file) { Tempfile.new(algorithm).path }
        let(:original_file) { Tempfile.new("#{algorithm}-original").path }
        let(:secret) { SecureRandom.hex }
        let(:data) { (iv.bytes + secret.bytes).pack('c*') }

        context 'when encoded as ASCII' do
          before do
            IO.write(original_file, data, encoding: Encoding::ASCII_8BIT)
            execute_shell([
              "openssl enc -#{openssl_algorithm} -p -e -A -nosalt",
              "-in #{original_file}",
              "-out #{encrypted_file}",
              "-K #{key.unpack1('H*').upcase}",
              "-iv #{iv.unpack1('H*').upcase}"
            ].join(' '))
          end

          specify do
            cipher_text = IO.read(encrypted_file, encoding: Encoding::ASCII_8BIT)
            expect(subject.decrypt(cipher_text)).to eql(secret)
          end
        end

        context 'when encoded as UTF-8' do
          before do
            IO.write(original_file, data)
            execute_shell([
              "openssl enc -#{openssl_algorithm} -p -e -A -nosalt",
              "-in #{original_file}",
              "-out #{encrypted_file}",
              "-K #{key.unpack1('H*').upcase}",
              "-iv #{iv.unpack1('H*').upcase}"
            ].join(' '))
          end

          specify do
            cipher_text = IO.read(encrypted_file)
            expect(subject.decrypt(cipher_text)).to eql(secret)
          end
        end
      end

      describe 'when decrypting with the OpenSSL CLI' do
        subject { described_class.new(xml_algorithm, key) }

        let(:encrypted_file) { Tempfile.new(algorithm).path }
        let(:decrypted_file) { Tempfile.new("#{algorithm}-decrypted").path }
        let(:secret) { SecureRandom.hex }

        before do
          IO.write(encrypted_file, subject.encrypt(secret))
          execute_shell([
            "openssl enc -#{openssl_algorithm} -p -d -nosalt",
            "-in #{encrypted_file}",
            "-out #{decrypted_file}",
            "-K #{key.unpack1('H*').upcase}",
            "-iv #{iv.unpack1('H*').upcase}"
          ].join(' '))
        end

        specify { expect(IO.read(decrypted_file)).to end_with(secret) }
      end
    end
  end
end