Skip to content

Commit

Permalink
fixed comments in code and readme, bumped version for release
Browse files Browse the repository at this point in the history
  • Loading branch information
namick committed Feb 12, 2012
1 parent fd7f27f commit b2ddba0
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
obfuscate_id (0.0.1.alpha)
obfuscate_id (0.0.1)
rails (~> 3.2.1)

GEM
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ This is also useful for making different models in the same app have different o

## How it works

ObfuscateId pairs each number, from 0 to 9999999999, with one and only one number in that same range. That other number is paired back to the first. This is an example of a minimal perfect hash function. Within a set of one Billion numbers, it simply maps every number to a different 10 digit number, and back again.
ObfuscateId pairs each number, from 0 to 9999999999, with one and only one number in that same range. That other number is paired back to the first. This is an example of a minimal perfect hash function. Within a set of ten billion numbers, it simply maps every number to a different 10 digit number, and back again.

ObfuscateId switches the plain record id to the obfuscated id in the models `to_param` method.

Expand All @@ -71,7 +71,7 @@ It then augments Active Record's `find` method on models that have have been ini
## Limitations

* This is not security. ObfuscateId was created to lightly mask record id numbers for the casual user. If you need to really secure your database ids (hint, you probably don't), you need to use real encryption like AES.
* Works for up to a Billion database records. ObfuscateId simply maps every integer below one Billion to some other number below one Billion.
* Works for up to ten billion database records. ObfuscateId simply maps every integer below ten billion to some other number below ten billion.
* To properly generate obfuscated urls, make sure you trigger the model's `to_param` method by passing in the whole object rather than just the id; do this: `post_path(@post)` not this: `post_path(@post.id)`.
* Rails uses the real id rather than `to_param` in some places. A simple view-source on a form will often show the real id. This can be avoided by taking certain precautions.

9 changes: 7 additions & 2 deletions lib/obfuscate_id/run_scatter_swap.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
require './scatter_swap.rb'

# This file isn't really part of the library, its pretty much spike code..
#
# While developing this, I used this file to visualize what was going on with the numbers
#
# you can run it like this:
# You can uncomment various methods at the bottom and then run it like this:
#
# watch -n1 ruby run_scatter_swap.rb
#
# tweak the code a bit and see instant visual changes in the generated numbers

def visualize_scatter_and_unscatter
# change this number to experiment with different values
Expand Down Expand Up @@ -81,7 +85,8 @@ def visualize_spin
end
end
end
visualize_spin

#visualize_spin
#visualize_hash
#visualize_scatter_and_unscatter
#visualize_scatter
Expand Down
58 changes: 30 additions & 28 deletions lib/obfuscate_id/scatter_swap.rb
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
class ScatterSwap
# ScatterSwap is an integer hash function designed to have:
# - zero collisions ( http://en.wikipedia.org/wiki/Perfect_hash_function )
# - achieve avalanche ( http://en.wikipedia.org/wiki/Avalanche_effect )
# - reversable
# This is the hashing function behind ObfuscateId.
# https://github.com/namick/obfuscate_id
#
# Designing a hash function is a bit of a black art and
# being that I don't have math background, I must resort
# to this simplistic swaping and scattering of array elements.
#
# I welcome all improvments :-)
#
# We are working with a limited sequential set of input integers.
# The largest value that a Mysql INT type is 2147483647
# which is the same as 2 to the power of 31 minus 1
# After writing this and reading/learning some elemental hashing techniques,
# I realize this library is what is known as a Minimal perfect hash function:
# http://en.wikipedia.org/wiki/Perfect_hash_function#Minimal_perfect_hash_function
#
# That gives us more than 2 Billion records.. if you need more than
# that, you might look for a different solution.
# I welcome all improvements :-)
#
# We will start by zero padding the integer and turning it into an array.
# If you have some comments or suggestions, please contact me on github
# https://github.com/namick
#
# The key to creating a reversable hash must be that somehow the information is preserved
# in the new number and the reverse hash can use that to reproduce the original number.
#
# One such piece of information could be the sum of digits
# - nathan amick
#
#
# This library basically works for integers that can be expressed with 10 digits:
# This library is built for integers that can be expressed with 10 digits:
# It zero pads smaller numbers... so the number one is expressed with:
# 0000000001
# The biggest number it can deal with is:
# 9999999999
#
# Every number within the above range is mapped to another number in that range.
# Since we are working with a limited sequential set of input integers, 10 billion,
# this algorithm will suffice for simple id obfuscation for many web apps.
# The largest value that Ruby on Rails default id, Mysql INT type, is just over 2 billion (2147483647)
# which is the same as 2 to the power of 31 minus 1, but considerably less than 10 billion.
#
# ScatterSwap is an integer hash function designed to have:
# - zero collisions ( http://en.wikipedia.org/wiki/Perfect_hash_function )
# - achieve avalanche ( http://en.wikipedia.org/wiki/Avalanche_effect )
# - reversable
#
# We do that by combining two distinct strategies.
#
Expand All @@ -46,11 +48,12 @@ class ScatterSwap
# for each place in the 10 digit array; for this, we need a map so that we
# can reverse it.

# obfuscates an integer up to 10 digits in length
# Convience class method pointing to the instance method
def self.hash(plain_integer, spin = 0)
new(plain_integer, spin).hash
end

# Convience class method pointing to the instance method
def self.reverse_hash(hashed_integer, spin = 0)
new(hashed_integer, spin).reverse_hash
end
Expand All @@ -64,12 +67,14 @@ def initialize(original_integer, spin = 0)

attr_accessor :working_array

# obfuscates an integer up to 10 digits in length
def hash
swap
scatter
completed_string
end

# de-obfuscates an integer
def reverse_hash
unscatter
unswap
Expand All @@ -80,10 +85,6 @@ def completed_string
@working_array.join
end

def completed_integer
completed_string.to_i
end

# We want a unique map for each place in the original number
def swapper_map(index)
array = (0..9).to_a
Expand All @@ -92,20 +93,22 @@ def swapper_map(index)
end
end

# Using a unique map for each of the ten places,
# we swap out one number for another
def swap
@working_array = @working_array.collect.with_index do |digit, index|
swapper_map(index)[digit]
end
end


# Reverse swap
def unswap
@working_array = @working_array.collect.with_index do |digit, index|
swapper_map(index).rindex(digit)
end
end

# rearrange the order of each digit in a reversable way by using the
# Rearrange the order of each digit in a reversable way by using the
# sum of the digits (which doesn't change regardless of order)
# as a key to record how they were scattered
def scatter
Expand All @@ -115,6 +118,7 @@ def scatter
end
end

# Reverse the scatter
def unscatter
scattered_array = @working_array
sum_of_digits = scattered_array.inject(:+).to_i
Expand All @@ -127,10 +131,8 @@ def unscatter
end
end


# Add some spice so that different apps can have differently mapped hashes
def spin
@spin || 0
end


end
2 changes: 1 addition & 1 deletion lib/obfuscate_id/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ObfuscateId
VERSION = "0.0.1.alpha"
VERSION = "0.0.1"
end

0 comments on commit b2ddba0

Please sign in to comment.