class Aws::S3::EncryptionV2::DefaultCipherProvider

@api private

def decode64(str)

def decode64(str)
  Base64.decode64(str)
end

def decryption_cipher(envelope, options = {})

Returns:
  • (Cipher) - Given an encryption envelope, returns a
def decryption_cipher(envelope, options = {})
  validate_options(options)
  master_key = @key_provider.key_for(envelope['x-amz-matdesc'])
  if envelope.key? 'x-amz-key'
    unless options[:security_profile] == :v2_and_legacy
      raise Errors::LegacyDecryptionError
    end
    # Support for decryption of legacy objects
    key = Utils.decrypt(master_key, decode64(envelope['x-amz-key']))
    iv = decode64(envelope['x-amz-iv'])
    Utils.aes_decryption_cipher(:CBC, key, iv)
  else
    if envelope['x-amz-cek-alg'] != 'AES/GCM/NoPadding'
      raise ArgumentError, 'Unsupported cek-alg: ' \
        "#{envelope['x-amz-cek-alg']}"
    end
    key =
      case envelope['x-amz-wrap-alg']
      when 'AES/GCM'
        if master_key.is_a? OpenSSL::PKey::RSA
          raise ArgumentError, 'Key mismatch - Client is configured' \
            ' with an RSA key and the x-amz-wrap-alg is AES/GCM.'
        end
        Utils.decrypt_aes_gcm(master_key,
                            decode64(envelope['x-amz-key-v2']),
                            envelope['x-amz-cek-alg'])
      when 'RSA-OAEP-SHA1'
        unless master_key.is_a? OpenSSL::PKey::RSA
          raise ArgumentError, 'Key mismatch - Client is configured' \
            ' with an AES key and the x-amz-wrap-alg is RSA-OAEP-SHA1.'
        end
        key, cek_alg = Utils.decrypt_rsa(master_key, decode64(envelope['x-amz-key-v2']))
        raise Errors::CEKAlgMismatchError unless cek_alg == envelope['x-amz-cek-alg']
        key
      when 'kms+context'
        raise ArgumentError, 'Key mismatch - Client is configured' \
            ' with a user provided key and the x-amz-wrap-alg is' \
            ' kms+context.  Please configure the client with the' \
            ' required kms_key_id'
      else
        raise ArgumentError, 'Unsupported wrap-alg: ' \
              "#{envelope['x-amz-wrap-alg']}"
      end
    iv = decode64(envelope['x-amz-iv'])
    Utils.aes_decryption_cipher(:GCM, key, iv)
  end
end

def encode64(str)

def encode64(str)
  Base64.encode64(str).split("\n") * ''
end

def encrypt_aes_gcm(data, auth_data)

def encrypt_aes_gcm(data, auth_data)
  Utils.encrypt_aes_gcm(@key_provider.encryption_materials.key, data, auth_data)
end

def encrypt_rsa(data, auth_data)

def encrypt_rsa(data, auth_data)
  Utils.encrypt_rsa(@key_provider.encryption_materials.key, data, auth_data)
end

def encryption_cipher(options = {})

Returns:
  • (Array) - Creates an returns a new encryption
def encryption_cipher(options = {})
  validate_options(options)
  cipher = Utils.aes_encryption_cipher(:GCM)
  if @key_provider.encryption_materials.key.is_a? OpenSSL::PKey::RSA
    enc_key = encode64(
      encrypt_rsa(envelope_key(cipher), @content_encryption_schema)
    )
  else
    enc_key = encode64(
      encrypt_aes_gcm(envelope_key(cipher), @content_encryption_schema)
    )
  end
  envelope = {
    'x-amz-key-v2' => enc_key,
    'x-amz-cek-alg' => @content_encryption_schema,
    'x-amz-tag-len' => (AES_GCM_TAG_LEN_BYTES * 8).to_s,
    'x-amz-wrap-alg' => @key_wrap_schema,
    'x-amz-iv' => encode64(envelope_iv(cipher)),
    'x-amz-matdesc' => materials_description
  }
  cipher.auth_data = '' # auth_data must be set after key and iv
  [envelope, cipher]
end

def envelope_iv(cipher)

def envelope_iv(cipher)
  cipher.iv = cipher.random_iv
end

def envelope_key(cipher)

def envelope_key(cipher)
  cipher.key = cipher.random_key
end

def initialize(options = {})

def initialize(options = {})
  @key_provider = options[:key_provider]
  @key_wrap_schema = validate_key_wrap(
    options[:key_wrap_schema],
    @key_provider.encryption_materials.key
  )
  @content_encryption_schema = validate_cek(
    options[:content_encryption_schema]
  )
end

def materials_description

def materials_description
  @key_provider.encryption_materials.description
end

def validate_cek(content_encryption_schema)

def validate_cek(content_encryption_schema)
  case content_encryption_schema
  when :aes_gcm_no_padding
    "AES/GCM/NoPadding"
  else
    raise ArgumentError, "Unsupported content_encryption_schema: #{content_encryption_schema}"
  end
end

def validate_key_wrap(key_wrap_schema, key)

Returns the string version for the x-amz-key-wrap-alg
is valid, supported and matches the provided key.
Validate that the key_wrap_schema
def validate_key_wrap(key_wrap_schema, key)
  if key.is_a? OpenSSL::PKey::RSA
    unless key_wrap_schema == :rsa_oaep_sha1
      raise ArgumentError, ':key_wrap_schema must be set to :rsa_oaep_sha1 for RSA keys.'
    end
  else
    unless key_wrap_schema == :aes_gcm
      raise ArgumentError, ':key_wrap_schema must be set to :aes_gcm for AES keys.'
    end
  end
  case key_wrap_schema
  when :rsa_oaep_sha1 then 'RSA-OAEP-SHA1'
  when :aes_gcm then 'AES/GCM'
  when :kms_context
    raise ArgumentError, 'A kms_key_id is required when using :kms_context.'
  else
    raise ArgumentError, "Unsupported key_wrap_schema: #{key_wrap_schema}"
  end
end

def validate_options(options)

def validate_options(options)
  if !options[:kms_encryption_context].nil?
    raise ArgumentError, 'Cannot provide :kms_encryption_context ' \
    'with non KMS client.'
  end
end