Created
March 25, 2019 13:59
-
-
Save elsurudo/b93ac65c74500386a2c07423e62b30f5 to your computer and use it in GitHub Desktop.
Knuthy Obfuscation (Optimus Prime)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/concerns/obfuscation.rb | |
# ID obfuscation using Optimus algorithm | |
# TODO if we want to use this with more classes, it'd | |
# be best to make sure we use a different random seed | |
# for each model. | |
# Do something like this: http://jes.al/2014/11/creating-rails-concern-accepts-argumentsparameters/ | |
module Obfuscation | |
extend ActiveSupport::Concern | |
module ClassMethods | |
def obfuscate_id(n) | |
OPTIMUS.encode(n.to_i) | |
end | |
def deobfuscate_id(str) | |
OPTIMUS.decode(str.to_i) | |
end | |
def find_by_obfuscated_id(id) | |
find_by(id: OPTIMUS.decode(id.to_i)) | |
end | |
def find_by_obfuscated_id!(id) | |
find_by!(id: OPTIMUS.decode(id.to_i)) | |
end | |
end | |
def obfuscated_id | |
OPTIMUS.encode(id.to_i) | |
end | |
def to_param | |
respond_to?(:title) && title.present? ? "#{obfuscated_id}-#{title.parameterize}" : obfuscated_id.to_s | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/util/optimus.rb | |
# Donald Knuth's two-way fast hashing algorithm | |
# More info: https://jenssegers.com/67/id-transformation-with-optimus | |
# Based on: https://github.com/jenssegers/optimus | |
# Generate prime, inverse, and random xor with `php vendor/bin/optimus spark` (must have above installed via PHP composer) | |
# Numeric alternative to: http://hashids.org/ruby/ | |
module Optimus | |
class Optimus | |
MAX_INT = 2147483647 # based on Postgres' integer/int4 maximum | |
def initialize(prime, inverse, xor = 0) | |
raise ArgumentError, "prime must be an integer" unless (prime.is_a?(Numeric) && prime.integer?) | |
raise ArgumentError, "inverse must be an integer" unless (inverse.is_a?(Numeric) && inverse.integer?) | |
raise ArgumentError, "xor must be an integer" unless (xor.is_a?(Numeric) && xor.integer?) | |
@prime = prime.to_i | |
@inverse = inverse.to_i | |
@xor = xor.to_i | |
end | |
def encode(value) | |
raise ArgumentError, "Value to encode must be an integer" unless (value.is_a?(Numeric) && value.integer?) | |
((value.to_i * @prime) & MAX_INT) ^ @xor | |
end | |
def decode(value) | |
raise ArgumentError, "Value to decode must be an integer" unless (value.is_a?(Numeric) && value.integer?) | |
((value.to_i ^ @xor) * @inverse) & MAX_INT | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/initializers/optimus_primes.rb | |
OPTIMUS = Optimus::Optimus.new(ENV['optimus_prime'].to_i, ENV['optimus_inverse'].to_i, ENV['optimus_random'].to_i) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment