obfuscated_identifier 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 847b96d3bdffdbc0780009f69509ca5ed1ed39f3
4
+ data.tar.gz: 89706dcf8cb664cf5dee90fb62ac5a9a32b185c1
5
+ SHA512:
6
+ metadata.gz: 26d146b0f8d593250e3fc19772f985bde82fbcee77fb60c9f24cfbbb27f6e07db2ceac71ad58f57e7d3a0f84f70f5a66fc32077062b0f1a3058096083d070cd5
7
+ data.tar.gz: 808e0a3ee1b77547bbb2611db90b8c40cb491e744b222c1d60c71c4a342f617417321fdf281c6bf334193af61c02c1b98748bd6676c0c929f55ea3234c58217b
data/.gitignore ADDED
@@ -0,0 +1,19 @@
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
18
+ .rspec
19
+ vendor/bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in obfusicated_identifier.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Steve Smith
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # Obfuscated Identifier
2
+
3
+ Hide your Rails primary key without the need for token generation and additional index space.
4
+
5
+ Obfuscate Identifier uses an obfuscation algorithm to generate a unique identifier for your
6
+ existing primary key. As long as you have the key that was used to create the identifier then you
7
+ can get back to the original primary key.
8
+
9
+ This removes the need for tricks like generating a random number and storing indexing it as the
10
+ primary key is still used to retrieve the object.
11
+
12
+ There are a huge number of options when creating a system like this here are some of the
13
+ considerations whilst creating this gem:
14
+
15
+ * Identifiers must be unique
16
+ * Identifiers must be reversible
17
+ * Identifiers should be consistent, repeat generation should create the same output
18
+ * Patterns within identifiers should not be 'obvious' (sequences should be avoided)
19
+ * The algorithm should not be overly complex
20
+ * The algorithm should 'relatively' computationally inexpensive
21
+
22
+ ### Notes:
23
+
24
+ Obfuscation is not encryption. It's important to note that this isn't really hiding anything,
25
+ if someone really wants to work out your primary key they probably can. This favors simplicity over
26
+ the quality of the identifier generated.
27
+
28
+ This was a very quick stab at an implementation. Pull requests and comments are hugely appreciated!
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ gem 'obfusicated_identifier'
35
+
36
+ And then execute:
37
+
38
+ $ bundle
39
+
40
+ Or install it yourself as:
41
+
42
+ $ gem install obfusicated_identifier
43
+
44
+ ## Usage
45
+
46
+ TODO: Write usage instructions here
47
+
48
+ ## Contributing
49
+
50
+ 1. Fork it
51
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module ObfuscatedIdentifier
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,57 @@
1
+ require "active_support/concern"
2
+ require "obfuscated_identifier/version"
3
+
4
+ module ObfuscatedIdentifier
5
+ extend ActiveSupport::Concern
6
+
7
+ def to_param
8
+ self.class.to_identifier(id)
9
+ end
10
+
11
+ module ClassMethods
12
+ attr_reader :identifier_length
13
+
14
+ def obfusicate_identifier(pattern, offset, length = 16)
15
+ @identifier_pattern = pattern
16
+ @identifier_offset = offset
17
+ @identifier_length = 16
18
+ end
19
+
20
+ def generate_identifier_pattern
21
+ %w{0 1 2 3 4 5 6 7 8 9 a b c d e}.shuffle
22
+ end
23
+
24
+ def from_param(value)
25
+ id = from_identifier(value)
26
+ find_by_id!(id)
27
+ end
28
+
29
+ def from_identifier(value)
30
+ counts = value.each_char.map { |c| @identifier_pattern.index(c.to_s) }.reverse
31
+
32
+ numbers = counts[0..-2].each_with_index.map do |count, index|
33
+ ((count - counts[index + 1]) - @identifier_offset) % @identifier_pattern.length
34
+ end + [(counts[-1] - @identifier_offset) % @identifier_pattern.length]
35
+
36
+ numbers.join('').to_i
37
+ end
38
+
39
+ def to_identifier(value)
40
+ padded_string = pad_number(value)
41
+
42
+ count = 0
43
+ counts = padded_string.reverse.each_char.map do |c|
44
+ count += (c.to_i + @identifier_offset)
45
+ count = count % @identifier_pattern.length
46
+ end
47
+
48
+ counts.map { |c| @identifier_pattern[c] }.join('')
49
+ end
50
+
51
+ protected
52
+
53
+ def pad_number(value)
54
+ sprintf("%0#{@identifier_length}d", value)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'obfuscated_identifier/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "obfuscated_identifier"
8
+ spec.version = ObfuscatedIdentifier::VERSION
9
+ spec.authors = ["Steve Smith"]
10
+ spec.email = ["github@scsworld.co.uk"]
11
+ spec.description = %q{Obfuscate your Rails primary key}
12
+ spec.summary = %q{Hide your Rails primary key without the need for token generation and additional index space.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "activesupport", "~> 4.0.0"
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec"
25
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+ require 'obfuscated_identifier'
3
+
4
+ class ObfuscatedIdentifierClass
5
+ include ObfuscatedIdentifier
6
+
7
+ obfusicate_identifier(
8
+ %w{2 7 3 e 6 9 1 8 b c 5 a 4 d 0},
9
+ 7,
10
+ 16
11
+ )
12
+ end
13
+
14
+ describe ObfuscatedIdentifier do
15
+ let(:klass) { ObfuscatedIdentifierClass }
16
+ let(:postgres_max_identifier) { (2**(4 * 8 - 1) - 1) }
17
+ let(:example_identifier) { 'b2801d946ae53c7b' }
18
+ let(:example_number) { 1 }
19
+
20
+ describe '#pad_number' do
21
+ it 'returns a string' do
22
+ expect(klass.send(:pad_number, 1)).to be_instance_of(String)
23
+ end
24
+
25
+ context 'when number is 1' do
26
+ it 'returns the number padded with 0s' do
27
+ expect(klass.send(:pad_number, 1)).to eq('0000000000000001')
28
+ end
29
+ end
30
+
31
+ context 'when number is greater than the padding' do
32
+ it 'returns the number as a string' do
33
+ expect(klass.send(:pad_number, 999_999_999_999_999_999)).to eq('999999999999999999')
34
+ end
35
+ end
36
+
37
+ context 'when number is the max identifier postgres int type allows' do
38
+ it 'returns the number as a string' do
39
+ expect(klass.send(:pad_number, postgres_max_identifier)).to eq('0000002147483647')
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#to_identifier' do
45
+ it 'returns a string' do
46
+ expect(klass.to_identifier(1)).to be_instance_of(String)
47
+ end
48
+
49
+ it 'returns a value with length LENGTH' do
50
+ expect(klass.to_identifier(1).length).to eq(klass.identifier_length)
51
+ end
52
+
53
+ it 'returns the expect identifier' do
54
+ expect(klass.to_identifier(1)).to eq(example_identifier)
55
+ end
56
+
57
+ it 'creates a reversable identifier' do
58
+ 100.times do
59
+ number = rand(0..postgres_max_identifier)
60
+ identifier = klass.to_identifier(number)
61
+ expect(klass.from_identifier(identifier)).to eq(number)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '#from_identifier' do
67
+ it 'returns a number' do
68
+ expect(klass.from_identifier(example_identifier)).to be_instance_of(Fixnum)
69
+ end
70
+
71
+ it 'returns the expected integer' do
72
+ expect(klass.from_identifier(example_identifier)).to eq(example_number)
73
+ end
74
+ end
75
+
76
+ describe 'generate_identifier_pattern' do
77
+ it 'returns 0-9a-f' do
78
+ klass.generate_identifier_pattern.each do |item|
79
+ expect(item).to match(/[a-f 0-9]/)
80
+ end
81
+ end
82
+
83
+ it 'returns each item only once' do
84
+ output = klass.generate_identifier_pattern
85
+ expect(output.uniq).to eq(output)
86
+ end
87
+
88
+ it 'generates a different pattern each time' do
89
+ output = klass.generate_identifier_pattern
90
+ expect(klass.generate_identifier_pattern).not_to eq(output)
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: obfuscated_identifier
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Steve Smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Obfuscate your Rails primary key
70
+ email:
71
+ - github@scsworld.co.uk
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - lib/obfuscated_identifier.rb
82
+ - lib/obfuscated_identifier/version.rb
83
+ - obfuscated_identifier.gemspec
84
+ - spec/obfuscated_identifier_spec.rb
85
+ - spec/spec_helper.rb
86
+ homepage: ''
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.2.0
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Hide your Rails primary key without the need for token generation and additional
110
+ index space.
111
+ test_files:
112
+ - spec/obfuscated_identifier_spec.rb
113
+ - spec/spec_helper.rb