3
3
-- - ORE CLLW types, functions, and operators
4
4
-- -
5
5
6
- -- Represents a ciphertext encrypted with the CLLW ORE scheme
6
+ -- Represents a ciphertext encrypted with the CLLW ORE scheme for a fixed output size
7
7
-- Each output block is 8-bits
8
8
CREATE TYPE ore_cllw_8_v1 AS (
9
9
bytes bytea
10
10
);
11
11
12
+ -- Represents a ciphertext encrypted with the CLLW ORE scheme for a variable output size
13
+ -- Each output block is 8-bits
14
+ CREATE TYPE ore_cllw_8_variable_v1 AS (
15
+ bytes bytea
16
+ );
17
+
18
+ DROP FUNCTION IF EXISTS __bytea_ct_eq(a bytea , b bytea );
19
+
20
+ -- Constant time comparison of 2 bytea values
21
+ CREATE FUNCTION __bytea_ct_eq (a bytea , b bytea ) RETURNS boolean AS $$
22
+ DECLARE
23
+ result boolean ;
24
+ differing bytea ;
25
+ BEGIN
26
+ -- Check if the bytea values are the same length
27
+ IF LENGTH(a) != LENGTH(b) THEN
28
+ RETURN false;
29
+ END IF;
30
+
31
+ -- Compare each byte in the bytea values
32
+ result := true;
33
+ FOR i IN 1 ..LENGTH(a) LOOP
34
+ IF SUBSTRING (a FROM i FOR 1 ) != SUBSTRING (b FROM i FOR 1 ) THEN
35
+ result := result AND false;
36
+ END IF;
37
+ END LOOP;
38
+
39
+ RETURN result;
40
+ END;
41
+ $$ LANGUAGE plpgsql;
12
42
13
- DROP FUNCTION IF EXISTS __compare_inner_ore_cllw_8_v1(a ore_cllw_8_v1 , b ore_cllw_8_v1 );
43
+ DROP FUNCTION IF EXISTS __compare_inner_ore_cllw_8_v1(a bytea , b bytea );
14
44
15
- CREATE FUNCTION __compare_inner_ore_cllw_8_v1 (a ore_cllw_8_v1 , b ore_cllw_8_v1 )
45
+ CREATE FUNCTION __compare_inner_ore_cllw_8_v1 (a bytea , b bytea )
16
46
RETURNS int AS $$
17
47
DECLARE
18
48
len_a INT ;
@@ -21,12 +51,12 @@ DECLARE
21
51
i INT ;
22
52
differing RECORD;
23
53
BEGIN
24
- len_a := LENGTH(a . bytes );
54
+ len_a := LENGTH(a);
25
55
26
56
-- Iterate over each byte and compare them
27
57
FOR i IN 1 ..len_a LOOP
28
- x := SUBSTRING (a . bytes FROM i FOR 1 );
29
- y := SUBSTRING (b . bytes FROM i FOR 1 );
58
+ x := SUBSTRING (a FROM i FOR 1 );
59
+ y := SUBSTRING (b FROM i FOR 1 );
30
60
31
61
-- Check if there's a difference
32
62
IF x != y THEN
@@ -66,22 +96,24 @@ BEGIN
66
96
len_b := LENGTH(b .bytes );
67
97
68
98
IF len_a != len_b THEN
69
- RAISE EXCEPTION ' Bytea arguments must have the same length' ;
99
+ RAISE EXCEPTION ' Numeric ORE comparison requires bytea values of the same length' ;
70
100
END IF;
71
101
72
- RETURN __compare_inner_ore_cllw_8_v1(a, b);
102
+ RETURN __compare_inner_ore_cllw_8_v1(a . bytes , b . bytes );
73
103
END;
74
104
$$ LANGUAGE plpgsql;
75
105
76
106
77
- DROP FUNCTION IF EXISTS compare_lex_ore_cllw_8_v1(a ore_cllw_8_v1 , b ore_cllw_8_v1 );
107
+ DROP FUNCTION IF EXISTS compare_lex_ore_cllw_8_v1(a ore_cllw_8_variable_v1 , b ore_cllw_8_variable_v1 );
78
108
79
- CREATE FUNCTION compare_lex_ore_cllw_8_v1 (a ore_cllw_8_v1 , b ore_cllw_8_v1 )
109
+ CREATE FUNCTION compare_lex_ore_cllw_8_v1 (a ore_cllw_8_variable_v1 , b ore_cllw_8_variable_v1 )
80
110
RETURNS int AS $$
81
111
DECLARE
82
112
len_a INT ;
83
113
len_b INT ;
84
- cmp_result int ;
114
+ -- length of the common part of the two bytea values
115
+ common_len INT ;
116
+ cmp_result INT ;
85
117
BEGIN
86
118
-- Get the lengths of both bytea inputs
87
119
len_a := LENGTH(a .bytes );
@@ -96,8 +128,18 @@ BEGIN
96
128
RETURN 1 ;
97
129
END IF;
98
130
131
+ -- Find the length of the shorter bytea
132
+ IF len_a < len_b THEN
133
+ common_len := len_a;
134
+ ELSE
135
+ common_len := len_b;
136
+ END IF;
137
+
99
138
-- Use the compare_bytea function to compare byte by byte
100
- cmp_result := __compare_inner_ore_cllw_8_v1(a, b);
139
+ cmp_result := __compare_inner_ore_cllw_8_v1(
140
+ SUBSTRING (a .bytes FROM 1 FOR common_len),
141
+ SUBSTRING (b .bytes FROM 1 FOR common_len)
142
+ );
101
143
102
144
-- If the comparison returns 'less' or 'greater', return that result
103
145
IF cmp_result = - 1 THEN
@@ -122,15 +164,15 @@ DROP FUNCTION IF EXISTS ore_cllw_8_v1_eq(a ore_cllw_8_v1, b ore_cllw_8_v1);
122
164
123
165
CREATE FUNCTION ore_cllw_8_v1_eq (a ore_cllw_8_v1, b ore_cllw_8_v1)
124
166
RETURNS boolean AS $$
125
- SELECT compare_ore_cllw_8_v1(a , b) = 0
167
+ SELECT __bytea_ct_eq( a . bytes , b . bytes )
126
168
$$ LANGUAGE SQL;
127
169
128
170
129
171
DROP FUNCTION IF EXISTS ore_cllw_8_v1_neq(a ore_cllw_8_v1, b ore_cllw_8_v1);
130
172
131
173
CREATE FUNCTION ore_cllw_8_v1_neq (a ore_cllw_8_v1, b ore_cllw_8_v1)
132
174
RETURNS boolean AS $$
133
- SELECT compare_ore_cllw_8_v1(a , b) <> 0
175
+ SELECT not __bytea_ct_eq( a . bytes , b . bytes )
134
176
$$ LANGUAGE SQL;
135
177
136
178
@@ -249,12 +291,127 @@ CREATE OPERATOR <= (
249
291
MERGES
250
292
);
251
293
294
+ -- Lexical comparison operators
295
+
296
+ DROP FUNCTION IF EXISTS ore_cllw_8_variable_v1_eq(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
297
+
298
+ CREATE OR REPLACE FUNCTION ore_cllw_8_variable_v1_eq (a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1) RETURNS boolean AS $$
299
+ SELECT __bytea_ct_eq(a .bytes , b .bytes )
300
+ $$ LANGUAGE SQL;
301
+
302
+ DROP FUNCTION IF EXISTS ore_cllw_8_variable_v1_neq(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
303
+
304
+ CREATE OR REPLACE FUNCTION ore_cllw_8_variable_v1_neq (a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1) RETURNS boolean AS $$
305
+ SELECT not __bytea_ct_eq(a .bytes , b .bytes )
306
+ $$ LANGUAGE SQL;
307
+
308
+ DROP FUNCTION IF EXISTS ore_cllw_8_v1_lt_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
309
+
310
+ CREATE OR REPLACE FUNCTION ore_cllw_8_v1_lt_lex (a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1) RETURNS boolean AS $$
311
+ SELECT compare_lex_ore_cllw_8_v1(a, b) = - 1
312
+ $$ LANGUAGE SQL;
313
+
314
+ DROP FUNCTION IF EXISTS ore_cllw_8_v1_lte_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
315
+
316
+ CREATE OR REPLACE FUNCTION ore_cllw_8_v1_lte_lex (a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1) RETURNS boolean AS $$
317
+ SELECT compare_lex_ore_cllw_8_v1(a, b) != 1
318
+ $$ LANGUAGE SQL;
319
+
320
+ DROP FUNCTION IF EXISTS ore_cllw_8_v1_gt_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
321
+
322
+ CREATE OR REPLACE FUNCTION ore_cllw_8_v1_gt_lex (a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1) RETURNS boolean AS $$
323
+ SELECT compare_lex_ore_cllw_8_v1(a, b) = 1
324
+ $$ LANGUAGE SQL;
325
+
326
+ DROP FUNCTION IF EXISTS ore_cllw_8_v1_gte_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
327
+
328
+ CREATE OR REPLACE FUNCTION ore_cllw_8_v1_gte_lex (a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1) RETURNS boolean AS $$
329
+ SELECT compare_lex_ore_cllw_8_v1(a, b) != - 1
330
+ $$ LANGUAGE SQL;
331
+
332
+ DROP OPERATOR IF EXISTS = (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);
333
+
334
+ CREATE OPERATOR = (
335
+ PROCEDURE= " ore_cllw_8_variable_v1_eq" ,
336
+ LEFTARG= ore_cllw_8_variable_v1,
337
+ RIGHTARG= ore_cllw_8_variable_v1,
338
+ NEGATOR = <> ,
339
+ RESTRICT = eqsel,
340
+ JOIN = eqjoinsel,
341
+ HASHES,
342
+ MERGES
343
+ );
344
+
345
+ DROP OPERATOR IF EXISTS <> (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);
346
+
347
+ CREATE OPERATOR <> (
348
+ PROCEDURE= " ore_cllw_8_variable_v1_neq" ,
349
+ LEFTARG= ore_cllw_8_variable_v1,
350
+ RIGHTARG= ore_cllw_8_variable_v1,
351
+ NEGATOR = = ,
352
+ RESTRICT = eqsel,
353
+ JOIN = eqjoinsel,
354
+ HASHES,
355
+ MERGES
356
+ );
357
+
358
+ DROP OPERATOR IF EXISTS > (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);
359
+
360
+ CREATE OPERATOR > (
361
+ PROCEDURE= " ore_cllw_8_v1_gt_lex" ,
362
+ LEFTARG= ore_cllw_8_variable_v1,
363
+ RIGHTARG= ore_cllw_8_variable_v1,
364
+ NEGATOR = <= ,
365
+ RESTRICT = scalarltsel,
366
+ JOIN = scalarltjoinsel,
367
+ HASHES,
368
+ MERGES
369
+ );
370
+
371
+ DROP OPERATOR IF EXISTS < (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);
372
+
373
+ CREATE OPERATOR < (
374
+ PROCEDURE= " ore_cllw_8_v1_lt_lex" ,
375
+ LEFTARG= ore_cllw_8_variable_v1,
376
+ RIGHTARG= ore_cllw_8_variable_v1,
377
+ NEGATOR = >= ,
378
+ RESTRICT = scalargtsel,
379
+ JOIN = scalargtjoinsel,
380
+ HASHES,
381
+ MERGES
382
+ );
383
+
384
+ DROP OPERATOR IF EXISTS >= (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);
385
+
386
+ CREATE OPERATOR >= (
387
+ PROCEDURE= " ore_cllw_8_v1_gte_lex" ,
388
+ LEFTARG= ore_cllw_8_variable_v1,
389
+ RIGHTARG= ore_cllw_8_variable_v1,
390
+ NEGATOR = < ,
391
+ RESTRICT = scalarltsel,
392
+ JOIN = scalarltjoinsel,
393
+ HASHES,
394
+ MERGES
395
+ );
396
+
397
+ DROP OPERATOR IF EXISTS <= (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);
398
+
399
+ CREATE OPERATOR <= (
400
+ PROCEDURE= " ore_cllw_8_v1_lte_lex" ,
401
+ LEFTARG= ore_cllw_8_variable_v1,
402
+ RIGHTARG= ore_cllw_8_variable_v1,
403
+ NEGATOR = > ,
404
+ RESTRICT = scalargtsel,
405
+ JOIN = scalargtjoinsel,
406
+ HASHES,
407
+ MERGES
408
+ );
409
+
252
410
253
411
DROP OPERATOR FAMILY IF EXISTS ore_cllw_8_v1_btree_ops USING btree;
254
412
255
413
CREATE OPERATOR FAMILY ore_cllw_8_v1_btree_ops USING btree;
256
414
257
-
258
415
DROP OPERATOR CLASS IF EXISTS ore_cllw_8_v1_btree_ops USING btree;
259
416
260
417
CREATE OPERATOR CLASS ore_cllw_8_v1_btree_ops DEFAULT FOR TYPE ore_cllw_8_v1 USING btree FAMILY ore_cllw_8_v1_btree_ops AS
@@ -264,3 +421,19 @@ CREATE OPERATOR CLASS ore_cllw_8_v1_btree_ops DEFAULT FOR TYPE ore_cllw_8_v1 USI
264
421
OPERATOR 4 >= ,
265
422
OPERATOR 5 > ,
266
423
FUNCTION 1 compare_ore_cllw_8_v1(a ore_cllw_8_v1, b ore_cllw_8_v1);
424
+
425
+ -- Lexical comparison operator class
426
+
427
+ DROP OPERATOR FAMILY IF EXISTS ore_cllw_8_v1_variable_btree_ops USING btree;
428
+
429
+ CREATE OPERATOR FAMILY ore_cllw_8_v1_variable_btree_ops USING btree;
430
+
431
+ DROP OPERATOR CLASS IF EXISTS ore_cllw_8_v1_variable_btree_ops USING btree;
432
+
433
+ CREATE OPERATOR CLASS ore_cllw_8_v1_variable_btree_ops DEFAULT FOR TYPE ore_cllw_8_variable_v1 USING btree FAMILY ore_cllw_8_v1_variable_btree_ops AS
434
+ OPERATOR 1 < ,
435
+ OPERATOR 2 <= ,
436
+ OPERATOR 3 = ,
437
+ OPERATOR 4 >= ,
438
+ OPERATOR 5 > ,
439
+ FUNCTION 1 compare_lex_ore_cllw_8_v1(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
0 commit comments