plpgsql_wrap
plpgsql_wrap : Oracle WRAP-equivalent PL/pgSQL language handler storing AES-256-GCM encrypted procedure source.
Overview
| ID | Extension | Package | Version | Category | License | Language |
|---|---|---|---|---|---|---|
| 9210 | plpgsql_wrap
|
plpgsql_wrap
|
1.0 |
SIM
|
PostgreSQL
|
C
|
| Attribute | Has Binary | Has Library | Need Load | Has DDL | Relocatable | Trusted |
|---|---|---|---|---|---|---|
--s-d--
|
No
|
Yes
|
No
|
Yes
|
no
|
no
|
| Relationships | |
|---|---|
| Requires | plpgsql
|
| See Also | orafce
pg_dbms_metadata
pgaudit
|
PGDG RPM and Pigsty DEB package hexacluster/plpgsql_wrap 1.0; control requires plpgsql and superuser=true; links OpenSSL.
Packages
| Type | Repo | Version | PG Major Compatibility | Package Pattern | Dependencies |
|---|---|---|---|---|---|
| EXT | PGDG
|
1.0 |
18
17
16
15
14
|
plpgsql_wrap |
plpgsql |
| RPM | PGDG
|
1.0 |
18
17
16
15
14
|
plpgsql_wrap_$v |
openssl-libs |
| DEB | PIGSTY
|
1.0 |
18
17
16
15
14
|
postgresql-$v-plpgsql-wrap |
libssl3 |
| Linux / PG | PG18 | PG17 | PG16 | PG15 | PG14 |
|---|---|---|---|---|---|
el8.x86_64
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
el8.aarch64
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
el9.x86_64
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
el9.aarch64
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
el10.x86_64
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
el10.aarch64
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
PGDG 1.0
|
d12.x86_64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
d12.aarch64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
d13.x86_64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
d13.aarch64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
u22.x86_64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
u22.aarch64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
u24.x86_64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
u24.aarch64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
u26.x86_64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
u26.aarch64
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
PIGSTY 1.0
|
Source
pig build pkg plpgsql_wrap; # build rpm/debInstall
Make sure PGDG repo available:
pig repo add pgdg -u # add pgdg repo and update cacheInstall this extension with pig:
pig install plpgsql_wrap; # install via package name, for the active PG version
pig install plpgsql_wrap -v 18; # install for PG 18
pig install plpgsql_wrap -v 17; # install for PG 17
pig install plpgsql_wrap -v 16; # install for PG 16
pig install plpgsql_wrap -v 15; # install for PG 15
pig install plpgsql_wrap -v 14; # install for PG 14Create this extension with:
CREATE EXTENSION plpgsql_wrap CASCADE; -- requires plpgsqlUsage
Sources: README, v1.0 release, control file
plpgsql_wrap provides an Oracle WRAP-style procedural language for PostgreSQL. Functions written with LANGUAGE plpgsql_wrap are validated as PL/pgSQL and then stored encrypted in pg_proc.prosrc as PLPGSQLWRAP:1:<hex>.
Install With A Key
Build the extension with a 32-byte AES-256-GCM key:
export WRAP_KEY_HEX=$(openssl rand -hex 32)
make WRAP_KEY_HEX=$WRAP_KEY_HEX
sudo make installBack up the key. Wrapped functions can only be unwrapped or restored safely when the correct compiled key is available.
Install the extension in each database that needs the language:
CREATE EXTENSION plpgsql_wrap; -- requires plpgsqlCreate Wrapped Functions
Use normal PL/pgSQL syntax with a different language name:
CREATE OR REPLACE FUNCTION public.calculate_bonus(emp_id int, yr int)
RETURNS numeric
LANGUAGE plpgsql_wrap
AS $$
DECLARE
v_salary numeric;
BEGIN
SELECT salary INTO v_salary FROM employees WHERE id = emp_id;
RETURN v_salary * 0.15;
END;
$$;The stored body is opaque:
SELECT substring(prosrc, 1, 32) AS wrapped_code
FROM pg_proc
WHERE proname = 'calculate_bonus';Dump, Restore, And Unwrap
pg_dump emits the encrypted PLPGSQLWRAP:1: blob. A restore on a server with the same compiled key works normally. A different key leaves the blob stored, but calls fail when the validator/authentication path cannot authenticate it.
Superusers can permanently unwrap a function when they know the key:
SELECT plpgsql_wrap.unwrap_procedure(
'myhexkey',
'public',
'calculate_bonus',
'emp_id int, yr int'
);Caveats
- Version 1.0 supports PostgreSQL 14-18.
- The control file requires
plpgsqland superuser installation. - This protects casual source inspection and dumps, but the compiled key is a critical secret. Treat package artifacts and build logs accordingly.
- Syntax is validated before encryption, so ordinary PL/pgSQL syntax errors abort
CREATE FUNCTIONbefore encrypted storage is written.