<commit_before>require 'openssl'
require 'encryptor/string'

String.send(:include, Encryptor::String)

# A simple wrapper for the standard OpenSSL library
module Encryptor
  autoload :Version, 'encryptor/version'

  extend self

  # The default options to use when calling the <tt>encrypt</tt> and <tt>decrypt</tt> methods
  #
  # Defaults to { :algorithm => 'aes-256-cbc' }
  #
  # Run 'openssl list-cipher-commands' in your terminal to view a list all cipher algorithms that are supported on your platform
  def default_options
    @default_options ||= { :algorithm => 'aes-256-cbc' }
  end

  # Encrypts a <tt>:value</tt> with a specified <tt>:key</tt>
  #
  # Optionally accepts <tt>:iv</tt> and <tt>:algorithm</tt> options
  #
  # Example
  #
  #   encrypted_value = Encryptor.encrypt(:value => 'some string to encrypt', :key => 'some secret key')
  #   # or
  #   encrypted_value = Encryptor.encrypt('some string to encrypt', :key => 'some secret key')
  def encrypt(*args, &block)
    crypt :encrypt, *args, &block
  end

  # Decrypts a <tt>:value</tt> with a specified <tt>:key</tt>
  #
  # Optionally accepts <tt>:iv</tt> and <tt>:algorithm</tt> options
  #
  # Example
  #
  #   decrypted_value = Encryptor.decrypt(:value => 'some encrypted string', :key => 'some secret key')
  #   # or
  #   decrypted_value = Encryptor.decrypt('some encrypted string', :key => 'some secret key')
  def decrypt(*args, &block)
    crypt :decrypt, *args, &block
  end

  protected

    def crypt(cipher_method, *args) #:nodoc:
      options = default_options.merge(:value => args.first).merge(args.last.is_a?(Hash) ? args.last : {})
      raise ArgumentError.new('must specify a :key') if options[:key].to_s.empty?
      cipher = OpenSSL::Cipher::Cipher.new(options[:algorithm])
      cipher.send(cipher_method)
      if options[:iv]
        cipher.iv = options[:iv]
        if options[:salt].nil?
          # Use a non-salted cipher.
          # This behaviour is retained for backwards compatibility. This mode
          # is not secure and new deployments should use the :salt options
          # wherever possible.
          cipher.key = options[:key]
        else
          # Use an explicit salt (which can be persisted into a database on a
          # per-column basis, for example). This is the preferred (and more
          # secure) mode of operation.
          cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(options[:key], options[:salt], 2000, cipher.key_len)
        end
      else
        cipher.pkcs5_keyivgen(options[:key])
      end
      yield cipher, options if block_given?
      result = cipher.update(options[:value])
      result << cipher.final
    end<commit_msg>Added support for AEAD.<commit_after>require 'openssl'
require 'encryptor/string'

String.send(:include, Encryptor::String)

# A simple wrapper for the standard OpenSSL library
module Encryptor
  autoload :Version, 'encryptor/version'

  AUTHENTICATED_ENCRYPTION_ALGORITHMS = ['aes-128-gcm','aes-192-gcm','aes-256-gcm']

  extend self

  # The default options to use when calling the <tt>encrypt</tt> and <tt>decrypt</tt> methods
  #
  # Defaults to { :algorithm => 'aes-256-cbc' }
  #
  # Run 'openssl list-cipher-commands' in your terminal to view a list all cipher algorithms that are supported on your platform
  def default_options
    @default_options ||= { algorithm: 'aes-256-cbc', auth_data: '' }
  end

  # Encrypts a <tt>:value</tt> with a specified <tt>:key</tt>
  #
  # Optionally accepts <tt>:iv</tt> and <tt>:algorithm</tt> options
  #
  # Example
  #
  #   encrypted_value = Encryptor.encrypt(:value => 'some string to encrypt', :key => 'some secret key')
  #   # or
  #   encrypted_value = Encryptor.encrypt('some string to encrypt', :key => 'some secret key')
  def encrypt(*args, &block)
    crypt :encrypt, *args, &block
  end

  # Decrypts a <tt>:value</tt> with a specified <tt>:key</tt>
  #
  # Optionally accepts <tt>:iv</tt> and <tt>:algorithm</tt> options
  #
  # Example
  #
  #   decrypted_value = Encryptor.decrypt(:value => 'some encrypted string', :key => 'some secret key')
  #   # or
  #   decrypted_value = Encryptor.decrypt('some encrypted string', :key => 'some secret key')
  def decrypt(*args, &block)
    crypt :decrypt, *args, &block
  end

  protected

    def crypt(cipher_method, *args) #:nodoc:
      options = default_options.merge(:value => args.first).merge(args.last.is_a?(Hash) ? args.last : {})
      raise ArgumentError.new('must specify a :key') if options[:key].to_s.empty?
      cipher = OpenSSL::Cipher::Cipher.new(options[:algorithm])
      uses_message_authentication = AUTHENTICATED_ENCRYPTION_ALGORITHMS.include? options[:algorithm]
      cipher.send(cipher_method)
      if options[:iv]
        cipher.iv = options[:iv]
        if options[:salt].nil?
          # Use a non-salted cipher.
          # This behaviour is retained for backwards compatibility. This mode
          # is not secure and new deployments should use the :salt options
          # wherever possible.
          cipher.key = options[:key]
        else
          # Use an explicit salt (which can be persisted into a database on a
          # per-column basis, for example). This is the preferred (and more
          # secure) mode of operation.
          cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(options[:key], options[:salt], 2000, cipher.key_len)
        end
      else
        cipher.pkcs5_keyivgen(options[:key])
      end
      yield cipher, options if block_given?
      value = cipher_method == :decrypt && uses_message_authentication ? options[:value][0..-17] : options[:value]
      cipher.auth_tag = options[:value][-16..-1] if uses_message_authentication && cipher_method == :decrypt
      cipher.auth_data = options[:auth_data] if uses_message_authentication
      result = cipher.update(value)
      result << cipher.final
      result << cipher.auth_tag if uses_message_authentication && cipher_method == :encrypt
      result
    end

{'fraction_non_alphanumeric': 0.12294532036229454, 'fraction_numerical': 0.007212344850721235, 'mean_word_length': 3.256245538900785, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3168834', 'n_tokens_mistral': 1940, 'n_tokens_neox': 1832, 'n_words': 519}