ope-rb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('openssl')
4
+ have_header("openssl/ssl.h")
5
+ have_library("ssl", "SSLv23_method")
6
+ create_makefile('ope/native')
@@ -0,0 +1,311 @@
1
+ #include <ruby.h>
2
+ #include <math.h>
3
+ #include <openssl/rand.h>
4
+
5
+ /*
6
+ * Helper methods from Mathlib : A C Library of Special Functions
7
+ * Copyright (C) 2005 The R Foundation, released under the GPL.
8
+ */
9
+ static double afc(int i)
10
+ {
11
+ static const double al[9] =
12
+ {
13
+ 0.0,
14
+ 0.0,/*ln(0!)=ln(1)*/
15
+ 0.0,/*ln(1!)=ln(1)*/
16
+ 0.69314718055994530941723212145817,/*ln(2) */
17
+ 1.79175946922805500081247735838070,/*ln(6) */
18
+ 3.17805383034794561964694160129705,/*ln(24)*/
19
+ 4.78749174278204599424770093452324,
20
+ 6.57925121201010099506017829290394,
21
+ 8.52516136106541430016553103634712
22
+ /*, 10.60460290274525022841722740072165*/
23
+ };
24
+ double di, value;
25
+
26
+ if (i < 0) {
27
+ printf(("rhyper.c: afc(i), i=%d < 0 -- SHOULD NOT HAPPEN!\n"),
28
+ i);
29
+ return -1;/* unreached (Wall) */
30
+ } else if (i <= 7) {
31
+ value = al[i + 1];
32
+ } else {
33
+ di = i;
34
+ value = (di + 0.5) * log(di) - di + 0.08333333333333 / di
35
+ - 0.00277777777777 / di / di / di + 0.9189385332;
36
+ }
37
+ return value;
38
+ }
39
+
40
+ static int imax2(int x, int y) {
41
+ return (x < y) ? y : x;
42
+ }
43
+
44
+ static int imin2(int x, int y) {
45
+ return (x < y) ? x : y;
46
+ }
47
+
48
+ static VALUE ope_rb;
49
+ static VALUE ope_rb_hgd;
50
+
51
+ static VALUE ope_rb_rhyper(VALUE self, VALUE rbNn1in, VALUE rbNn2in, VALUE rbKkin, VALUE rbSeed) {
52
+
53
+ double nn1in, nn2in, kkin;
54
+
55
+ static const double con = 57.56462733;
56
+ static const double deltal = 0.0078;
57
+ static const double deltau = 0.0034;
58
+ static const double scale = 1e25;
59
+
60
+ int nn1, nn2, kk;
61
+ int i, ix;
62
+ int reject, setup1, setup2;
63
+
64
+ double e, f, g, p, r, t, u, v, y;
65
+ double de, dg, dr, ds, dt, gl, gu, nk, nm, ub;
66
+ double xk, xm, xn, y1, ym, yn, yk, alv;
67
+
68
+ static int ks = -1;
69
+ static int n1s = -1, n2s = -1;
70
+
71
+ static int k, m;
72
+ static int minjx, maxjx, n1, n2;
73
+
74
+ static double a, d, s, w;
75
+ static double tn, xl, xr, kl, kr, lamdl, lamdr, p1, p2, p3;
76
+
77
+ unsigned char* seed;
78
+ int seedLen;
79
+
80
+ nn1in = NUM2DBL(rbNn1in);
81
+ nn2in = NUM2DBL(rbNn2in);
82
+ kkin = NUM2DBL(rbKkin);
83
+
84
+ StringValue(rbSeed);
85
+ seed = (unsigned char*) RSTRING_PTR(rbSeed);
86
+ seedLen = RSTRING_LEN(rbSeed);
87
+ RAND_seed(seed, seedLen);
88
+
89
+ if(!isfinite(nn1in) || !isfinite(nn2in) || !isfinite(kkin))
90
+ return -1;
91
+
92
+ nn1 = (int) nn1in;
93
+ nn2 = (int) nn2in;
94
+ kk = (int) kkin;
95
+
96
+ if (nn1 < 0 || nn2 < 0 || kk < 0 || kk > nn1 + nn2) {
97
+ //rb_raise(rb_eRuntimeError, 'Incorrect arguments to HGD');
98
+ return INT2NUM(-2);
99
+ }
100
+
101
+ reject = 1;
102
+ if (nn1 != n1s || nn2 != n2s) {
103
+ setup1 = 1; setup2 = 1;
104
+ } else if (kk != ks) {
105
+ setup1 = 0; setup2 = 1;
106
+ } else {
107
+ setup1 = 0; setup2 = 0;
108
+ }
109
+ if (setup1) {
110
+ n1s = nn1;
111
+ n2s = nn2;
112
+ tn = nn1 + nn2;
113
+ if (nn1 <= nn2) {
114
+ n1 = nn1;
115
+ n2 = nn2;
116
+ } else {
117
+ n1 = nn2;
118
+ n2 = nn1;
119
+ }
120
+ }
121
+ if (setup2) {
122
+ ks = kk;
123
+ if (kk + kk >= tn) {
124
+ k = (int)(tn - kk);
125
+ } else {
126
+ k = kk;
127
+ }
128
+ }
129
+ if (setup1 || setup2) {
130
+ m = (int) ((k + 1.0) * (n1 + 1.0) / (tn + 2.0));
131
+ minjx = imax2(0, k - n2);
132
+ maxjx = imin2(n1, k);
133
+ }
134
+
135
+ if (minjx == maxjx) {
136
+ ix = maxjx;
137
+
138
+ if (kk + kk >= tn) {
139
+ if (nn1 > nn2) {
140
+ ix = kk - nn2 + ix;
141
+ } else {
142
+ ix = nn1 - ix;
143
+ }
144
+ } else {
145
+ if (nn1 > nn2)
146
+ ix = kk - ix;
147
+ }
148
+
149
+ return DBL2NUM(ix);
150
+
151
+ } else if (m - minjx < 10) {
152
+ if (setup1 || setup2) {
153
+ if (k < n2) {
154
+ w = exp(con + afc(n2) + afc(n1 + n2 - k)
155
+ - afc(n2 - k) - afc(n1 + n2));
156
+ } else {
157
+ w = exp(con + afc(n1) + afc(k)
158
+ - afc(k - n2) - afc(n1 + n2));
159
+ }
160
+ }
161
+ L10:
162
+ p = w;
163
+ ix = minjx;
164
+ u = unif_rand(seed, seedLen) * scale;
165
+ L20:
166
+ if (u > p) {
167
+ u -= p;
168
+ p *= (n1 - ix) * (k - ix);
169
+ ix++;
170
+ p = p / ix / (n2 - k + ix);
171
+ if (ix > maxjx)
172
+ goto L10;
173
+ goto L20;
174
+ }
175
+ } else {
176
+
177
+ if (setup1 || setup2) {
178
+ s = sqrt((tn - k) * k * n1 * n2 / (tn - 1) / tn / tn);
179
+
180
+ d = (int) (1.5 * s) + .5;
181
+ xl = m - d + .5;
182
+ xr = m + d + .5;
183
+ a = afc(m) + afc(n1 - m) + afc(k - m) + afc(n2 - k + m);
184
+ kl = exp(a - afc((int) (xl)) - afc((int) (n1 - xl))
185
+ - afc((int) (k - xl))
186
+ - afc((int) (n2 - k + xl)));
187
+ kr = exp(a - afc((int) (xr - 1))
188
+ - afc((int) (n1 - xr + 1))
189
+ - afc((int) (k - xr + 1))
190
+ - afc((int) (n2 - k + xr - 1)));
191
+ lamdl = -log(xl * (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1));
192
+ lamdr = -log((n1 - xr + 1) * (k - xr + 1) / xr / (n2 - k + xr));
193
+ p1 = d + d;
194
+ p2 = p1 + kl / lamdl;
195
+ p3 = p2 + kr / lamdr;
196
+ }
197
+ L30:
198
+ u = unif_rand(seed, seedLen) * p3;
199
+ v = unif_rand(seed, seedLen);
200
+ if (u < p1) {
201
+ ix = (int) (xl + u);
202
+ } else if (u <= p2) {
203
+ ix = (int) (xl + log(v) / lamdl);
204
+ if (ix < minjx)
205
+ goto L30;
206
+ v = v * (u - p1) * lamdl;
207
+ } else {
208
+ ix = (int) (xr - log(v) / lamdr);
209
+ if (ix > maxjx)
210
+ goto L30;
211
+ v = v * (u - p2) * lamdr;
212
+ }
213
+
214
+ if (m < 100 || ix <= 50) {
215
+ f = 1.0;
216
+ if (m < ix) {
217
+ for (i = m + 1; i <= ix; i++)
218
+ f = f * (n1 - i + 1) * (k - i + 1) / (n2 - k + i) / i;
219
+ } else if (m > ix) {
220
+ for (i = ix + 1; i <= m; i++)
221
+ f = f * i * (n2 - k + i) / (n1 - i + 1) / (k - i + 1);
222
+ }
223
+ if (v <= f) {
224
+ reject = 0;
225
+ }
226
+ } else {
227
+ /* squeeze using upper and lower bounds */
228
+ y = ix;
229
+ y1 = y + 1.0;
230
+ ym = y - m;
231
+ yn = n1 - y + 1.0;
232
+ yk = k - y + 1.0;
233
+ nk = n2 - k + y1;
234
+ r = -ym / y1;
235
+ s = ym / yn;
236
+ t = ym / yk;
237
+ e = -ym / nk;
238
+ g = yn * yk / (y1 * nk) - 1.0;
239
+ dg = 1.0;
240
+ if (g < 0.0)
241
+ dg = 1.0 + g;
242
+ gu = g * (1.0 + g * (-0.5 + g / 3.0));
243
+ gl = gu - .25 * (g * g * g * g) / dg;
244
+ xm = m + 0.5;
245
+ xn = n1 - m + 0.5;
246
+ xk = k - m + 0.5;
247
+ nm = n2 - k + xm;
248
+ ub = y * gu - m * gl + deltau
249
+ + xm * r * (1. + r * (-0.5 + r / 3.0))
250
+ + xn * s * (1. + s * (-0.5 + s / 3.0))
251
+ + xk * t * (1. + t * (-0.5 + t / 3.0))
252
+ + nm * e * (1. + e * (-0.5 + e / 3.0));
253
+ alv = log(v);
254
+ if (alv > ub) {
255
+ reject = 1;
256
+ } else {
257
+ dr = xm * (r * r * r * r);
258
+ if (r < 0.0)
259
+ dr /= (1.0 + r);
260
+ ds = xn * (s * s * s * s);
261
+ if (s < 0.0)
262
+ ds /= (1.0 + s);
263
+ dt = xk * (t * t * t * t);
264
+ if (t < 0.0)
265
+ dt /= (1.0 + t);
266
+ de = nm * (e * e * e * e);
267
+ if (e < 0.0)
268
+ de /= (1.0 + e);
269
+ if (alv < ub - 0.25 * (dr + ds + dt + de)
270
+ + (y + m) * (gl - gu) - deltal) {
271
+ reject = 0;
272
+ }
273
+ else {
274
+ if (alv <= (a - afc(ix) - afc(n1 - ix)
275
+ - afc(k - ix) - afc(n2 - k + ix))) {
276
+ reject = 0;
277
+ } else {
278
+ reject = 1;
279
+ }
280
+ }
281
+ }
282
+ }
283
+ if (reject)
284
+ goto L30;
285
+ }
286
+
287
+ if (kk + kk >= tn) {
288
+ if (nn1 > nn2) {
289
+ ix = kk - nn2 + ix;
290
+ } else {
291
+ ix = nn1 - ix;
292
+ }
293
+ } else {
294
+ if (nn1 > nn2)
295
+ ix = kk - ix;
296
+ }
297
+
298
+ return DBL2NUM(ix);
299
+
300
+ }
301
+
302
+ void Init_native(void) {
303
+
304
+ ope_rb = rb_define_module("OPE");
305
+
306
+ ope_rb_hgd = rb_define_class_under(ope_rb, "HGD", rb_cObject);
307
+ rb_define_singleton_method(ope_rb_hgd, "rhyper_native", ope_rb_rhyper, 4);
308
+
309
+ return;
310
+
311
+ }
@@ -0,0 +1,155 @@
1
+ require 'ope-rb/native'
2
+ require 'ope-rb/version'
3
+ require 'ope-rb/prng'
4
+ require 'ope-rb/hgd'
5
+ require 'ope-rb/crypto'
6
+ require 'ope-rb/errors'
7
+
8
+ module OPE
9
+
10
+ class Cipher
11
+
12
+ OPE_KEY_SIZE = 128
13
+
14
+ include Crypto
15
+
16
+ def initialize(key, pt_len = 8, ct_len = 16)
17
+
18
+ check_key_size(key)
19
+
20
+ @key, @pt_len, @ct_len =
21
+ key, pt_len * 8, ct_len * 8
22
+
23
+ create_cipher
24
+
25
+ end
26
+
27
+ def check_key_size(key)
28
+
29
+ valid = key.bytesize * 8 == OPE_KEY_SIZE
30
+ raise Errors::KeySizeError unless valid
31
+
32
+ end
33
+
34
+ def sample_hgd(lo_d, hi_d, lo_r, hi_r, y, coins)
35
+
36
+ wb, bp = hi_d - lo_d + 1, y - lo_r
37
+ bb = hi_r - lo_r + 1 - wb
38
+
39
+ unless wb > 0 && bb >= 0 && y >= lo_r && y <= hi_r
40
+ raise Errors::HGDParameterError
41
+ end
42
+
43
+ prec = (hi_r - lo_r + 1).size * 8 + 10
44
+
45
+ lo_d + HGD.rhyper(bp, wb, bb, coins, prec)
46
+
47
+ end
48
+
49
+ def tape_gen(lo_d, hi_d, y, desired_no_bits)
50
+
51
+ if desired_no_bits % 8 != 0
52
+ raise Errors::NumBitsError
53
+ elsif (desired_bytes = desired_no_bits / 8) > 16
54
+ raise Errors::DesiredBytesError
55
+ end
56
+
57
+ digest = hash_concat(lo_d, hi_d, y)
58
+ seed = get_seed(digest, desired_bytes)
59
+
60
+ end
61
+
62
+ def encrypt(m)
63
+
64
+ lo_d, hi_d = 0, (1 << @pt_len) - 1
65
+ lo_r, hi_r = 0, (1 << @ct_len) - 1
66
+
67
+ encrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
68
+
69
+ end
70
+
71
+ def decrypt(m)
72
+
73
+ lo_d, hi_d = 0, (1 << @pt_len) - 1
74
+ lo_r, hi_r = 0, (1 << @ct_len) - 1
75
+
76
+ decrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
77
+
78
+ end
79
+
80
+ private
81
+
82
+ def get_seed(digest, desired_bytes)
83
+
84
+ # Encrypt the hash using the cipher
85
+ seed = cipher_encrypt(digest)
86
+
87
+ # Take only the desired no of bytes
88
+ seed = seed.byteslice(0, desired_bytes)
89
+
90
+ # Convert the seed to a Bignum
91
+ seed.unpack('H*')[0].hex
92
+
93
+ end
94
+
95
+ def encrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
96
+
97
+ m2, n = hi_d - lo_d + 1, hi_r - lo_r + 1
98
+ d, r = lo_d - 1, lo_r - 1; y = r + (n + 1) / 2
99
+
100
+ raise Errors::IncorrectMValueError unless m2 > 0
101
+
102
+ coins = nil
103
+
104
+ if m2 == 1
105
+
106
+ coins = tape_gen(lo_d, hi_d, m, @ct_len)
107
+ return lo_r + (coins % n)
108
+
109
+ end
110
+
111
+ coins = tape_gen(lo_d, hi_d, y, @pt_len)
112
+
113
+ x = sample_hgd(lo_d, hi_d, lo_r, hi_r, y, coins)
114
+
115
+ lo_d, hi_d = *((m <= x) ? [d + 1, x] : [x + 1, d + m2])
116
+ lo_r, hi_r = *((m <= x) ? [r + 1, y] : [y + 1, r + n])
117
+
118
+ encrypt_recurse(lo_d, hi_d, lo_r, hi_r, m)
119
+
120
+ end
121
+
122
+ def decrypt_recurse(lo_d, hi_d, lo_r, hi_r, c)
123
+
124
+ m2, n = hi_d - lo_d + 1, hi_r - lo_r + 1
125
+ d, r = lo_d - 1, lo_r - 1; y = r + (n + 1) / 2
126
+
127
+ raise Errors::IncorrectMValueError unless m2 > 0
128
+
129
+ if m2 == 1
130
+
131
+ m = lo_d.to_i
132
+
133
+ coins = tape_gen(lo_d, hi_d, m, @ct_len)
134
+ w = lo_r + coins % n
135
+
136
+ return m.to_i if w == c
137
+
138
+ raise Errors::BadDecryptError
139
+
140
+ end
141
+
142
+ coins = tape_gen(lo_d, hi_d, y, @pt_len)
143
+
144
+ x = sample_hgd(lo_d, hi_d, lo_r, hi_r, y, coins)
145
+
146
+ lo_d, hi_d = *((c <= y) ? [d + 1, x] : [x + 1, d + m2])
147
+ lo_r, hi_r = *((c <= y) ? [r + 1, y] : [y + 1, r + n])
148
+
149
+ decrypt_recurse(lo_d, hi_d, lo_r, hi_r, c)
150
+
151
+ end
152
+
153
+ end
154
+
155
+ end
@@ -0,0 +1,33 @@
1
+ module OPE
2
+
3
+ module Crypto
4
+
5
+ def hash_concat(*args)
6
+
7
+ lens = args.map { |arg| [1].pack("L") }
8
+ hash((lens + args).join(''))
9
+
10
+ end
11
+
12
+ def hash(data)
13
+
14
+ OpenSSL::Digest::SHA256.digest(data)
15
+
16
+ end
17
+
18
+ def create_cipher
19
+
20
+ @cipher = OpenSSL::Cipher::AES.new(128, :ECB)
21
+ @cipher.encrypt; @cipher.key = @key
22
+
23
+ end
24
+
25
+ def cipher_encrypt(data)
26
+
27
+ @cipher.update(data) + @cipher.final
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,55 @@
1
+ module OPE
2
+
3
+ module Errors
4
+
5
+ class KeySizeError < StandardError
6
+
7
+ def initialize
8
+ super('Incorrect key size')
9
+ end
10
+
11
+ end
12
+
13
+ class HGDParameterError < StandardError
14
+
15
+ def initialize
16
+ super('Corrupt HGD parameters')
17
+ end
18
+
19
+ end
20
+
21
+ class NumBitsError < StandardError
22
+
23
+ def initialize
24
+ super('Desired no bits not a multiple of 8')
25
+ end
26
+
27
+ end
28
+
29
+ class DesiredBytesError < StandardError
30
+
31
+ def initialize
32
+ super('Only 64-bit output is supported for now')
33
+ end
34
+
35
+ end
36
+
37
+ class IncorrectMValueError < StandardError
38
+
39
+ def initialize
40
+ super('M should not be less than or equal to 0')
41
+ end
42
+
43
+ end
44
+
45
+ class BadDecryptError < StandardError
46
+
47
+ def initialize
48
+ super('Decryption failed')
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,267 @@
1
+ module OPE
2
+
3
+ class HGD
4
+
5
+ # Random variates from the hypergeometric distribution.
6
+ #
7
+ # Returns the number of white balls drawn when kk balls
8
+ # are drawn at random from an urn containing nn1 white
9
+ # and nn2 black balls.
10
+ def self.rhyper(kk, nn1, nn2, coins, precision)
11
+
12
+ ix = nil
13
+
14
+ prng = PRNG.new(coins)
15
+
16
+ con, deltal = 57.56462733, 0.0078
17
+ deltau, scale = 0.0034, 1.0e25
18
+
19
+ # Check validity of parameters.
20
+ if [nn1, nn2, kk].include?(Float::INFINITY) ||
21
+ (nn1 < 0 || nn2 < 0 || kk < 0 || kk > (nn1 + nn2))
22
+ raise 'Invalid parameters nn1, nn2 or kk'
23
+ end
24
+
25
+ reject = true
26
+
27
+ if nn1 >= nn2
28
+ n1, n2 = nn2.to_f, nn1.to_f
29
+ else
30
+ n1, n2 = nn1.to_f, nn2.to_f
31
+ end
32
+
33
+ tn = n1 + n2
34
+
35
+ if kk + kk >= tn
36
+ k = tn - kk
37
+ else
38
+ k = kk
39
+ end
40
+
41
+ m = (k+1.0) * (n1+1.0) / (tn+2.0)
42
+
43
+ minjx = (k - n2 < 0) ? 0 : k - n2
44
+ maxjx = (n1 < k) ? n1 : k
45
+
46
+ # Degenerate distribution
47
+ if minjx == maxjx
48
+
49
+ # no, need to untangle TSL
50
+ return maxjx.floor.to_f
51
+
52
+ # Inverse transformation
53
+ elsif m-minjx < 10
54
+
55
+ w = nil
56
+
57
+ if k < n2
58
+ w = Math.exp(con + afc(n2) + afc(n1+n2-k)-afc(n2-k)-afc(n1+n2))
59
+ else
60
+ w = Math.exp(con + afc(n1) + afc(k) + afc(k-n2) -afc(n1+n2))
61
+ end
62
+
63
+ catch :l10 do
64
+
65
+ p = w
66
+ ix = minjx
67
+ u = prng.draw * scale
68
+
69
+ catch :l20 do
70
+
71
+ if u > p
72
+ u = u - p
73
+ p = p * (n1-ix)*(k-ix)
74
+ ix = ix + 1
75
+ p = p / ix / (n2-k+ix)
76
+ throw :l10 if ix > maxjx
77
+ throw :l20
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ # Hypergeometrics-2 points-exponential tails
85
+ else
86
+
87
+ s = Math.sqrt( (tn-k) * k * n1 * n2 / (tn - 1.0) / tn / tn)
88
+
89
+ # Truncation centers cell boundaries at 0.5
90
+ d = (1.5 * s).floor.to_f + 0.5
91
+ xl = m - d + 0.5
92
+ xr = m + d + 0.5
93
+ a = afc(m) + afc(n1-m) +
94
+ afc(k-m) + afc(n2-k+m)
95
+
96
+ expon = a - afc(xl) -
97
+ afc(n1 - xl) - afc(k - xl) -
98
+ afc(n2 - k + xl)
99
+
100
+ kl = Math.exp(expon)
101
+
102
+ kr = Math.exp(a - afc(xr-1) -
103
+ afc(n1-xr+1) - afc(k-xr+1) -
104
+ afc(n2-k+xr-1))
105
+
106
+ lamdl = -Math.log(xl *
107
+ (n2 - k + xl) / (n1 - xl + 1) / (k - xl + 1))
108
+
109
+ lamdr = -Math.log(
110
+ (n1 - xr + 1) * (k -xr + 1) / xr / (n2 - k + xr))
111
+
112
+ p1 = 2 * d
113
+ p2 = p1 + kl / lamdl
114
+ p3 = p2 + kr / lamdr
115
+
116
+ count_30 = 0
117
+
118
+ catch :count do
119
+
120
+ count_30 += 1
121
+
122
+ u = prng.draw * p3
123
+ v = prng.draw
124
+
125
+ # Rectangular region
126
+ if u < p1
127
+ ix = xl + u
128
+ # Left tail region
129
+ elsif u <= p2
130
+ ix = xl + Math.log(v) / lamdl
131
+ throw :count if ix < minjx
132
+ v = v * (u - p1) * lamdl
133
+ # Right tail region
134
+ else
135
+ ix = xr - Math.log(v) / lamdr
136
+ throw :count if ix > maxjx
137
+ v = v * (u - p2) * lamdr
138
+ end
139
+
140
+ f = nil
141
+
142
+ if m < 100 || ix <= 50
143
+
144
+ f = 1
145
+
146
+ if m < ix
147
+
148
+ i = m + 1
149
+
150
+ while i < ix # <= ?
151
+
152
+ f = f * (n1 - i + 1.0) *
153
+ (k - i + 1.0) /
154
+ (n2 - k + i) / i
155
+ i += 1
156
+
157
+ end
158
+
159
+ elsif m > ix
160
+
161
+ i = ix + 1
162
+
163
+ while i < m # <= ?
164
+
165
+ f = f * i * (n2 - k + i) /
166
+ (n1 - i) / (k - i) # + 1 ?
167
+ i += 1
168
+
169
+ end
170
+
171
+ end
172
+
173
+ reject = false if v <= f
174
+
175
+ else
176
+
177
+ y = ix; y1 = y + 1.0; ym = y - m
178
+ yn = n1 - y + 1.0; yk = k - y + 1.0
179
+ nk = n2 - k + y1; r = -ym / y1
180
+ s2 = ym / yn; t = ym / yk; e = -ym / nk
181
+ g = yn * yk / (y1 * nk) - 1.0
182
+ dg = 1.0; dg = 1.0 + g if g < 0
183
+ gu = g * (1.0 + g * (-0.5 + g / 3.0))
184
+ gl = gu - 0.25 * (g * g * g * g) / dg
185
+ xm = m + 0.5; xn = n1 - m + 0.5
186
+ xk = k - m + 0.5; nm = n2 - k + xm
187
+
188
+ ub = y * gu - m * gl + deltau + xm *
189
+ r * (1 + r * (-0.5 + r / 3)) +
190
+ xn * s2 * (1.0 + s2 * (-0.5 + s2 / 3.0)) +
191
+ xk * t * (1.0 + t * (-0.5 + t / 3.0)) +
192
+ nm * e * (1.0 + e * (-0.5 + e / 3.0))
193
+
194
+ alv = Math.log(v)
195
+
196
+ if alv > ub
197
+ reject = true
198
+ else
199
+
200
+ dr = xm * (r * r * r * r)
201
+ dr /= (1.0 + r) if r < 0
202
+ ds = xn * (s2 * s2 * s2 * s2)
203
+ ds /= (1.0 + s2) if s2 < 0
204
+ dt = xk * (t * t * t * t)
205
+ dt /= (1.0 + t) if t < 0
206
+ de = nm * (e * e * e * e)
207
+ de /= (1.0 + e) if e < 0
208
+
209
+
210
+ cand = ub - 0.25 * (dr + ds + dt + de) +
211
+ (y + m) * (gl - gu) - deltal
212
+
213
+ if alv < cand
214
+ reject = false
215
+ else
216
+
217
+
218
+ cand = a - afc(ix) - afc(n1 - ix) -
219
+ afc(k - ix) - afc(n2 - k + ix)
220
+
221
+ reject = alv > cand
222
+
223
+ end
224
+
225
+ end
226
+
227
+ end
228
+
229
+ throw :count if reject
230
+
231
+ end
232
+
233
+ end
234
+
235
+ if kk + kk >= tn
236
+ if nn1 > nn2
237
+ ix = kk - nn2 + ix
238
+ else
239
+ ix = nn1 - ix
240
+ end
241
+ else
242
+ ix = kk - ix if nn1 > nn2
243
+ end
244
+
245
+ jx = ix
246
+
247
+ return jx.floor.to_f
248
+
249
+ end
250
+
251
+ # Calculates logarithm of i factorial: ln(i!)
252
+ # Uses Stirling's approximation to do so.
253
+ def self.afc(i)
254
+
255
+ raise 'i should not be < 0' if i < 0
256
+
257
+ frac_12, frac_360 = 1.0 / 12.0, 1.0 / 360.0
258
+ frac_pi = 0.5 * Math.log(2 * Math::PI)
259
+
260
+ (i + 0.5) * Math.log(i) - i + frac_12 /
261
+ i - frac_360 / i / i / i + frac_pi
262
+
263
+ end
264
+
265
+ end
266
+
267
+ end
@@ -0,0 +1,21 @@
1
+ module OPE
2
+
3
+ class PRNG
4
+
5
+ require 'bigdecimal'
6
+ require 'drbg-rb'
7
+
8
+ def initialize(coin)
9
+ coin = coin.to_s
10
+ coin += '0' while coin.bytesize < 24
11
+ @prng = DRBG::HMAC.new(coin, 128)
12
+ end
13
+
14
+ def draw
15
+ n = @prng.generate(4, 128).unpack('H*')[0]
16
+ n.byteslice(0, 8).hex.to_f / 2**32
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,5 @@
1
+ module OPE
2
+
3
+ VERSION = '0.0.1'
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ope-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Louis Mullie
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-05-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.12.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.12.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! ' '
47
+ email:
48
+ - louis.mullie@gmail.com
49
+ executables: []
50
+ extensions:
51
+ - ext/ope/extconf.rb
52
+ extra_rdoc_files: []
53
+ files:
54
+ - lib/ope-rb/crypto.rb
55
+ - lib/ope-rb/errors.rb
56
+ - lib/ope-rb/hgd.rb
57
+ - lib/ope-rb/prng.rb
58
+ - lib/ope-rb/version.rb
59
+ - lib/ope-rb.rb
60
+ - ext/ope/native.c
61
+ - ext/ope/extconf.rb
62
+ homepage: https://github.com/cryodex/ope-rb
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 1.8.25
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: A Ruby implementation of order-preserving encryption
86
+ test_files: []