Skip to content
223 changes: 41 additions & 182 deletions sql/000-ore.sql
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
CREATE EXTENSION IF NOT EXISTS pgcrypto;

CREATE TYPE ore_64_8_v1_term AS (
bytes bytea
);

CREATE TYPE ore_64_8_v1 AS (
terms ore_64_8_v1_term[]
);
CREATE DOMAIN ore_64_8_index_v1 AS bytea[];

DROP FUNCTION IF EXISTS compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term);
DROP FUNCTION IF EXISTS compare_ore_64_8_v1_term(a bytea, b bytea);

CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term) returns integer AS $$
CREATE FUNCTION compare_ore_64_8_v1_term(a bytea, b bytea) returns integer AS $$
DECLARE
eq boolean := true;
unequal_block smallint := 0;
Expand All @@ -35,7 +29,7 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
RETURN 1;
END IF;

IF bit_length(a.bytes) != bit_length(b.bytes) THEN
IF bit_length(a) != bit_length(b) THEN
RAISE EXCEPTION 'Ciphertexts are different lengths';
END IF;

Expand All @@ -47,8 +41,8 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
-- * We are not worrying about timing attacks here; don't fret about
-- the OR or !=.
IF
substr(a.bytes, 1 + block, 1) != substr(b.bytes, 1 + block, 1)
OR substr(a.bytes, 9 + left_block_size * block, left_block_size) != substr(b.bytes, 9 + left_block_size * BLOCK, left_block_size)
substr(a, 1 + block, 1) != substr(b, 1 + block, 1)
OR substr(a, 9 + left_block_size * block, left_block_size) != substr(b, 9 + left_block_size * BLOCK, left_block_size)
THEN
-- set the first unequal block we find
IF eq THEN
Expand All @@ -63,20 +57,20 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
END IF;

-- Hash key is the IV from the right CT of b
hash_key := substr(b.bytes, right_offset + 1, 16);
hash_key := substr(b, right_offset + 1, 16);

-- first right block is at right offset + nonce_size (ordinally indexed)
target_block := substr(b.bytes, right_offset + 17 + (unequal_block * right_block_size), right_block_size);
target_block := substr(b, right_offset + 17 + (unequal_block * right_block_size), right_block_size);

indicator := (
get_bit(
encrypt(
substr(a.bytes, 9 + (left_block_size * unequal_block), left_block_size),
substr(a, 9 + (left_block_size * unequal_block), left_block_size),
hash_key,
'aes-ecb'
),
0
) + get_bit(target_block, get_byte(a.bytes, unequal_block))) % 2;
) + get_bit(target_block, get_byte(a, unequal_block))) % 2;

IF indicator = 1 THEN
RETURN 1::integer;
Expand All @@ -87,169 +81,34 @@ CREATE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term)
$$ LANGUAGE plpgsql;


DROP FUNCTION IF EXISTS ore_64_8_v1_term_eq(a ore_64_8_v1_term, b ore_64_8_v1_term);

CREATE FUNCTION ore_64_8_v1_term_eq(a ore_64_8_v1_term, b ore_64_8_v1_term)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1_term(a, b) = 0
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_term_neq(a ore_64_8_v1_term, b ore_64_8_v1_term);

CREATE FUNCTION ore_64_8_v1_term_neq(a ore_64_8_v1_term, b ore_64_8_v1_term)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1_term(a, b) <> 0
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_term_lt(a ore_64_8_v1_term, b ore_64_8_v1_term);

CREATE FUNCTION ore_64_8_v1_term_lt(a ore_64_8_v1_term, b ore_64_8_v1_term)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1_term(a, b) = -1
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_term_lte(a ore_64_8_v1_term, b ore_64_8_v1_term);

CREATE FUNCTION ore_64_8_v1_term_lte(a ore_64_8_v1_term, b ore_64_8_v1_term)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1_term(a, b) != 1
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_term_gt(a ore_64_8_v1_term, b ore_64_8_v1_term);

CREATE FUNCTION ore_64_8_v1_term_gt(a ore_64_8_v1_term, b ore_64_8_v1_term)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1_term(a, b) = 1
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_term_gte(a ore_64_8_v1_term, b ore_64_8_v1_term);

CREATE FUNCTION ore_64_8_v1_term_gte(a ore_64_8_v1_term, b ore_64_8_v1_term)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1_term(a, b) != -1
$$ LANGUAGE SQL;


DROP OPERATOR IF EXISTS = (ore_64_8_v1_term, ore_64_8_v1_term);

CREATE OPERATOR = (
PROCEDURE="ore_64_8_v1_term_eq",
LEFTARG=ore_64_8_v1_term,
RIGHTARG=ore_64_8_v1_term,
NEGATOR = <>,
RESTRICT = eqsel,
JOIN = eqjoinsel,
HASHES,
MERGES
);


DROP OPERATOR IF EXISTS <> (ore_64_8_v1_term, ore_64_8_v1_term);

CREATE OPERATOR <> (
PROCEDURE="ore_64_8_v1_term_neq",
LEFTARG=ore_64_8_v1_term,
RIGHTARG=ore_64_8_v1_term,
NEGATOR = =,
RESTRICT = eqsel,
JOIN = eqjoinsel,
HASHES,
MERGES
);

DROP OPERATOR IF EXISTS > (ore_64_8_v1_term, ore_64_8_v1_term);

CREATE OPERATOR > (
PROCEDURE="ore_64_8_v1_term_gt",
LEFTARG=ore_64_8_v1_term,
RIGHTARG=ore_64_8_v1_term,
COMMUTATOR = <,
NEGATOR = <=,
RESTRICT = scalargtsel,
JOIN = scalargtjoinsel
);

DROP OPERATOR IF EXISTS < (ore_64_8_v1_term, ore_64_8_v1_term);

CREATE OPERATOR < (
PROCEDURE="ore_64_8_v1_term_lt",
LEFTARG=ore_64_8_v1_term,
RIGHTARG=ore_64_8_v1_term,
COMMUTATOR = >,
NEGATOR = >=,
RESTRICT = scalarltsel,
JOIN = scalarltjoinsel
);

DROP OPERATOR IF EXISTS <= (ore_64_8_v1_term, ore_64_8_v1_term);

CREATE OPERATOR <= (
PROCEDURE="ore_64_8_v1_term_lte",
LEFTARG=ore_64_8_v1_term,
RIGHTARG=ore_64_8_v1_term,
COMMUTATOR = >=,
NEGATOR = >,
RESTRICT = scalarlesel,
JOIN = scalarlejoinsel
);

DROP OPERATOR IF EXISTS >= (ore_64_8_v1_term, ore_64_8_v1_term);

CREATE OPERATOR >= (
PROCEDURE="ore_64_8_v1_term_gte",
LEFTARG=ore_64_8_v1_term,
RIGHTARG=ore_64_8_v1_term,
COMMUTATOR = <=,
NEGATOR = <,
RESTRICT = scalarlesel,
JOIN = scalarlejoinsel
);

DROP OPERATOR FAMILY IF EXISTS ore_64_8_v1_term_btree_ops USING btree;

CREATE OPERATOR FAMILY ore_64_8_v1_term_btree_ops USING btree;


DROP OPERATOR CLASS IF EXISTS ore_64_8_v1_term_btree_ops USING btree;

CREATE OPERATOR CLASS ore_64_8_v1_term_btree_ops DEFAULT FOR TYPE ore_64_8_v1_term USING btree FAMILY ore_64_8_v1_term_btree_ops AS
OPERATOR 1 <,
OPERATOR 2 <=,
OPERATOR 3 =,
OPERATOR 4 >=,
OPERATOR 5 >,
FUNCTION 1 compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term);

-- Compare the "head" of each array and recurse if necessary
-- This function assumes an empty string is "less than" everything else
-- so if a is empty we return -1, if be is empty and a isn't, we return 1.
-- If both are empty we return 0. This cases probably isn't necessary as equality
-- doesn't always make sense but it's here for completeness.
-- If both are non-empty, we compare the first element. If they are equal
-- we need to consider the next block so we recurse, otherwise we return the comparison result.
DROP FUNCTION IF EXISTS compare_ore_array(a ore_64_8_v1_term[], b ore_64_8_v1_term[]);

CREATE FUNCTION compare_ore_array(a ore_64_8_v1_term[], b ore_64_8_v1_term[])

CREATE FUNCTION compare_ore_array(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS integer AS $$
DECLARE
cmp_result integer;
BEGIN
IF (array_length(a, 1) = 0 OR a IS NULL) AND (array_length(b, 1) = 0 OR b IS NULL) THEN
RETURN 0;
END IF;

IF array_length(a, 1) = 0 OR a IS NULL THEN
RETURN -1;
END IF;

IF array_length(b, 1) = 0 OR a IS NULL THEN
RETURN 1;
END IF;

cmp_result := compare_ore_64_8_v1_term(a[1], b[1]);

IF cmp_result = 0 THEN
-- Removes the first element in the array, and calls this fn again to compare the next element/s in the array.
RETURN compare_ore_array(a[2:array_length(a,1)], b[2:array_length(b,1)]);
Expand All @@ -260,68 +119,68 @@ RETURNS integer AS $$
$$ LANGUAGE plpgsql;

-- This function uses lexicographic comparison
DROP FUNCTION IF EXISTS compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1);
DROP FUNCTION IF EXISTS compare_ore_64_8_v1(a ore_64_8_index_v1, b ore_64_8_index_v1);

CREATE FUNCTION compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1)
CREATE FUNCTION compare_ore_64_8_v1(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS integer AS $$
DECLARE
cmp_result integer;
BEGIN
-- Recursively compare blocks bailing as soon as we can make a decision
RETURN compare_ore_array(a.terms, b.terms);
RETURN compare_ore_array(a, b);
END
$$ LANGUAGE plpgsql;


DROP FUNCTION IF EXISTS ore_64_8_v1_eq(a ore_64_8_v1, b ore_64_8_v1);
DROP FUNCTION IF EXISTS ore_64_8_v1_eq(a ore_64_8_index_v1, b ore_64_8_index_v1);

CREATE FUNCTION ore_64_8_v1_eq(a ore_64_8_v1, b ore_64_8_v1)
CREATE FUNCTION ore_64_8_v1_eq(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1(a, b) = 0
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_neq(a ore_64_8_v1, b ore_64_8_v1);
DROP FUNCTION IF EXISTS ore_64_8_v1_neq(a ore_64_8_index_v1, b ore_64_8_index_v1);

CREATE FUNCTION ore_64_8_v1_neq(a ore_64_8_v1, b ore_64_8_v1)
CREATE FUNCTION ore_64_8_v1_neq(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1(a, b) <> 0
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_lt(a ore_64_8_v1, b ore_64_8_v1);
DROP FUNCTION IF EXISTS ore_64_8_v1_lt(a ore_64_8_index_v1, b ore_64_8_index_v1);

CREATE FUNCTION ore_64_8_v1_lt(a ore_64_8_v1, b ore_64_8_v1)
CREATE FUNCTION ore_64_8_v1_lt(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1(a, b) = -1
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_lte(a ore_64_8_v1, b ore_64_8_v1);
DROP FUNCTION IF EXISTS ore_64_8_v1_lte(a ore_64_8_index_v1, b ore_64_8_index_v1);

CREATE FUNCTION ore_64_8_v1_lte(a ore_64_8_v1, b ore_64_8_v1)
CREATE FUNCTION ore_64_8_v1_lte(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1(a, b) != 1
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_64_8_v1_gt(a ore_64_8_v1, b ore_64_8_v1);
DROP FUNCTION IF EXISTS ore_64_8_v1_gt(a ore_64_8_index_v1, b ore_64_8_index_v1);

CREATE FUNCTION ore_64_8_v1_gt(a ore_64_8_v1, b ore_64_8_v1)
CREATE FUNCTION ore_64_8_v1_gt(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1(a, b) = 1
$$ LANGUAGE SQL;
BEGIN
SELECT compare_ore_64_8_v1(a, b) = 1;
END;
$$ LANGUAGE plpgsql;


DROP FUNCTION IF EXISTS ore_64_8_v1_gte(a ore_64_8_v1, b ore_64_8_v1);
DROP FUNCTION IF EXISTS ore_64_8_v1_gte(a ore_64_8_index_v1, b ore_64_8_index_v1);

CREATE FUNCTION ore_64_8_v1_gte(a ore_64_8_v1, b ore_64_8_v1)
CREATE FUNCTION ore_64_8_v1_gte(a ore_64_8_index_v1, b ore_64_8_index_v1)
RETURNS boolean AS $$
SELECT compare_ore_64_8_v1(a, b) != -1
$$ LANGUAGE SQL;


DROP OPERATOR IF EXISTS = (ore_64_8_v1, ore_64_8_v1);
DROP OPERATOR IF EXISTS = (ore_64_8_index_v1, ore_64_8_index_v1);

CREATE OPERATOR = (
PROCEDURE="ore_64_8_v1_eq",
Expand All @@ -335,7 +194,7 @@ CREATE OPERATOR = (
);


DROP OPERATOR IF EXISTS <> (ore_64_8_v1, ore_64_8_v1);
DROP OPERATOR IF EXISTS <> (ore_64_8_index_v1, ore_64_8_index_v1);

CREATE OPERATOR <> (
PROCEDURE="ore_64_8_v1_neq",
Expand All @@ -348,7 +207,7 @@ CREATE OPERATOR <> (
MERGES
);

DROP OPERATOR IF EXISTS > (ore_64_8_v1, ore_64_8_v1);
DROP OPERATOR IF EXISTS > (ore_64_8_index_v1, ore_64_8_index_v1);

CREATE OPERATOR > (
PROCEDURE="ore_64_8_v1_gt",
Expand All @@ -361,7 +220,7 @@ CREATE OPERATOR > (
);


DROP OPERATOR IF EXISTS < (ore_64_8_v1, ore_64_8_v1);
DROP OPERATOR IF EXISTS < (ore_64_8_index_v1, ore_64_8_index_v1);

CREATE OPERATOR < (
PROCEDURE="ore_64_8_v1_lt",
Expand All @@ -374,7 +233,7 @@ CREATE OPERATOR < (
);


DROP OPERATOR IF EXISTS <= (ore_64_8_v1, ore_64_8_v1);
DROP OPERATOR IF EXISTS <= (ore_64_8_index_v1, ore_64_8_index_v1);

CREATE OPERATOR <= (
PROCEDURE="ore_64_8_v1_lte",
Expand All @@ -387,7 +246,7 @@ CREATE OPERATOR <= (
);


DROP OPERATOR IF EXISTS >= (ore_64_8_v1, ore_64_8_v1);
DROP OPERATOR IF EXISTS >= (ore_64_8_index_v1, ore_64_8_index_v1);

CREATE OPERATOR >= (
PROCEDURE="ore_64_8_v1_gte",
Expand All @@ -413,4 +272,4 @@ CREATE OPERATOR CLASS ore_64_8_v1_btree_ops DEFAULT FOR TYPE ore_64_8_v1 USING b
OPERATOR 3 =,
OPERATOR 4 >=,
OPERATOR 5 >,
FUNCTION 1 compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1);
FUNCTION 1 compare_ore_64_8_v1(a ore_64_8_index_v1, b ore_64_8_index_v1);
Loading