id_shuffler 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/id_shuffler/id_shuffler.c +25 -21
- data/lib/id_shuffler.rb +10 -6
- metadata +1 -1
@@ -15,25 +15,27 @@ static VALUE r_base32_shuffle(VALUE self, VALUE original_num, VALUE key_str) {
|
|
15
15
|
// initialize the feistel network and lfsr
|
16
16
|
unsigned int keypos, key_len;
|
17
17
|
unsigned long l, r, r_orig;
|
18
|
-
unsigned long
|
18
|
+
unsigned long lfsr, lfsr_check_bit, lfsr_out_bit, lfsr_round;
|
19
19
|
l = (original >> 15) & 32767;
|
20
20
|
r = original & 32767;
|
21
21
|
key_len = strlen(key);
|
22
22
|
// apply the feistel network in a loop over each char in key. the round
|
23
|
-
// function uses the key
|
24
|
-
// lfsr
|
23
|
+
// function uses the current key character as the taps mask for several
|
24
|
+
// iterations of a 32-bit lfsr
|
25
25
|
for (keypos = 0; keypos < key_len; keypos++) {
|
26
26
|
r_orig = r;
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
lfsr = r + 255; // ensure nonzero starting condition in the lfsr
|
28
|
+
for (lfsr_round = 0; lfsr_round < 15; lfsr_round++) {
|
29
|
+
lfsr_out_bit = 0;
|
30
|
+
for (lfsr_check_bit = 0; lfsr_check_bit < 8; lfsr_check_bit++) {
|
31
|
+
if ((key[keypos] & (1 << lfsr_check_bit)) > 0) {
|
32
|
+
lfsr_out_bit = lfsr_out_bit ^ ((lfsr & (1 << lfsr_check_bit)) >> lfsr_check_bit);
|
33
|
+
}
|
32
34
|
}
|
35
|
+
lfsr = (lfsr << 1) + lfsr_out_bit;
|
33
36
|
}
|
34
|
-
|
35
|
-
|
36
|
-
r = (l ^ lfsr_num);
|
37
|
+
lfsr = lfsr & 32767;
|
38
|
+
r = (l ^ lfsr);
|
37
39
|
l = r_orig;
|
38
40
|
}
|
39
41
|
// base32 encode the result
|
@@ -73,25 +75,27 @@ static VALUE r_base32_unshuffle(VALUE self, VALUE shuffled_str, VALUE key_str) {
|
|
73
75
|
return INT2NUM(-1);
|
74
76
|
}
|
75
77
|
}
|
76
|
-
//
|
78
|
+
// unwind
|
77
79
|
int keypos,key_len;
|
78
80
|
unsigned long l, r, l_orig;
|
79
|
-
unsigned long
|
81
|
+
unsigned long lfsr, lfsr_check_bit, lfsr_out_bit, lfsr_round;
|
80
82
|
l = (shuffled >> 15) & 32767;
|
81
83
|
r = shuffled & 32767;
|
82
84
|
key_len = strlen(key);
|
83
85
|
for (keypos = (key_len - 1); keypos >= 0; keypos--) {
|
84
86
|
l_orig = l;
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
lfsr = l + 255;
|
88
|
+
for (lfsr_round = 0; lfsr_round < 15; lfsr_round++) {
|
89
|
+
lfsr_out_bit = 0;
|
90
|
+
for (lfsr_check_bit = 0; lfsr_check_bit < 8; lfsr_check_bit++) {
|
91
|
+
if ((key[keypos] & (1 << lfsr_check_bit)) > 0) {
|
92
|
+
lfsr_out_bit = lfsr_out_bit ^ ((lfsr & (1 << lfsr_check_bit)) >> lfsr_check_bit);
|
93
|
+
}
|
90
94
|
}
|
95
|
+
lfsr = (lfsr << 1) + lfsr_out_bit;
|
91
96
|
}
|
92
|
-
|
93
|
-
|
94
|
-
l = (r ^ lfsr_num);
|
97
|
+
lfsr = lfsr & 32767;
|
98
|
+
l = (r ^ lfsr);
|
95
99
|
r = l_orig;
|
96
100
|
}
|
97
101
|
// return the resulting original number as a ruby fixnum
|
data/lib/id_shuffler.rb
CHANGED
@@ -17,6 +17,10 @@ class IdShuffler
|
|
17
17
|
@key = Digest::MD5.digest(key)
|
18
18
|
end
|
19
19
|
|
20
|
+
# note the c extension defines the two class methods:
|
21
|
+
# - shuffle_with_raw_key
|
22
|
+
# - unshuffle_with_raw_key
|
23
|
+
|
20
24
|
def shuffle(i)
|
21
25
|
self.class.shuffle_with_raw_key(i.to_i, @key)
|
22
26
|
end
|
@@ -25,16 +29,16 @@ class IdShuffler
|
|
25
29
|
self.class.unshuffle_with_raw_key(s.to_s, @key)
|
26
30
|
end
|
27
31
|
|
32
|
+
# these class methods are here for convenience but they are slower because the
|
33
|
+
# md5 is computed each time. better to use an instance with an initialized
|
34
|
+
# key.
|
35
|
+
|
28
36
|
def self.shuffle(i, key)
|
29
|
-
|
30
|
-
@keycache[key] ||= Digest::MD5.digest(key)
|
31
|
-
shuffle_with_raw_key(i.to_i, @keycache[key])
|
37
|
+
shuffle_with_raw_key(i.to_i, Digest::MD5.digest(key))
|
32
38
|
end
|
33
39
|
|
34
40
|
def self.unshuffle(s, key)
|
35
|
-
|
36
|
-
@keycache[key] ||= Digest::MD5.digest(key)
|
37
|
-
unshuffle_with_raw_key(s.to_s, @keycache[key])
|
41
|
+
unshuffle_with_raw_key(s.to_s, Digest::MD5.digest(key))
|
38
42
|
end
|
39
43
|
|
40
44
|
end
|