hashid 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bitswitch.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Kelly Becker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # HashId
2
+
3
+ HashId lets you hide your database ids with on the spot generated hashes. The hases will be valid 100% of the time unless you change the salt this can also be used to create confirmation codes or tracking numbers.
4
+
5
+ ## Installing BitSwitch
6
+
7
+ You can install HashId with [RubyGems](https://rubygems.org/gems/hashid).
8
+
9
+ `gem install hashid` or `gem 'hashid'`
10
+
11
+ ## Contributing to BitSwitch
12
+
13
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
14
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
15
+ * Fork the project.
16
+ * Start a feature/bugfix branch.
17
+ * Commit and push until you are happy with your contribution.
18
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
19
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
20
+
21
+ ## Todo
22
+
23
+ * Write some documentation
24
+
25
+ ## Copyright
26
+
27
+ Copyright (c) 2012 Kelly Becker. See LICENSE.txt for
28
+ further details.
29
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/hashid.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hashid/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "hashid"
8
+ gem.version = KellyLSB::HashId::VERSION
9
+ gem.authors = ["Kelly Becker"]
10
+ gem.email = ["kellylsbkr@gmail.com"]
11
+ gem.description = "With HashId you can hide your actual page ids with on the spot randomly generated hashes."
12
+ gem.summary = "HashId lets you hide your databse ids with on the spot generated hashes."
13
+ gem.homepage = "http://kellybecker.me"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
data/lib/hashid.rb ADDED
@@ -0,0 +1,177 @@
1
+ class HashId
2
+ class Error < StandardError; end
3
+
4
+ def initialize(salt = nil)
5
+ @salt = salt || 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
6
+
7
+ @letters = [
8
+ 'P0MVLWNTZD',
9
+ 'UE58X2VSCT',
10
+ '43Z0Y9AQLS',
11
+ 'V5Q1P4E8L9',
12
+ 'MOIRZCWXED',
13
+ '7NBYXCZU9R',
14
+ 'G2S90I84MC',
15
+ 'TQAMIWH4ZC',
16
+ 'POERHBYA1F',
17
+ 'XKO20UB3IL',
18
+ 'Y0NTH78VSO',
19
+ 'P4DE6VUZLK',
20
+ '9OKN2JLQGI',
21
+ '61UTFSN0BR',
22
+ 'R7ZAHJVGE9',
23
+ 'ADHIZ5WNUQ',
24
+ 'Z9SPX2OQI5',
25
+ 'V7YFEU4PTJ',
26
+ 'YZVFD6UXNG',
27
+ 'VH8UDLCE93',
28
+ 'W0H5GMTFZK',
29
+ 'GXE6CT2VOP',
30
+ 'QH2FLZOM9V',
31
+ 'MBGHIF78PU',
32
+ 'MHS04FY8L7',
33
+ 'E95IGRSMZ1',
34
+ 'MN8AILRB95',
35
+ 'S7JVO4EHCD',
36
+ 'GT01ZPLVUA',
37
+ '9OKN2JLQGI',
38
+ 'DUF24AGTSN',
39
+ '4ASPNFJ2BR',
40
+ 'OR465YEXQV',
41
+ 'DUF24AGTSN',
42
+ 'M78PCRAGKS',
43
+ 'D8LVQSKA7U'
44
+ ]
45
+
46
+ @indexes = [
47
+ [0,0],
48
+ [0,1],
49
+ [1,0],
50
+ [2,0],
51
+ [0,2],
52
+ [1,1],
53
+ [2,1],
54
+ [1,2]
55
+ ]
56
+ end
57
+
58
+ def self.generate_salt
59
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'.split(//).shuffle.join('')
60
+ end
61
+
62
+ def encrypt(string, len = 8)
63
+
64
+ # Require a fixnum for the encryption process
65
+ raise Error, 'HashID.encrypt expected a Fixnum as its argument' unless string.is_a?(Fixnum)
66
+
67
+ # Require a fixnum for the encryption process
68
+ raise Error, 'HashID.encrypt must have a length of no less then 6' unless string.is_a?(Fixnum)
69
+
70
+ # Prep the string for encryption
71
+ string = string.to_s.rjust(len, '0')
72
+
73
+ # Get the salt ids to use
74
+ saltids = Array.new
75
+ random = [*0..35].shuffle
76
+ 3.times{saltids<<random.shift}
77
+
78
+ # Get the letters cooresponding to the salts
79
+ salts = saltids.collect{|x|@letters[x]}
80
+
81
+ # Go ahead and convert the numbers into the new format
82
+ i=2;string=string.split(//).collect{|x|i==2?i=0:i+=1;salts[i][x.to_i,1]}.join('')
83
+
84
+ # Turn the salt ids into their letter forms
85
+ saltids.collect!{|x|@salt[x,1]}
86
+
87
+ # Get the index id and the indexes
88
+ indexid = [*0..7].shuffle.first
89
+ injections = @indexes[indexid]
90
+
91
+ # Inject the indexes and index id
92
+ string.insert(injections.first, saltids[0])
93
+ string.insert(string.length - injections.last, saltids[1])
94
+ string << saltids[2] + @salt[indexid,1]
95
+ end
96
+
97
+ def decrypt(string)
98
+
99
+ # Require a string for the decryption process
100
+ raise Error, 'HashID.decrypt expected a String as its argument' unless string.is_a?(String)
101
+
102
+ # Prep the string for decryption
103
+ string = string.upcase.gsub(/[^A-Z0-9]+/, '').split(//)
104
+
105
+ # Require no less then 8 characters
106
+ raise Error, 'A minimum of 8 characters is required for decryption' if string.length < 8
107
+
108
+ begin
109
+ # Get the indexes and index id
110
+ indexid = @salt.index(string.pop)
111
+ injections = @indexes[indexid]
112
+
113
+ # Go ahead and locate the salts
114
+ saltids = [string.pop]
115
+ saltids << string.slice!(string.length - 1 - injections.last)
116
+ saltids << string.slice!(injections.first)
117
+
118
+ # Go ahead and reverse and determine the salt ids
119
+ saltids = saltids.reverse.collect{|x|@salt.index(x)}
120
+
121
+ # Get the letters cooresponding to the salts
122
+ salts = saltids.collect{|x|@letters[x]}
123
+
124
+ # Go ahead and convert the alphanumeric id back into numbers
125
+ i=2;string=string.collect{|x|i==2?i=0:i+=1;salts[i].index(x)}.join('')
126
+
127
+ # Return the integer
128
+ return string.to_i
129
+ rescue
130
+ raise Error, 'The ID provided was not decryptable'
131
+ end
132
+ end
133
+ end
134
+
135
+ # Convert Fixnum to HashId (String)
136
+ class Fixnum
137
+ def to_hashid(salt = nil)
138
+ HashId.new(salt).encrypt(self)
139
+ end
140
+ end
141
+
142
+ # Convert HashId (String) to Fixnum
143
+ class String
144
+ def from_hashid(salt = nil)
145
+ HashId.new(salt).decrypt(self)
146
+ end
147
+ end
148
+
149
+ # Rails 3 Extension
150
+ if defined? ActiveRecord::Base
151
+ module KellyLSB
152
+ module HashId
153
+ extend ActiveSupport::Concern
154
+
155
+ module ClassMethods
156
+ def hashid(salt)
157
+ send(:include, Module.new {
158
+ send(:define_method, :id) do |*args|
159
+ _id = read_attribute(:id)
160
+ return _id unless _id.respond_to?(:to_hashid)
161
+ _id.to_hashid(salt).parameterize
162
+ end
163
+ })
164
+
165
+ send(:extend, Module.new {
166
+ send(:define_method, :find_by_hashid) do |hashid|
167
+ hashid = hashid.from_hashid(salt) if hashid.is_a?(String)
168
+ find(hashid)
169
+ end
170
+ })
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ ActiveRecord::Base.send(:include, KellyLSB::HashId)
177
+ end
@@ -0,0 +1,5 @@
1
+ module KellyLSB
2
+ module HashId
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hashid
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kelly Becker
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: With HashId you can hide your actual page ids with on the spot randomly
15
+ generated hashes.
16
+ email:
17
+ - kellylsbkr@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - hashid.gemspec
28
+ - lib/hashid.rb
29
+ - lib/hashid/version.rb
30
+ homepage: http://kellybecker.me
31
+ licenses: []
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 1.8.23
51
+ signing_key:
52
+ specification_version: 3
53
+ summary: HashId lets you hide your databse ids with on the spot generated hashes.
54
+ test_files: []