33-- - ORE CLLW types, functions, and operators
44-- -
55
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
77-- Each output block is 8-bits
88CREATE TYPE ore_cllw_8_v1 AS (
99 bytes bytea
1010);
1111
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;
1242
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 );
1444
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 )
1646RETURNS int AS $$
1747DECLARE
1848 len_a INT ;
@@ -21,12 +51,12 @@ DECLARE
2151 i INT ;
2252 differing RECORD;
2353BEGIN
24- len_a := LENGTH(a . bytes );
54+ len_a := LENGTH(a);
2555
2656 -- Iterate over each byte and compare them
2757 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 );
3060
3161 -- Check if there's a difference
3262 IF x != y THEN
@@ -66,22 +96,24 @@ BEGIN
6696 len_b := LENGTH(b .bytes );
6797
6898 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' ;
70100 END IF;
71101
72- RETURN __compare_inner_ore_cllw_8_v1(a, b);
102+ RETURN __compare_inner_ore_cllw_8_v1(a . bytes , b . bytes );
73103END;
74104$$ LANGUAGE plpgsql;
75105
76106
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 );
78108
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 )
80110RETURNS int AS $$
81111DECLARE
82112 len_a INT ;
83113 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 ;
85117BEGIN
86118 -- Get the lengths of both bytea inputs
87119 len_a := LENGTH(a .bytes );
@@ -96,8 +128,18 @@ BEGIN
96128 RETURN 1 ;
97129 END IF;
98130
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+
99138 -- 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+ );
101143
102144 -- If the comparison returns 'less' or 'greater', return that result
103145 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);
122164
123165CREATE FUNCTION ore_cllw_8_v1_eq (a ore_cllw_8_v1, b ore_cllw_8_v1)
124166RETURNS boolean AS $$
125- SELECT compare_ore_cllw_8_v1(a , b) = 0
167+ SELECT __bytea_ct_eq( a . bytes , b . bytes )
126168$$ LANGUAGE SQL;
127169
128170
129171DROP FUNCTION IF EXISTS ore_cllw_8_v1_neq(a ore_cllw_8_v1, b ore_cllw_8_v1);
130172
131173CREATE FUNCTION ore_cllw_8_v1_neq (a ore_cllw_8_v1, b ore_cllw_8_v1)
132174RETURNS boolean AS $$
133- SELECT compare_ore_cllw_8_v1(a , b) <> 0
175+ SELECT not __bytea_ct_eq( a . bytes , b . bytes )
134176$$ LANGUAGE SQL;
135177
136178
@@ -249,12 +291,127 @@ CREATE OPERATOR <= (
249291 MERGES
250292);
251293
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+
252410
253411DROP OPERATOR FAMILY IF EXISTS ore_cllw_8_v1_btree_ops USING btree;
254412
255413CREATE OPERATOR FAMILY ore_cllw_8_v1_btree_ops USING btree;
256414
257-
258415DROP OPERATOR CLASS IF EXISTS ore_cllw_8_v1_btree_ops USING btree;
259416
260417CREATE 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
264421 OPERATOR 4 >= ,
265422 OPERATOR 5 > ,
266423 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