class Rage::Cookies::EncryptedJar

def build_key(secret)

def build_key(secret)
  RbNaCl::Hash.blake2b("", key: [secret].pack("H*"), digest_size: 32, personal: INFO)
end

def dump(value)

def dump(value)
  # add two bytes to hold meta information, e.g. in case we
  # need to change the encryption algorithm in the future
  Base64.urlsafe_encode64(PADDING + primary_box.encrypt(value.to_s))
end

def fallback_boxes

def fallback_boxes
  @fallback_boxes ||= begin
    fallbacks = Rage.config.fallback_secret_key_base.map do |key|
      RbNaCl::SimpleBox.from_secret_key(build_key(key))
    end
    fallbacks << RbNaCl::SimpleBox.from_secret_key(
      RbNaCl::Hash.blake2b(Rage.config.secret_key_base, digest_size: 32, salt: INFO)
    )
  end
end

def load(value)

def load(value)
  box = primary_box
  begin
    box.decrypt(Base64.urlsafe_decode64(value).byteslice(2..))
  rescue ArgumentError
    Rage.logger.debug("Failed to decode encrypted cookie")
    nil
  rescue RbNaCl::CryptoError
    Rage.logger.debug("Failed to decrypt encrypted cookie")
    i ||= 0
    if (box = fallback_boxes[i])
      Rage.logger.debug { "Trying to decrypt with fallback key ##{i + 1}" }
      i += 1
      retry
    end
  end
end

def primary_box

def primary_box
  @primary_box ||= begin
    if !defined?(RbNaCl) || !(Gem::Version.create(RbNaCl::VERSION) >= Gem::Version.create("3.3.0") && Gem::Version.create(RbNaCl::VERSION) < Gem::Version.create("8.0.0"))
      fail <<~ERR
        Rage depends on `rbnacl` [>= 3.3, < 8.0] to encrypt cookies. Ensure the following line is added to your Gemfile:
        gem "rbnacl"
      ERR
    end
    unless Rage.config.secret_key_base
      raise "Rage.config.secret_key_base should be set to use encrypted cookies"
    end
    RbNaCl::SimpleBox.from_secret_key(build_key(Rage.config.secret_key_base))
  end
end