class BB::Crypto::ControlToken

Secure Control Token.

Public Class Methods

create(op, args, expire_in = 900, key = ENV['CONTROLTOKEN_SECRET'], cipher_type = 'aes-256-cbc') click to toggle source

Encode and encrypt an urlsafe ControlToken.

@param [String] op Operation id @param [Array] args Arguments (Strings) @param [Fixnum] expire_in @param [String] key Encryption key @param [String] cipher_type OpenSSL cipher @return [String] ControlToken (urlsafe base64)

# File lib/blackbox/crypto.rb, line 110
def create(op, args, expire_in = 900, key = ENV['CONTROLTOKEN_SECRET'], cipher_type = 'aes-256-cbc')
  raise ArgumentError, 'key can not be blank' if key.nil? || key.empty?
  # If you're reading this in the year 2038: Hi there! :-)
  [Time.now.to_i + expire_in].pack('l<')
  body = ([[Time.now.to_i + expire_in].pack('l<'), op] + args).join("\x00")
  BB::Crypto.encrypt_urlsafe_base64(body, key, cipher_type)
end
parse(token, key = ENV['CONTROLTOKEN_SECRET'], force = false, cipher_type = 'aes-256-cbc') click to toggle source

Decrypt and parse an urlsafe ControlToken.

@param [String] token Input String (urlsafe base64) @param [String] key Encryption key @param [Boolean] force Decode expired token (suppress ArgumentError) @param [String] cipher_type OpenSSL cipher @return [Hash] Token payload

# File lib/blackbox/crypto.rb, line 125
def parse(token, key = ENV['CONTROLTOKEN_SECRET'], force = false, cipher_type = 'aes-256-cbc')
  raise ArgumentError, 'key can not be blank' if key.nil? || key.empty?
  body = BB::Crypto.decrypt_urlsafe_base64(token, key, cipher_type)
  valid_until, op, *args = body.split("\x00")
  valid_until = valid_until.unpack('l<')[0]
  expired = Time.now.to_i > valid_until
  raise ArgumentError, "Token expired at #{Time.at(valid_until)} (#{ChronicDuration.output(Time.now.to_i - valid_until)} ago)" if expired && !force
  { valid_until: valid_until,
    op: op,
    args: args,
    expired: expired }
end