File: decrypt.rb

package info (click to toggle)
ruby-mongo 2.21.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 14,764 kB
  • sloc: ruby: 108,806; makefile: 5; sh: 2
file content (105 lines) | stat: -rw-r--r-- 2,802 bytes parent folder | download
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
93
94
95
96
97
98
99
100
101
102
103
104
105
# frozen_string_literal: true

require 'mongo'
require_relative '../base'

module Mongo
  module DriverBench
    module Crypto
      # Benchmark for reporting the performance of decrypting a document with
      # a large number of encrypted fields.
      class Decrypt < Mongo::DriverBench::Base
        ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
        KEY_VAULT_NAMESPACE = 'encryption.__keyVault'
        N = 10

        def run
          doc = build_encrypted_doc

          # warm up
          run_test(doc, 1)

          [ 1, 2, 8, 64 ].each do |thread_count|
            run_test_with_thread_count(doc, thread_count)
          end
        end

        private

        def run_test_with_thread_count(doc, thread_count)
          results = []

          N.times do
            threads = Array.new(thread_count) do
              Thread.new { Thread.current[:ops_sec] = run_test(doc, 1) }
            end

            results << threads.each(&:join).sum { |t| t[:ops_sec] }
          end

          median = results.sort[N / 2]
          puts "thread_count=#{thread_count}; median ops/sec=#{median}"
        end

        def build_encrypted_doc
          data_key_id = client_encryption.create_data_key('local')

          pairs = Array.new(1500) do |i|
            n = format('%04d', i + 1)
            key = "key#{n}"
            value = "value #{n}"

            encrypted = client_encryption.encrypt(value,
                                                  key_id: data_key_id,
                                                  algorithm: ALGORITHM)

            [ key, encrypted ]
          end

          BSON::Document[pairs]
        end

        def timeout_holder
          @timeout_holder ||= Mongo::CsotTimeoutHolder.new
        end

        def encrypter
          @encrypter ||= Crypt::AutoEncrypter.new(
            client: new_client,
            key_vault_client: key_vault_client,
            key_vault_namespace: KEY_VAULT_NAMESPACE,
            kms_providers: kms_providers
          )
        end

        def run_test(doc, duration)
          finish_at = Mongo::Utils.monotonic_time + duration
          count = 0

          while Mongo::Utils.monotonic_time < finish_at
            encrypter.decrypt(doc, timeout_holder)
            count += 1
          end

          count
        end

        def key_vault_client
          @key_vault_client ||= new_client
        end

        def kms_providers
          @kms_providers ||= { local: { key: SecureRandom.random_bytes(96) } }
        end

        def client_encryption
          @client_encryption ||= Mongo::ClientEncryption.new(
            key_vault_client,
            key_vault_namespace: KEY_VAULT_NAMESPACE,
            kms_providers: kms_providers
          )
        end
      end
    end
  end
end