Sha256: f017f5f9941393312d2915f5cbf0d3ab1445ec56d6c2371c612e64f6fa625f5f

Contents?: true

Size: 1.82 KB

Versions: 8

Compression:

Stored size: 1.82 KB

Contents

module Slosilo
  class Symmetric
    VERSION_MAGIC = 'G'
    TAG_LENGTH = 16

    def initialize
      @cipher = OpenSSL::Cipher.new 'aes-256-gcm' # NB: has to be lower case for whatever reason.
      @cipher_mutex = Mutex.new
    end

    # This lets us do a final sanity check in migrations from older encryption versions
    def cipher_name
      @cipher.name
    end

    def encrypt plaintext, opts = {}
      # All of these operations in OpenSSL must occur atomically, so we
      # synchronize their access to make this step thread-safe.
      @cipher_mutex.synchronize do
        @cipher.reset
        @cipher.encrypt
        @cipher.key = (opts[:key] or raise("missing :key option"))
        @cipher.iv = iv = random_iv
        @cipher.auth_data = opts[:aad] || "" # Nothing good happens if you set this to nil, or don't set it at all
        ctext = @cipher.update(plaintext) + @cipher.final
        tag = @cipher.auth_tag(TAG_LENGTH)
        "#{VERSION_MAGIC}#{tag}#{iv}#{ctext}"
      end
    end

    def decrypt ciphertext, opts = {}
      version, tag, iv, ctext = unpack ciphertext

      raise "Invalid version magic: expected #{VERSION_MAGIC} but was #{version}" unless version == VERSION_MAGIC

      # All of these operations in OpenSSL must occur atomically, so we
      # synchronize their access to make this step thread-safe.
      @cipher_mutex.synchronize do
        @cipher.reset
        @cipher.decrypt
        @cipher.key = opts[:key]
        @cipher.iv = iv
        @cipher.auth_tag = tag
        @cipher.auth_data = opts[:aad] || ""
        @cipher.update(ctext) + @cipher.final
      end
    end

    def random_iv
      @cipher.random_iv
    end

    def random_key
      @cipher.random_key
    end

    private
    # return tag, iv, ctext
    def unpack msg
      msg.unpack "aa#{TAG_LENGTH}a#{@cipher.iv_len}a*"
    end
  end
end

Version data entries

8 entries across 8 versions & 1 rubygems

Version Path
slosilo-3.0.2.pre.224 lib/slosilo/symmetric.rb
slosilo-3.0.2.pre.5 lib/slosilo/symmetric.rb
slosilo-3.0.2.pre.44 lib/slosilo/symmetric.rb
slosilo-3.0.2.pre.42 lib/slosilo/symmetric.rb
slosilo-3.0.2.pre.2 lib/slosilo/symmetric.rb
slosilo-3.0.2.pre.35 lib/slosilo/symmetric.rb
slosilo-0.0.0 lib/slosilo/symmetric.rb
slosilo-3.0.1 lib/slosilo/symmetric.rb