Skip to content

Additional JSONB functions and fixes #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,33 @@ build:

# Collect all the drops
# In reverse order (tac) so that we drop the constraints before the tables
grep -h -E '^(DROP|ALTER DOMAIN [^ ]+ DROP CONSTRAINT)' sql/0*-*.sql | tac > release/cipherstash-encrypt-tmp-drop.sql
grep -h -E '^(DROP)' sql/0*-*.sql | tac > release/cipherstash-encrypt-tmp-drop-install.sql
# types are always last
cat sql/666-drop_types.sql >> release/cipherstash-encrypt-tmp-drop.sql
cat sql/666-drop_types.sql >> release/cipherstash-encrypt-tmp-drop-install.sql


# Build cipherstash-encrypt.sql
# drop everything first
cat release/cipherstash-encrypt-tmp-drop.sql > release/cipherstash-encrypt.sql
cat release/cipherstash-encrypt-tmp-drop-install.sql > release/cipherstash-encrypt.sql
# cat the rest of the sql files
cat sql/0*-*.sql >> release/cipherstash-encrypt.sql

# Collect all the drops
# In reverse order (tac) so that we drop the constraints before the tables
grep -h -E '^(DROP|ALTER DOMAIN [^ ]+ DROP CONSTRAINT)' sql/0*-*.sql | tac > release/cipherstash-encrypt-tmp-drop-uninstall.sql
# types are always last
cat sql/666-drop_types.sql >> release/cipherstash-encrypt-tmp-drop-uninstall.sql


# Build cipherstash-encrypt-uninstall.sql
# prepend the drops to the main sql file
cat release/cipherstash-encrypt-tmp-drop.sql >> release/cipherstash-encrypt-uninstall.sql
cat release/cipherstash-encrypt-tmp-drop-uninstall.sql >> release/cipherstash-encrypt-uninstall.sql
# uninstall renames configuration table
cat sql/666-rename_configuration_table.sql >> release/cipherstash-encrypt-uninstall.sql

# remove the drop file
rm release/cipherstash-encrypt-tmp-drop.sql
rm release/cipherstash-encrypt-tmp-drop-install.sql
rm release/cipherstash-encrypt-tmp-drop-uninstall.sql


reset:
Expand Down
203 changes: 188 additions & 15 deletions sql/001-ore-cllw.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,46 @@
--- ORE CLLW types, functions, and operators
---

-- Represents a ciphertext encrypted with the CLLW ORE scheme
-- Represents a ciphertext encrypted with the CLLW ORE scheme for a fixed output size
-- Each output block is 8-bits
CREATE TYPE ore_cllw_8_v1 AS (
bytes bytea
);

-- Represents a ciphertext encrypted with the CLLW ORE scheme for a variable output size
-- Each output block is 8-bits
CREATE TYPE ore_cllw_8_variable_v1 AS (
bytes bytea
);

DROP FUNCTION IF EXISTS __bytea_ct_eq(a bytea, b bytea);

-- Constant time comparison of 2 bytea values
CREATE FUNCTION __bytea_ct_eq(a bytea, b bytea) RETURNS boolean AS $$
DECLARE
result boolean;
differing bytea;
BEGIN
-- Check if the bytea values are the same length
IF LENGTH(a) != LENGTH(b) THEN
RETURN false;
END IF;

-- Compare each byte in the bytea values
result := true;
FOR i IN 1..LENGTH(a) LOOP
IF SUBSTRING(a FROM i FOR 1) != SUBSTRING(b FROM i FOR 1) THEN
result := result AND false;
END IF;
END LOOP;

RETURN result;
END;
$$ LANGUAGE plpgsql;

DROP FUNCTION IF EXISTS __compare_inner_ore_cllw_8_v1(a ore_cllw_8_v1, b ore_cllw_8_v1);
DROP FUNCTION IF EXISTS __compare_inner_ore_cllw_8_v1(a bytea, b bytea);

CREATE FUNCTION __compare_inner_ore_cllw_8_v1(a ore_cllw_8_v1, b ore_cllw_8_v1)
CREATE FUNCTION __compare_inner_ore_cllw_8_v1(a bytea, b bytea)
RETURNS int AS $$
DECLARE
len_a INT;
Expand All @@ -21,12 +51,12 @@ DECLARE
i INT;
differing RECORD;
BEGIN
len_a := LENGTH(a.bytes);
len_a := LENGTH(a);

-- Iterate over each byte and compare them
FOR i IN 1..len_a LOOP
x := SUBSTRING(a.bytes FROM i FOR 1);
y := SUBSTRING(b.bytes FROM i FOR 1);
x := SUBSTRING(a FROM i FOR 1);
y := SUBSTRING(b FROM i FOR 1);

-- Check if there's a difference
IF x != y THEN
Expand Down Expand Up @@ -66,22 +96,24 @@ BEGIN
len_b := LENGTH(b.bytes);

IF len_a != len_b THEN
RAISE EXCEPTION 'Bytea arguments must have the same length';
RAISE EXCEPTION 'Numeric ORE comparison requires bytea values of the same length';
END IF;

RETURN __compare_inner_ore_cllw_8_v1(a, b);
RETURN __compare_inner_ore_cllw_8_v1(a.bytes, b.bytes);
END;
$$ LANGUAGE plpgsql;


DROP FUNCTION IF EXISTS compare_lex_ore_cllw_8_v1(a ore_cllw_8_v1, b ore_cllw_8_v1);
DROP FUNCTION IF EXISTS compare_lex_ore_cllw_8_v1(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);

CREATE FUNCTION compare_lex_ore_cllw_8_v1(a ore_cllw_8_v1, b ore_cllw_8_v1)
CREATE FUNCTION compare_lex_ore_cllw_8_v1(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1)
RETURNS int AS $$
DECLARE
len_a INT;
len_b INT;
cmp_result int;
-- length of the common part of the two bytea values
common_len INT;
cmp_result INT;
BEGIN
-- Get the lengths of both bytea inputs
len_a := LENGTH(a.bytes);
Expand All @@ -96,8 +128,18 @@ BEGIN
RETURN 1;
END IF;

-- Find the length of the shorter bytea
IF len_a < len_b THEN
common_len := len_a;
ELSE
common_len := len_b;
END IF;

-- Use the compare_bytea function to compare byte by byte
cmp_result := __compare_inner_ore_cllw_8_v1(a, b);
cmp_result := __compare_inner_ore_cllw_8_v1(
SUBSTRING(a.bytes FROM 1 FOR common_len),
SUBSTRING(b.bytes FROM 1 FOR common_len)
);

-- If the comparison returns 'less' or 'greater', return that result
IF cmp_result = -1 THEN
Expand All @@ -122,15 +164,15 @@ DROP FUNCTION IF EXISTS ore_cllw_8_v1_eq(a ore_cllw_8_v1, b ore_cllw_8_v1);

CREATE FUNCTION ore_cllw_8_v1_eq(a ore_cllw_8_v1, b ore_cllw_8_v1)
RETURNS boolean AS $$
SELECT compare_ore_cllw_8_v1(a, b) = 0
SELECT __bytea_ct_eq(a.bytes, b.bytes)
$$ LANGUAGE SQL;


DROP FUNCTION IF EXISTS ore_cllw_8_v1_neq(a ore_cllw_8_v1, b ore_cllw_8_v1);

CREATE FUNCTION ore_cllw_8_v1_neq(a ore_cllw_8_v1, b ore_cllw_8_v1)
RETURNS boolean AS $$
SELECT compare_ore_cllw_8_v1(a, b) <> 0
SELECT not __bytea_ct_eq(a.bytes, b.bytes)
$$ LANGUAGE SQL;


Expand Down Expand Up @@ -249,12 +291,127 @@ CREATE OPERATOR <= (
MERGES
);

-- Lexical comparison operators

DROP FUNCTION IF EXISTS ore_cllw_8_variable_v1_eq(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);

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 $$
SELECT __bytea_ct_eq(a.bytes, b.bytes)
$$ LANGUAGE SQL;

DROP FUNCTION IF EXISTS ore_cllw_8_variable_v1_neq(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);

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 $$
SELECT not __bytea_ct_eq(a.bytes, b.bytes)
$$ LANGUAGE SQL;

DROP FUNCTION IF EXISTS ore_cllw_8_v1_lt_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);

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 $$
SELECT compare_lex_ore_cllw_8_v1(a, b) = -1
$$ LANGUAGE SQL;

DROP FUNCTION IF EXISTS ore_cllw_8_v1_lte_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);

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 $$
SELECT compare_lex_ore_cllw_8_v1(a, b) != 1
$$ LANGUAGE SQL;

DROP FUNCTION IF EXISTS ore_cllw_8_v1_gt_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);

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 $$
SELECT compare_lex_ore_cllw_8_v1(a, b) = 1
$$ LANGUAGE SQL;

DROP FUNCTION IF EXISTS ore_cllw_8_v1_gte_lex(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);

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 $$
SELECT compare_lex_ore_cllw_8_v1(a, b) != -1
$$ LANGUAGE SQL;

DROP OPERATOR IF EXISTS = (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);

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

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

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

DROP OPERATOR IF EXISTS > (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);

CREATE OPERATOR > (
PROCEDURE="ore_cllw_8_v1_gt_lex",
LEFTARG=ore_cllw_8_variable_v1,
RIGHTARG=ore_cllw_8_variable_v1,
NEGATOR = <=,
RESTRICT = scalarltsel,
JOIN = scalarltjoinsel,
HASHES,
MERGES
);

DROP OPERATOR IF EXISTS < (ore_cllw_8_variable_v1, ore_cllw_8_variable_v1);

CREATE OPERATOR < (
PROCEDURE="ore_cllw_8_v1_lt_lex",
LEFTARG=ore_cllw_8_variable_v1,
RIGHTARG=ore_cllw_8_variable_v1,
NEGATOR = >=,
RESTRICT = scalargtsel,
JOIN = scalargtjoinsel,
HASHES,
MERGES
);

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

CREATE OPERATOR >= (
PROCEDURE="ore_cllw_8_v1_gte_lex",
LEFTARG=ore_cllw_8_variable_v1,
RIGHTARG=ore_cllw_8_variable_v1,
NEGATOR = <,
RESTRICT = scalarltsel,
JOIN = scalarltjoinsel,
HASHES,
MERGES
);

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

CREATE OPERATOR <= (
PROCEDURE="ore_cllw_8_v1_lte_lex",
LEFTARG=ore_cllw_8_variable_v1,
RIGHTARG=ore_cllw_8_variable_v1,
NEGATOR = >,
RESTRICT = scalargtsel,
JOIN = scalargtjoinsel,
HASHES,
MERGES
);


DROP OPERATOR FAMILY IF EXISTS ore_cllw_8_v1_btree_ops USING btree;

CREATE OPERATOR FAMILY ore_cllw_8_v1_btree_ops USING btree;


DROP OPERATOR CLASS IF EXISTS ore_cllw_8_v1_btree_ops USING btree;

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
Expand All @@ -264,3 +421,19 @@ CREATE OPERATOR CLASS ore_cllw_8_v1_btree_ops DEFAULT FOR TYPE ore_cllw_8_v1 USI
OPERATOR 4 >=,
OPERATOR 5 >,
FUNCTION 1 compare_ore_cllw_8_v1(a ore_cllw_8_v1, b ore_cllw_8_v1);

-- Lexical comparison operator class

DROP OPERATOR FAMILY IF EXISTS ore_cllw_8_v1_variable_btree_ops USING btree;

CREATE OPERATOR FAMILY ore_cllw_8_v1_variable_btree_ops USING btree;

DROP OPERATOR CLASS IF EXISTS ore_cllw_8_v1_variable_btree_ops USING btree;

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
OPERATOR 1 <,
OPERATOR 2 <=,
OPERATOR 3 =,
OPERATOR 4 >=,
OPERATOR 5 >,
FUNCTION 1 compare_lex_ore_cllw_8_v1(a ore_cllw_8_variable_v1, b ore_cllw_8_variable_v1);
Loading
Loading