integer-obfuscator 0.1.0
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.
- data/.document +3 -0
- data/.gitignore +4 -0
- data/.yardopts +1 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.md +46 -0
- data/Rakefile +16 -0
- data/integer-obfuscator.gemspec +26 -0
- data/lib/cipher/skip32.rb +134 -0
- data/lib/integer_obfuscator.rb +47 -0
- data/lib/integer_obfuscator/version.rb +3 -0
- data/skip32.c.md +128 -0
- data/test/helper.rb +5 -0
- data/test/test_integer_obfuscator.rb +42 -0
- data/test/test_skip32.rb +20 -0
- metadata +125 -0
data/.document
ADDED
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
ADDED
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2011 John Nishinaga and Pat Deegan, PhD & Associates, LLC.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Integer Obfuscator
|
2
|
+
|
3
|
+
This is a tool for obfuscating 32-bits integers. More specifically,
|
4
|
+
`IntegerObfuscator` will one-to-one transform a 32-bit integer to another
|
5
|
+
32-bit integer using a 32-bit block cipher based on SKIPJACK.
|
6
|
+
|
7
|
+
This is useful when you want to transform sequentially generated
|
8
|
+
IDs (e.g. database IDs) into integers that don't have an obvious ordering.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
gem install integer-obfuscator
|
13
|
+
|
14
|
+
## Example
|
15
|
+
|
16
|
+
require 'rubygems'
|
17
|
+
require 'integer_obfuscator'
|
18
|
+
|
19
|
+
c = IntegerObfuscator.new("my secret key")
|
20
|
+
c.obfuscate(1) # => 418026769
|
21
|
+
c.obfuscate(2) # => 1524067781
|
22
|
+
c.obfuscate(3) # => 1476269236
|
23
|
+
c.unobfuscate(418026769) # => 1
|
24
|
+
c.unobfuscate(1524067781) # => 2
|
25
|
+
c.unobfuscate(1476269236) # => 3
|
26
|
+
|
27
|
+
## Warnings
|
28
|
+
|
29
|
+
This code...
|
30
|
+
|
31
|
+
1. is not intended to be cryptographically secure.
|
32
|
+
3. is slow (i.e., pure Ruby implementation).
|
33
|
+
4. only handles integers up to 32-bits in size.
|
34
|
+
|
35
|
+
## References
|
36
|
+
|
37
|
+
This is based directly on the Perl Crypt::Skip32 module and the Greg Rose's
|
38
|
+
original C implementation.
|
39
|
+
|
40
|
+
* <http://search.cpan.org/~esh/Crypt-Skip32-0.15/lib/Crypt/Skip32.pm>
|
41
|
+
* <http://www.qualcomm.com.au/PublicationsDocs/skip32.c>
|
42
|
+
|
43
|
+
## Copyright and License
|
44
|
+
|
45
|
+
Copyright (c) 2010-2011 Pat Deegan, PhD & Associates, LLC. Released under
|
46
|
+
the MIT license. See the license file for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
require 'yard'
|
7
|
+
YARD::Rake::YardocTask.new
|
8
|
+
|
9
|
+
require "rake/testtask"
|
10
|
+
Rake::TestTask.new(:test) do |test|
|
11
|
+
test.libs << 'lib' << 'test'
|
12
|
+
test.pattern = 'test/**/test_*.rb'
|
13
|
+
test.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
task :default => :test
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "integer_obfuscator/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "integer-obfuscator"
|
7
|
+
s.version = IntegerObfuscator::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["John Nishinaga"]
|
10
|
+
s.email = ["jingoro@casa-z.org"]
|
11
|
+
s.homepage = "https://github.com/patdeegan/integer-obfuscator"
|
12
|
+
s.summary = "integer-obfuscator-#{IntegerObfuscator::VERSION}"
|
13
|
+
s.description = "Obfuscate 32-bit Integers using a 32-bit block cipher based on SKIPJACK"
|
14
|
+
|
15
|
+
s.rubyforge_project = "integer-obfuscator"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency 'yard'
|
23
|
+
s.add_development_dependency 'bluecloth'
|
24
|
+
s.add_development_dependency 'rspec'
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Cipher
|
2
|
+
|
3
|
+
# A 32-bit version of the SKIPJACK cipher. This interface is not intended to be
|
4
|
+
# compatible with the OpenSSL::Cipher modules.
|
5
|
+
class Skip32
|
6
|
+
|
7
|
+
class Error < RuntimeError
|
8
|
+
end
|
9
|
+
|
10
|
+
# @param key [String] the key
|
11
|
+
# @raise [Error] if `key` is too short
|
12
|
+
def initialize(key)
|
13
|
+
raise Error, "key length too short" if key.length < key_len
|
14
|
+
@key = key.unpack("C*")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Encrypts `block` and returns the result
|
18
|
+
# @return [String] the encrypted block
|
19
|
+
# @raise [Error] if `block` is too short
|
20
|
+
def encrypt(block)
|
21
|
+
buffer = unpack(block)
|
22
|
+
skip32(@key, buffer, true)
|
23
|
+
pack(buffer)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Decrypts `block` and returns the result
|
27
|
+
# @return [String] the decrypted block
|
28
|
+
# @raise [Error] if `block` is too short
|
29
|
+
def decrypt(block)
|
30
|
+
buffer = unpack(block)
|
31
|
+
skip32(@key, buffer, false)
|
32
|
+
pack(buffer)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a string representation of the object
|
36
|
+
# @return [String] a string representation of the object
|
37
|
+
def inspect
|
38
|
+
"#<Cipher::Skip32:#{object_id}>"
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the block size
|
42
|
+
# @return [Integer] the block size
|
43
|
+
def block_size
|
44
|
+
4
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the key length
|
48
|
+
# @return [Integer] the key length
|
49
|
+
def key_len
|
50
|
+
10
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# @param block [String] the block to unpack
|
56
|
+
# @return [Array] the resulting buffer
|
57
|
+
# @raise [Error] if `block` is too short
|
58
|
+
def unpack(block)
|
59
|
+
raise Error, "block length too short" if block.length < block_size
|
60
|
+
block.unpack("C*")
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param buffer [Array] the buffer to pack
|
64
|
+
# @return [String] the resulting block
|
65
|
+
def pack(buffer)
|
66
|
+
buffer.pack("C*")
|
67
|
+
end
|
68
|
+
|
69
|
+
# The Feistel table
|
70
|
+
FTABLE = [
|
71
|
+
0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9,
|
72
|
+
0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28,
|
73
|
+
0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53,
|
74
|
+
0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2,
|
75
|
+
0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8,
|
76
|
+
0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90,
|
77
|
+
0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76,
|
78
|
+
0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d,
|
79
|
+
0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18,
|
80
|
+
0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4,
|
81
|
+
0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40,
|
82
|
+
0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5,
|
83
|
+
0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2,
|
84
|
+
0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8,
|
85
|
+
0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac,
|
86
|
+
0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46
|
87
|
+
]
|
88
|
+
|
89
|
+
# A Ruby translation of the `skip32.c` `g` function.
|
90
|
+
# @see http://www.qualcomm.com.au/PublicationsDocs/skip32.c
|
91
|
+
def g(key, k, w)
|
92
|
+
g1 = (w>>8)&0xff
|
93
|
+
g2 = w&0xff
|
94
|
+
|
95
|
+
g3 = FTABLE[g2 ^ key[(4*k)%10]] ^ g1
|
96
|
+
g4 = FTABLE[g3 ^ key[(4*k+1)%10]] ^ g2
|
97
|
+
g5 = FTABLE[g4 ^ key[(4*k+2)%10]] ^ g3
|
98
|
+
g6 = FTABLE[g5 ^ key[(4*k+3)%10]] ^ g4
|
99
|
+
|
100
|
+
(g5<<8) + g6
|
101
|
+
end
|
102
|
+
|
103
|
+
# A Ruby translation of the `skip32.c` `skip32` function.
|
104
|
+
# @see http://www.qualcomm.com.au/PublicationsDocs/skip32.c
|
105
|
+
def skip32(key, buf, encrypt)
|
106
|
+
# sort out direction
|
107
|
+
if encrypt
|
108
|
+
kstep = 1; k = 0
|
109
|
+
else
|
110
|
+
kstep = -1; k = 23
|
111
|
+
end
|
112
|
+
|
113
|
+
# pack into words
|
114
|
+
wl = (buf[0] << 8) + buf[1]
|
115
|
+
wr = (buf[2] << 8) + buf[3]
|
116
|
+
|
117
|
+
# 24 feistel rounds, doubled up
|
118
|
+
1.upto(24/2) do
|
119
|
+
wr ^= g(key, k, wl) ^ k
|
120
|
+
k += kstep
|
121
|
+
wl ^= g(key, k, wr) ^ k
|
122
|
+
k += kstep
|
123
|
+
end
|
124
|
+
|
125
|
+
# implicitly swap halves while unpacking
|
126
|
+
buf[0] = wr >> 8; buf[1] = wr & 0xFF
|
127
|
+
buf[2] = wl >> 8; buf[3] = wl & 0xFF
|
128
|
+
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
|
132
|
+
end # class Skip32
|
133
|
+
|
134
|
+
end # module Cipher
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'cipher/skip32'
|
3
|
+
require 'integer_obfuscator/version'
|
4
|
+
|
5
|
+
# Obfuscates or unobfuscates 32-bit integers using a 32-bit block cipher based on SKIPJACK.
|
6
|
+
class IntegerObfuscator
|
7
|
+
|
8
|
+
class RangeError < ArgumentError
|
9
|
+
def initialize(i)
|
10
|
+
super("#{i.inspect} is not a 32-bit integer")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
MAX_SIZE = (2 ** 32) - 1
|
15
|
+
|
16
|
+
# Creates an obfuscator
|
17
|
+
# @param key [String] the key used to obfuscate/unobfuscate integers
|
18
|
+
def initialize(key)
|
19
|
+
shakey = Digest::SHA1.digest(key)[0...10]
|
20
|
+
@c = Cipher::Skip32.new(shakey)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Obfuscates an integer
|
24
|
+
# @param i [Integer] the integer to obfuscate
|
25
|
+
# @return [Integer] the obfuscated integer
|
26
|
+
# @raise [RangeError] if `i` is not a 32-bit integer
|
27
|
+
def obfuscate(i)
|
28
|
+
require_32bit_integer(i)
|
29
|
+
@c.encrypt([i].pack("I")).unpack("I").first
|
30
|
+
end
|
31
|
+
|
32
|
+
# Unobfuscates an integer
|
33
|
+
# @param i [Integer] the integer to unobfuscate
|
34
|
+
# @return [Integer] the unobfuscated integer
|
35
|
+
# @raise [RangeError] if `i` is not a 32-bit integer
|
36
|
+
def unobfuscate(i)
|
37
|
+
require_32bit_integer(i)
|
38
|
+
@c.decrypt([i].pack("I")).unpack("I").first
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def require_32bit_integer(i)
|
44
|
+
raise RangeError.new(i) if (i > MAX_SIZE || i < 0)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/skip32.c.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
From <http://www.qualcomm.com.au/PublicationsDocs/skip32.c>.
|
2
|
+
|
3
|
+
/*
|
4
|
+
SKIP32 -- 32 bit block cipher based on SKIPJACK.
|
5
|
+
Written by Greg Rose, QUALCOMM Australia, 1999/04/27.
|
6
|
+
|
7
|
+
In common: F-table, G-permutation, key schedule.
|
8
|
+
Different: 24 round feistel structure.
|
9
|
+
Based on: Unoptimized test implementation of SKIPJACK algorithm
|
10
|
+
Panu Rissanen <bande@lut.fi>
|
11
|
+
|
12
|
+
SKIPJACK and KEA Algorithm Specifications
|
13
|
+
Version 2.0
|
14
|
+
29 May 1998
|
15
|
+
|
16
|
+
Not copyright, no rights reserved.
|
17
|
+
*/
|
18
|
+
|
19
|
+
typedef unsigned char BYTE; /* 8 bits */
|
20
|
+
typedef unsigned short WORD; /* 16 bits */
|
21
|
+
|
22
|
+
const BYTE ftable[256] = {
|
23
|
+
0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9,
|
24
|
+
0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28,
|
25
|
+
0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53,
|
26
|
+
0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2,
|
27
|
+
0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8,
|
28
|
+
0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90,
|
29
|
+
0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76,
|
30
|
+
0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d,
|
31
|
+
0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18,
|
32
|
+
0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4,
|
33
|
+
0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40,
|
34
|
+
0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5,
|
35
|
+
0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2,
|
36
|
+
0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8,
|
37
|
+
0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac,
|
38
|
+
0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46
|
39
|
+
};
|
40
|
+
|
41
|
+
WORD
|
42
|
+
g(BYTE *key, int k, WORD w)
|
43
|
+
{
|
44
|
+
BYTE g1, g2, g3, g4, g5, g6;
|
45
|
+
|
46
|
+
g1 = (w>>8)&0xff;
|
47
|
+
g2 = w&0xff;
|
48
|
+
|
49
|
+
g3 = ftable[g2 ^ key[(4*k)%10]] ^ g1;
|
50
|
+
g4 = ftable[g3 ^ key[(4*k+1)%10]] ^ g2;
|
51
|
+
g5 = ftable[g4 ^ key[(4*k+2)%10]] ^ g3;
|
52
|
+
g6 = ftable[g5 ^ key[(4*k+3)%10]] ^ g4;
|
53
|
+
|
54
|
+
return ((g5<<8) + g6);
|
55
|
+
}
|
56
|
+
|
57
|
+
void
|
58
|
+
skip32(BYTE key[10], BYTE buf[4], int encrypt)
|
59
|
+
{
|
60
|
+
int k; /* round number */
|
61
|
+
int i; /* round counter */
|
62
|
+
int kstep;
|
63
|
+
WORD wl, wr;
|
64
|
+
|
65
|
+
/* sort out direction */
|
66
|
+
if (encrypt)
|
67
|
+
kstep = 1, k = 0;
|
68
|
+
else
|
69
|
+
kstep = -1, k = 23;
|
70
|
+
|
71
|
+
/* pack into words */
|
72
|
+
wl = (buf[0] << 8) + buf[1];
|
73
|
+
wr = (buf[2] << 8) + buf[3];
|
74
|
+
|
75
|
+
/* 24 feistel rounds, doubled up */
|
76
|
+
for (i = 0; i < 24/2; ++i) {
|
77
|
+
wr ^= g(key, k, wl) ^ k;
|
78
|
+
k += kstep;
|
79
|
+
wl ^= g(key, k, wr) ^ k;
|
80
|
+
k += kstep;
|
81
|
+
}
|
82
|
+
|
83
|
+
/* implicitly swap halves while unpacking */
|
84
|
+
buf[0] = wr >> 8; buf[1] = wr & 0xFF;
|
85
|
+
buf[2] = wl >> 8; buf[3] = wl & 0xFF;
|
86
|
+
}
|
87
|
+
|
88
|
+
#include <stdio.h>
|
89
|
+
int main(int ac, char *av[])
|
90
|
+
{
|
91
|
+
BYTE in[4] = { 0x33,0x22,0x11,0x00 };
|
92
|
+
BYTE key[10] = { 0x00,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11 };
|
93
|
+
int i, encrypt;
|
94
|
+
int bt;
|
95
|
+
|
96
|
+
if (ac == 1) {
|
97
|
+
skip32(key, in, 1);
|
98
|
+
printf("%02x%02x%02x%02x\n", in[0], in[1], in[2], in[3]);
|
99
|
+
if (in[0] != 0x81 || in[1] != 0x9d || in[2] != 0x5f || in[3] != 0x1f) {
|
100
|
+
printf("819d5f1f is the answer! Didn't encrypt correctly!\n");
|
101
|
+
return 1;
|
102
|
+
}
|
103
|
+
skip32(key, in, 0);
|
104
|
+
if (in[0] != 0x33 || in[1] != 0x22 || in[2] != 0x11 || in[3] != 0x00) {
|
105
|
+
printf("%02x%02x%02x%02x\n", in[0], in[1], in[2], in[3]);
|
106
|
+
printf("33221100 is the answer! Didn't decrypt correctly!\n");
|
107
|
+
return 1;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
else if (ac != 4) {
|
111
|
+
fprintf(stderr, "usage: %s e/d kkkkkkkkkkkkkkkkkkkk dddddddd\n", av[0]);
|
112
|
+
return 1;
|
113
|
+
}
|
114
|
+
else {
|
115
|
+
encrypt = av[1][0] == 'e';
|
116
|
+
for (i = 0; i < 10; ++i) {
|
117
|
+
sscanf(&av[2][i*2], "%02x", &bt);
|
118
|
+
key[i] = bt;
|
119
|
+
}
|
120
|
+
for (i = 0; i < 4; ++i) {
|
121
|
+
sscanf(&av[3][i*2], "%02x", &bt);
|
122
|
+
in[i] = bt;
|
123
|
+
}
|
124
|
+
skip32(key, in, encrypt);
|
125
|
+
printf("%02x%02x%02x%02x\n", in[0], in[1], in[2], in[3]);
|
126
|
+
}
|
127
|
+
return 0;
|
128
|
+
}
|
data/test/helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class TestIntegerObfuscator < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@c = IntegerObfuscator.new("my secret key")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_obfuscation
|
10
|
+
assert_equal 418026769, @c.obfuscate(1)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_unobfuscation
|
14
|
+
assert_equal 1, @c.unobfuscate(418026769)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_1000_obfuscation_deobfuscates
|
18
|
+
0.upto(1000) do |i|
|
19
|
+
assert_equal i, @c.unobfuscate(@c.obfuscate(i))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_does_not_allow_negative_values
|
24
|
+
assert_raises IntegerObfuscator::RangeError do
|
25
|
+
@c.obfuscate(-1)
|
26
|
+
end
|
27
|
+
assert_raises IntegerObfuscator::RangeError do
|
28
|
+
@c.unobfuscate(-1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_does_not_allow_big_integers
|
33
|
+
bigint = (2 ** 32) + 1
|
34
|
+
assert_raises IntegerObfuscator::RangeError do
|
35
|
+
@c.obfuscate(bigint)
|
36
|
+
end
|
37
|
+
assert_raises IntegerObfuscator::RangeError do
|
38
|
+
@c.unobfuscate(bigint)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/test/test_skip32.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
class TestSkip32 < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@key = [ 0x00,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11 ].pack("C*")
|
7
|
+
@c = Cipher::Skip32.new(@key)
|
8
|
+
@block = [ 0x33,0x22,0x11,0x00 ].pack("C*")
|
9
|
+
@enc_block = [ 0x81,0x9d,0x5f,0x1f ].pack("C*")
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_original_encrypt
|
13
|
+
assert_equal @enc_block, @c.encrypt(@block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_original_decrypt
|
17
|
+
assert_equal @block, @c.decrypt(@enc_block)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: integer-obfuscator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- John Nishinaga
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-03-22 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
prerelease: false
|
23
|
+
type: :development
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
name: yard
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
prerelease: false
|
37
|
+
type: :development
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
name: bluecloth
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
prerelease: false
|
51
|
+
type: :development
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
name: rspec
|
62
|
+
version_requirements: *id003
|
63
|
+
description: Obfuscate 32-bit Integers using a 32-bit block cipher based on SKIPJACK
|
64
|
+
email:
|
65
|
+
- jingoro@casa-z.org
|
66
|
+
executables: []
|
67
|
+
|
68
|
+
extensions: []
|
69
|
+
|
70
|
+
extra_rdoc_files: []
|
71
|
+
|
72
|
+
files:
|
73
|
+
- .document
|
74
|
+
- .gitignore
|
75
|
+
- .yardopts
|
76
|
+
- Gemfile
|
77
|
+
- MIT-LICENSE.txt
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- integer-obfuscator.gemspec
|
81
|
+
- lib/cipher/skip32.rb
|
82
|
+
- lib/integer_obfuscator.rb
|
83
|
+
- lib/integer_obfuscator/version.rb
|
84
|
+
- skip32.c.md
|
85
|
+
- test/helper.rb
|
86
|
+
- test/test_integer_obfuscator.rb
|
87
|
+
- test/test_skip32.rb
|
88
|
+
has_rdoc: true
|
89
|
+
homepage: https://github.com/patdeegan/integer-obfuscator
|
90
|
+
licenses: []
|
91
|
+
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project: integer-obfuscator
|
118
|
+
rubygems_version: 1.5.2
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: integer-obfuscator-0.1.0
|
122
|
+
test_files:
|
123
|
+
- test/helper.rb
|
124
|
+
- test/test_integer_obfuscator.rb
|
125
|
+
- test/test_skip32.rb
|