{"id":13640000,"url":"https://github.com/michelp/pgsodium","last_synced_at":"2025-04-05T13:01:40.845Z","repository":{"id":19942833,"uuid":"88354535","full_name":"michelp/pgsodium","owner":"michelp","description":"Modern cryptography for PostgreSQL using libsodium.","archived":false,"fork":false,"pushed_at":"2023-11-10T23:37:32.000Z","size":462,"stargazers_count":508,"open_issues_count":26,"forks_count":30,"subscribers_count":11,"default_branch":"main","last_synced_at":"2024-04-14T09:38:34.358Z","etag":null,"topics":["cryptography","decryption","encryption","library","libsodium","postgresql","sql"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michelp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-04-15T15:06:39.000Z","updated_at":"2024-04-10T18:26:02.000Z","dependencies_parsed_at":"2023-02-16T09:00:45.315Z","dependency_job_id":"2fe5a329-5cb9-4e13-b2f2-7ae93d4bea59","html_url":"https://github.com/michelp/pgsodium","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fpgsodium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fpgsodium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fpgsodium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michelp%2Fpgsodium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michelp","download_url":"https://codeload.github.com/michelp/pgsodium/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339145,"owners_count":20923012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","decryption","encryption","library","libsodium","postgresql","sql"],"created_at":"2024-08-02T01:01:06.892Z","updated_at":"2025-04-05T13:01:40.798Z","avatar_url":"https://github.com/michelp.png","language":"C","readme":"[![Tests](https://github.com/michelp/pgsodium/actions/workflows/test.yml/badge.svg)](https://github.com/michelp/pgsodium/actions/workflows/test.yml)\n\n# pgsodium\n\npgsodium is an encryption library extension for\n[PostgreSQL](https://www.postgresql.org/) using the\n[libsodium](https://download.libsodium.org/doc/) library for high\nlevel cryptographic algorithms.\n\npgsodium can be used a straight interface to libsodium, but it can\nalso use a powerful feature called [Server Key\nManagement](#server-key-management) where pgsodium loads an external\nsecret key into memory that is never accessible to SQL.  This\ninaccessible root key can then be used to derive sub-keys and keypairs\n*by key id*.  This id (type `bigint`) can then be stored *instead of\nthe derived key*.\n\nAnother advanced feature of pgsodium is [Transparent Column\nEncryption](#transparent-column-encryption) which can automatically\nencrypt and decrypt one or more columns of data in a table.\n\n# Table of Contents\n\n   * [pgsodium](#pgsodium)\n      * [Installation](#installation)\n   * [Usage](#usage)\n   * [Server Key Management](#server-key-management)\n   * [Server Key Derivation](#server-key-derivation)\n   * [Key Management API](#key-management-table)\n   * [Security Roles](#security-roles)\n   * [Transparent Column Encryption](#transparent-column-encryption)\n   * [Simple public key encryption with crypto_box()](#simple-public-key-encryption-with-crypto_box)\n   * [Avoid secret logging](#avoid-secret-logging)\n   * [API Reference](#api-reference)\n      * [Generating Random Data](#generating-random-data)\n      * [Secret key cryptography](#secret-key-cryptography)\n         * [Authenticated encryption](#authenticated-encryption)\n         * [Authentication](#authentication)\n      * [Public key cryptography](#public-key-cryptography)\n         * [Authenticated encryption](#authenticated-encryption-1)\n         * [Public key signatures](#public-key-signatures)\n         * [Sealed boxes](#sealed-boxes)\n      * [Hashing](#hashing)\n      * [Password hashing](#password-hashing)\n      * [Key Derivation](#key-derivation)\n      * [Key Exchange](#key-exchange)\n      * [HMAC512](#hmac512)\n      * [Advanced Stream API](#advanced-stream-api)\n      * [XChaCha20-SIV](#xchacha20-siv)\n      * [Signcryption](#signcryption)\n\n## Installation\n\npgsodium requires libsodium \u003e= 1.0.18.  In addition to the libsodium\nlibrary and it's development headers, you may also need the PostgreSQL\nheader files typically in the '-dev' packages to build the extension.\n\nAfter installing the dependencies, clone the repo and run `sudo make\ninstall`.  You can also install pgsodium through the pgxn extension\nnetwork with `pgxn install pgsodium`.\n\npgTAP tests can be run with `sudo -u postgres pg_prove test.sql` or\nthey can be run in a self-contained Docker image.  Run `./test.sh` if\nyou have docker installed to run all tests.\n\nAs of version 3.0.0 pgsodium requires PostgreSQL 14+.  Use pgsodium\n2.0.* for earlier versions of Postgres.  Once you have the extension\ncorrectly compiled you can install it into your database using the\nSQL:\n\n```\nCREATE EXTENSION pgsodium;\n```\n\nNote that pgsodium is very careful about the risk of `search_path`\nhacking and must go into a database schema named `pgsodium`.  The\nabove command will automatically create that schema.  You are\nencouraged to always reference pgsodium functions by their fully\nqualified names, or by making sure that the `pgsodium` schema is first\nin your `search_path`.\n\n# Usage\n\nWithout using the optional [Server Managed\nKeys](#server-key-management) feature pgsodium is a simple and\nstraightforward interface to the libsodium API.\n\npgsodium arguments and return values for content and keys are of type\n`bytea`.  If you wish to use `text` or `varchar` values for general\ncontent, you must make sure they are encoded correctly.  The\n[`encode() and decode()` and\n`convert_to()/convert_from()`](https://www.postgresql.org/docs/current/functions-binarystring.html)\nbinary string functions can convert from `text` to `bytea`.  Simple\nascii `text` strings without escape or unicode characters will be cast\nby the database implicitly, and this is how it is done in the tests to\nsave time, but you should really be explicitly converting your `text`\ncontent if you wish to use pgsodium without conversion errors.\n\nMost of the libsodium API is available as SQL functions.  Keys that\nare generated in pairs are returned as a record type, for example:\n\n```\npostgres=# SELECT * FROM crypto_box_new_keypair();\n                               public                               |                               secret\n--------------------------------------------------------------------+--------------------------------------------------------------------\n \\xa55f5d40b814ae4a5c7e170cd6dc0493305e3872290741d3be24a1b2f508ab31 | \\x4a0d2036e4829b2da172fea575a568a74a9740e86a7fc4195fe34c6dcac99976\n(1 row)\n```\n\npgsodium is careful to use memory cleanup callbacks to zero out all\nallocated memory used when freed.  In general it is a bad idea to\nstore secrets in the database itself, although this can be done\ncarefully it has a higher risk.  To help with this problem, pgsodium\nhas an optional Server Key Management function that can load a hidden\nserver key at boot that other keys are *derived* from.\n\n# Server Key Management\n\nIf you add pgsodium to your\n[`shared_preload_libraries`](https://www.postgresql.org/docs/current/runtime-config-client.html#RUNTIME-CONFIG-CLIENT-PRELOAD)\nconfiguration and place a special script in your postgres shared\nextension directory, the server can preload a libsodium key on server\nstart. **This root secret key cannot be accessed from SQL**.  The only\nway to use the server secret key is to derive other keys from it using\n`derive_key()` or use the key_id variants of the API that take key ids\nand contexts instead of raw `bytea` keys.\n\nServer managed keys are completely optional, pgsodium can still be\nused without putting it in `shared_preload_libraries`, but you will\nneed to provide your own key management.  Skip ahead to the API usage\nsection if you choose not to use server managed keys.\n\nSee the file\n[`getkey_scripts/pgsodium_getkey_urandom.sh`](getkey_scripts/pgsodium_getkey_urandom.sh)\nfor an example script that returns a libsodium key using the linux\n`/dev/urandom` CSPRNG.\n\npgsodium also comes with example scripts for:\n\n  - [Amazon Web Service's Key Management\n    Service](getkey_scripts/pgsodium_getkey_aws.sh).\n\n  - [Google Cloud's Cloud Key\n    Management](getkey_scripts/pgsodium_getkey_gcp.sh).\n\n  - [Doppler SecretOps Platform](getkey_scripts/pgsodium_getkey_doppler.sh).\n\n  - [Zymbit Zymkey 4i Hardware Security\n    Module](getkey_scripts/pgsodium_getkey_zmk.sh).\n\nNext place `pgsodium` in your `shared_preload_libraries`.  For docker\ncontainers, you can append this after the run:\n\n    docker run -d ... -c 'shared_preload_libraries=pgsodium'\n\nWhen the server starts, it will load the secret key into memory, but\nthis key is *never* accessible to SQL.  It's possible that a\nsufficiently clever malicious superuser can access the key by invoking\nexternal programs, causing core dumps, looking in swap space, or other\nattack paths beyond the scope of pgsodium.  Databases that work with\nencryption and keys should be extra cautious and use as many process\nhardening mitigations as possible.\n\nIt is up to you to edit the get key script to get or generate the key\nhowever you want.  pgsodium can be used to generate a new random key\nwith `select encode(randombytes_buf(32), 'hex')`.  Other common\npatterns including prompting for the key on boot, fetching it from an\nssh server or managed cloud secret system, or using a command line\ntool to get it from a hardware security module.\n\nYou can specify the location of the get key script with a database\nconfiguration variable in either `postgresql.conf` or using `ALTER\nSYSTEM`:\n\n    pgsodium.getkey_script = 'path_to_script'\n\n# Server Key Derivation\n\nNew keys are derived from the primary server secret key by id and an\noptional context using the [libsodium Key Derivation\nFunctions](https://doc.libsodium.org/key_derivation).  Key id are just\n`bigint` integers.  If you know the key id, key length (default 32\nbytes) and the context (default 'pgsodium'), you can deterministicly\ngenerate a derived key.\n\nDerived keys can be used to encrypt data or as a seed for\ndeterministicly generating keypairs using `crypto_sign_seed_keypair()`\nor `crypto_box_seed_keypair()`.  It is wise not to store these secrets\nbut only store or infer the key id, length and context.  If an\nattacker steals your database image, they cannot generate the key even\nif they know the key id, length and context because they will not have\nthe server secret key.\n\nThe key id, key length and context can be secret or not, if you store\nthem then possibly logged in database users can generate the key if\nthey have permission to call the `derive_key()` function.\nKeeping the key id and/or length context secret to a client avoid this\npossibility and make sure to set your [database security\nmodel](https://www.postgresql.org/docs/current/sql-grant.html) correctly so\nthat only the minimum permission possible is given to users that\ninteract with the encryption API.\n\nKey rotation is up to you, whatever strategy you want to go from one\nkey to the next.  A simple strategy is incrementing the key id and\nre-encrypting from N to N+1.  Newer keys will have increasing ids, you\ncan always tell the order in which keys are superceded.\n\nA derivation context is an 8 byte `bytea`. The same key id in\ndifferent contexts generate different keys.  The default context is\nthe ascii encoded bytes `pgsodium`.  You are free to use any 8 byte\ncontext to scope your keys, but remember it must be a valid 8 byte\n`bytea` which automatically cast correctly for simple ascii string.\nFor encoding other characters, see the [`encode() and decode()` and\n`convert_to()/convert_from()`](https://www.postgresql.org/docs/current/functions-binarystring.html)\nbinary string functions.  The derivable keyspace is huge given one\n`bigint` keyspace per context and 2^64 contexts.\n\nTo derive a key:\n\n    # select derive_key(1);\n                              derive_key\n    --------------------------------------------------------------------\n     \\x84fa0487750d27386ad6235fc0c4bf3a9aa2c3ccb0e32b405b66e69d5021247b\n\n    # select derive_key(1, 64);\n                                                              derive_key\n    ------------------------------------------------------------------------------------------------------------------------------------\n     \\xc58cbe0522ac4875707722251e53c0f0cfd8e8b76b133f399e2c64c9999f01cb1216d2ccfe9448ed8c225c8ba5db9b093ff5c1beb2d1fd612a38f40e362073fb\n\n    # select derive_key(1, 32, '__auth__');\n                              derive_key\n    --------------------------------------------------------------------\n     \\xa9aadb2331324f399fb58576c69f51727901c651c970f3ef6cff47066ea92e95\n\nThe default keysize is `32` and the default context is `'pgsodium'`.\n\nDerived keys can be used either directly in `crypto_secretbox_*`\nfunctions for \"symmetric\" encryption or as seeds for generating other\nkeypairs using for example `crypto_box_seed_new_keypair()` and\n`crypto_sign_seed_new_keypair()`.\n\n    # select * from crypto_box_seed_new_keypair(derive_key(1));\n                                   public                               |                               secret\n    --------------------------------------------------------------------+--------------------------------------------------------------------\n     \\x01d0e0ec4b1fa9cc8dede88e0b43083f7e9cd33be4f91f0b25aa54d70f562278 | \\x066ec431741a9d39f38c909de4a143ed39b09834ca37b6dd2ba3d015206f14ca\n\n# Key Management API\n\npgsodium provides an API and internal table and view for simple key id\nand context managment.  This table provides a number of useful columns\nincluding experation capability.  Keys generated with this API must be\nused for the [Transparent Column\nEncryption](#transparent-column-encryption) features.\n\nManaged Keys have UUIDs for indentifiers, these UUIDs are used to\nlookup keys in the table.  Note that the key management is based on\nthe same [Server Key Management](#server-key-management) that uses the\ninternal hidden root key, so both the Key Management API and\nTransparent Column Encryption require it.\n\nTo create a new key, call the `pgsodium.create_key()` function:\n\n```\n# select * from pgsodium.create_key();\n-[ RECORD 1 ]-------------------------------------\nid          | 74d97ba2-f9e3-4a64-a032-8427cd6bd686\nstatus      | valid\ncreated     | 2022-08-04 05:06:53.878502\nexpires     |\nkey_type    | aead-det\nkey_id      | 4\nkey_context | \\x7067736f6469756d\ncomment     | This is an optional comment\nuser_data   |\n\n```\n\n`pgsodium.create_key()` takes the following arguments, all of them are\noptional:\n\n  - `key_type pgsodium.key_type = 'aead-det'`: The type of key to\n     create.If you do not specify a `raw_key` argument, a new derived\n     key_id of the correct type will be automatically generated in\n     `key_context` argument context.  Possible values are:\n     - `aead-det`\n     - `aead-ietf`\n     - `hmacsha512`\n     - `hmacsha256`\n     - `auth`\n     - `shorthash`\n     - `generichash`\n     - `kdf`\n     - `generichash`\n     - `kdf`\n     - `secretbox`\n     - `secretstream`\n  - `name text = null`: The optional unique name of the key.\n  - `raw_key bytea = null`: A raw key to store encrypted, if not\n    specified, the raw key is derived from `key_id` and `key_context`.\n  - `raw_key_nonce bytea = null`: The nonce used to encrypt the raw\n    key with, if not specified a new random nonce will be generated.\n  -  `key_context bytea = 'pgsodium'`: The libsodium context to use\n     for derivation if `key_id` is not null.\n  - `parent_key uuid = null`: The parent key use to encrypt the raw\n    key.  If not specified, a new unnamed key is created.\n  - `expires timestamptz = null`: The expiration time checked by the\n    `pgsodium.valid_key` view.\n  - `associated_data text = ''`: Extra user data you can associate\n    with the encrypted raw key.  This data is appended to the key\n    UUID, and mixed into the encryption signature and can be\n    authenticated with it.\n\nKeys of the type `aead-det` can be used for [Transparent Column\nEncryption](#transparent-column-encryption).  The view\n`pgsodium.valid_keys` filters the key table for only keys that are\nvalid and not expired.\n\n# Security Roles\n\nThe pgsodium API has two nested layers of security roles:\n\n  - `pgsodium_keyiduser` Is the less privileged role that can only\n    access keys by their UUID.  This is the role you would typically\n    give to a user facing application.\n\n  - `pgsodium_keymaker` is the more privileged role and can work with\n    raw `bytea` And managed server keys.  You would not typically give\n    this role to a user facing application.\n\nNote that public key apis like `crypto_box` and `crypto_sign` do not\nhave \"key id\" variants, because they work with a combination of four\nkeys, two keypairs for each of two parties.\n\nAs the point of public key encryption is for each party to keep their\nsecrets and for that secret to not be centrally derivable.  You can\ncertainly call something like `SELECT * FROM\ncrypto_box_seed_new_keypair(derive_key(1))` and make deterministic\nkeypairs, but then if an attacker steals your root key they can derive\nall keypair secrets, so this approach is not recommended.\n\n# Transparent Column Encryption\n\npgsodium provides a useful pattern where a trigger is used to encrypt\na column of data in a table which is then decrypted using a view.\nThis is called *Transparent Column Encryption* and can be enabled with\npgsodium using the [SECURITY LABEL ...]() PostgreSQL command.\n\nIf an attacker acquires a dump of the table or database, they will not\nbe able to derive the keys used to encrypt the data since they will\nnot have the root server managed key, which is never revealed to SQL\nSee the [example file for more details](./example/tce.sql).\n\nIn order to use TCE you must use keys created from the [Key Management\nTable](#key-management-table) API.  This API returns key ids that are\nUUIDs for use with the internal encryption functions used by the TCE\nfunctionality.  Creating a key to use is the first step:\n\n```\n# select * from pgsodium.create_key();\n-[ RECORD 1 ]-------------------------------------\nid                | dfc44293-fa78-4a1a-9ef9-7e600e63e101\nstatus            | valid\ncreated           | 2022-08-03 18:50:53.355099\nexpires           |\nkey_type          | aead-det\nkey_id            | 5\nkey_context       | \\x7067736f6469756d\ncomment           |\nassociated_data   |\n```\n\nThis key is now stored in the `pgsodium.key` table, and can be\naccessed via the `pgsodium.valid_key` view:\n\n```\n# select EXISTS (select 1 from pgsodium.valid_key where id = 'dfc44293-fa78-4a1a-9ef9-7e600e63e101');\n-[ RECORD 1 ]\nexists | t\n```\n\nNow this key id can be used for simple TCE as shown in the next section.\n\n## One Key Id for the Entire Column\n\nFor the simplest case, a column can be encrypted with one key id which\nmust be of the type `aead-det` (as created above):\n\n```sql\nCREATE TABLE private.users (\n\tid bigserial primary key,\n\tsecret text);\n\nSECURITY LABEL FOR pgsodium\tON COLUMN private.users.secret\n  IS 'ENCRYPT WITH KEY ID dfc44293-fa78-4a1a-9ef9-7e600e63e101';\n```\n\nThe advantage of this approach is it is very simple, the user creates\none key and labels a column with it.  The cryptographic algorithm for\nthis approach uses a *nonceless* encryption algorithm called\n`crypto_aead_det_xchacha20()`.  If you wish to use a nonce value, see\nbelow.\n\n## One Key ID per Row\n\nUsing one key for an entire column means that whoever can decrypt one\nrow can decrypt them all from a database dump.  Also changing\n(rotating) the key means rewriting the whole table.\n\nA more fine grained approach is to store one key id per row:\n\n```sql\nCREATE TABLE private.users (\n\tid bigserial primary key,\n\tsecret text,\n\tkey_id uuid not null,\n  nonce bytea\n);\n\nSECURITY LABEL FOR pgsodium\n\tON COLUMN private.users.secret\n  IS 'ENCRYPT WITH KEY COLUMN key_id;\n```\n\nThis approach ensures that “cracking” the key for one row does not\nhelp decrypt any others.  It also acts as a natural partition that can\nwork in conjunction with RLS to share distinct keys between owners.\n\n## One Key ID per Row with Nonce Support\n\nThe default cryptographic algorithm for the above approach uses a\n*nonceless* encryption algorithm called `crypto_aead_det_xchacha20()`.\nThis scheme has the advantage that it does not require nonce values,\nthe disadvantage is that duplicate plaintexts will produce duplicate\nciphertexts, but this information can not be used to attack the key it\ncan only reveal the duplication.\n\nHowever duplication is still information, and if you want more\nsecurity, slightly better performance, or you require duplicate\nplaintexts to have *different* ciphertexts, a unique *nonce* can be\nprovided that mixes in some additional non-secret data that\ndeduplicates ciphertexts for duplicate plaintext:\n\n```sql\nCREATE TABLE private.users (\n\tid bigserial primary key,\n\tsecret text,\n\tkey_id uuid not null,\n    nonce bytea\n);\n\nSECURITY LABEL FOR pgsodium\n\tON COLUMN private.users.secret\n  IS 'ENCRYPT WITH KEY COLUMN key_id NONCE nonce';\n```\n## One Key ID per Row with Nonce Support and Associated Data\n\nThe `aead-det` algorithm can mix user provided data into the\nauthentication signature for the encrypted secret.  This\n\"authenticates\" the plaintext and ensures that it has not been altered\n(or the decryption will fail).  This is useful for associated useful\nmetadata with your secrets:\n\n```sql\nCREATE TABLE private.users (\n\tid bigserial primary key,\n\tsecret text,\n\tkey_id uuid not null,\n    nonce bytea,\n    associated_data text\n);\n\nSECURITY LABEL FOR pgsodium\n\tON COLUMN private.users.secret\n  IS 'ENCRYPT WITH KEY COLUMN key_id NONCE nonce ASSOCIATED (id, associated_data)';\n```\n\nYou can specify multiple columns as shown above with both the id and\nassociated data column.  Columns used for associated data must be\n*deterministicly* castable to `text`.\n\n## TCE and `ON CONFLICT UPDATE` Clauses \"UPSERT\" Pattern\n\nUPSERT is not a command in PostgreSQL, it is one pattern among many\npossible when using the `INSERT ... ON CONFLICT DO ...` clause in\nPostgres to either insert a value, or do some other action, which is\ncommonly to update the alreadt extant row that the command was\nattempting to INSERT.  This pattern usually looks like:\n\n```sql\nINSERT INTO my_table (my_columns...) VALUES (new_values...)\n  ON CONFLICT (some_unique_key_like_id) DO UPDATE\n  SET my_data = EXCLUDED.my_data;\n```\n\nThe statement tries to insert a row, and if there is a unique\nconstraint violation, it will instead update the row with the value of\nthe row that was about to be inserted.\n\nUnfortunately, the value of the row that was about to be inserted is\nalready encrypted, so this pattern does not work, instead to do an\n\"UPSERT\" you must combine the unencrypted data from the view with the\nencryted data in the table, so that the unencrypted value is\n\"reencrypted\" correctly and not \"double encrypted\".\n\nThe function below shows how this query can be formatted as a stored\nprocedure, if you are using PostgREST, this is the \"RPC\" function to\nuse to do the intended upsert behavior:\n\n```sql\nCREATE OR REPLACE FUNCTION upsert_test(p_id bigint, p_name text DEFAULT NULL, p_secret text DEFAULT NULL)\n    RETURNS test LANGUAGE sql AS\n    $$\n    INSERT INTO test (id, name, secret) VALUES (p_id, p_name, p_secret)\n    ON CONFLICT (id) DO UPDATE\n        SET name   = coalesce(p_name, (SELECT name FROM test WHERE id = p_id)),\n            secret = coalesce(p_secret, (SELECT decrypted_secret FROM decrypted_test WHERE id = p_id))\n    RETURNING *\n    $$;\n```\n\nIf you do not need the stored procedure you can modify the inner query\nto suite your specific needs as a literal SQL query.\n\n## Postgres 15 and \"Security Invoker\" Views\n\nPostgres 15 added a new propery to views called `security_invoker`\nwhich changes the behavior of views that access an underlying table\nwith row security labels.  Before pg15, all views ran as the owner of\nthe view itself, making interaction with RLS clumsy, starting with\npg15, views that are marked as `security_invoker` will \"run\" with the\nprivileges of the invoking user, not the owner of the view, this makes\nworking with RLS policies simpler.\n\nAny TCE security label can be appended with the string `SECURITY\nINVOKER' which will cause the automatically generated view to be\nmarked `security_invoker=true`.  Note that you are still responsible\nfor understanding the grants/revokes to your view and table, which can\nvary depending on the specific needs of your application's security\nmodel.\n\n## Inspecting Security Labels\n\nThe system catalog `pg_seclabel` can be hard to decipher, requiring\njoins to figure out which labels apply to which columns.  The\n`pgsodium.seclabel` view simplifies this task by resolving the table\nand column names for you:\n\n```\npostgres=\u003e select * from pgsodium.seclabel ;\n-[ RECORD 1 ]---------------------------------------------------------------------------------------------------------\nnspname | tce-example\nrelname | test2\nattname | secret2\nlabel   | ENCRYPT WITH KEY COLUMN secret2_key_id ASSOCIATED (id, associated2) NONCE nonce2\n-[ RECORD 2 ]---------------------------------------------------------------------------------------------------------\nnspname | tce-example\nrelname | test2\nattname | secret\nlabel   | ENCRYPT WITH KEY ID f8db208c-8201-466a-98cd-b0d91f5326ca ASSOCIATED (associated) NONCE nonce\n-[ RECORD 3 ]---------------------------------------------------------------------------------------------------------\nnspname | tce-example\nrelname | test\nattname | secret\nlabel   | ENCRYPT WITH KEY ID 2a5500f3-9378-4134-89db-5fd870a5ce7a\n-[ RECORD 4 ]---------------------------------------------------------------------------------------------------------\nnspname | pgsodium\nrelname | key\nattname | raw_key\nlabel   | ENCRYPT WITH KEY COLUMN parent_key ASSOCIATED (id, associated_data) NONCE raw_key_nonce\n-[ RECORD 5 ]---------------------------------------------------------------------------------------------------------\nnspname | tce-example\nrelname | bob-testt\nattname | secret2-test\nlabel   | ENCRYPT WITH KEY COLUMN secret2_key_id-test ASSOCIATED (associated2-test) NONCE nonce2-test SECURITY INVOKER\n```\n\n## Disabling View and Trigger generation\n\nIf you wish to disable the `EVENT TRIGGER` that fires and generates\nthe trigger and view, you can turn if off with a configuration\nsetting:\n\n```sql\nSET pgsodium.enable_event_trigger = 'off';\n```\n\nThis parameter can be set in the `postgresql.conf` file, or passed to\nthe server on startup with `-C`.  Disabling trigger generation can be\nuseful for doing migrations when you don't want trigger generation to\nget in the way of copying DDL from one system to another.  See the\npostgres docs for [Setting\nParameters](https://www.postgresql.org/docs/current/config-setting.html).\n\n# Simple public key encryption with `crypto_box()`\n\nHere's an example usage from the test.sql that uses command-line\n[`psql`](https://www.postgresql.org/docs/current/app-psql.html) client\ncommands (which begin with a backslash) to create keypairs and encrypt\na message from Alice to Bob.\n\n    -- Generate public and secret keypairs for bob and alice\n    -- \\gset [prefix] is a psql command that will create local\n    -- script variables\n\n    SELECT public, secret FROM crypto_box_new_keypair() \\gset bob_\n    SELECT public, secret FROM crypto_box_new_keypair() \\gset alice_\n\n    -- Create a boxnonce\n\n    SELECT crypto_box_noncegen() boxnonce \\gset\n\n    -- Alice encrypts the box for bob using her secret key, the nonce and his public key\n\n    SELECT crypto_box('bob is your uncle', :'boxnonce', :'bob_public', :'alice_secret') box \\gset\n\n    -- Bob decrypts the box using his secret key, the nonce, and Alice's public key\n\n    SELECT crypto_box_open(:'box', :'boxnonce', :'alice_public', :'bob_secret');\n\nNote in the above example, no secrets are *stored* in the db, but they\nare *interpolated* into the sql by the psql client that is sent to the\nserver, so it's possible they can show up in the database logs.  You\ncan avoid this by using derived keys.\n\n# Avoid secret logging\n\nIf you choose to work with your own keys and not restrict yourself to\nthe `pgsodium_keyiduser` role, a useful approach is to keep keys in an\nexternal storage and disables logging while injecting the keys into\nlocal variables with [`SET\nLOCAL`](https://www.postgresql.org/docs/current/sql-set.html). If the\nimages of database are hacked or stolen, the keys will not be\navailable to the attacker.\n\nTo disable logging of the key injections, `SET LOCAL` is also used to\ndisable\n[`log_statements`](https://www.postgresql.org/docs/current/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHAT)\nand then re-enable normal logging afterwards. as shown below. Setting\n`log_statement` requires superuser privileges:\n\n    -- SET LOCAL must be done in a transaction block\n    BEGIN;\n\n    -- Generate a boxnonce, and public and secret keypairs for bob and alice\n    -- This creates secrets that are sent back to the client but not stored\n    -- or logged.  Make sure you're using an encrypted database connection!\n\n    SELECT crypto_box_noncegen() boxnonce \\gset\n    SELECT public, secret FROM crypto_box_new_keypair() \\gset bob_\n    SELECT public, secret FROM crypto_box_new_keypair() \\gset alice_\n\n    -- Turn off logging and inject secrets\n    -- into session with set local, then resume logging.\n\n    SET LOCAL log_statement = 'none';\n    SET LOCAL app.bob_secret = :'bob_secret';\n    SET LOCAL app.alice_secret = :'alice_secret';\n    RESET log_statement;\n\n    -- Now call the `current_setting()` function to get the secrets, these are not\n    -- stored in the db but only in session memory, when the session is closed they are no longer\n    -- accessible.\n\n    -- Alice encrypts the box for bob using her secret key and his public key\n\n    SELECT crypto_box('bob is your uncle', :'boxnonce', :'bob_public',\n                      current_setting('app.alice_secret')::bytea) box \\gset\n\n    -- Bob decrypts the box using his secret key and Alice's public key.\n\n    SELECT crypto_box_open(:'box', :'boxnonce', :'alice_public',\n                              current_setting('app.bob_secret')::bytea);\n\n    COMMIT;\n\nFor additional paranoia you can use a function to check that the\nconnection being used is secure or a unix domain socket.\n\n    CREATE FUNCTION is_ssl_or_domain_socket() RETURNS bool\n    LANGUAGE plpgsql AS $$\n    DECLARE\n        addr text;\n\t    ssl text;\n    BEGIN\n        SELECT inet_client_addr() INTO addr;\n        SELECT current_setting('ssl', true) INTO ssl;\n        IF NOT FOUND OR ((ssl IS NULL OR ssl != 'on')\n            AND (addr IS NOT NULL OR length(addr) != 0))\n        THEN\n            RETURN false;\n        END IF;\n        RETURN true;\n    END;\n    $$;\n\nThis doesn't guarantee the secret won't leak out in some way of\ncourse, but it can useful if you never store secrets and send them\nonly through secure channels back to the client, for example using the\n`psql` client `\\gset` command shown above, or by only storing a\nderived key id and context.\n\n# API Reference\n\nThe reference below is adapted from and uses some of the same language\nfound at the [libsodium C API\nDocumentation](https://doc.libsodium.org/).  Refer to those documents\nfor details on algorithms and other libsodium specific details.\n\nThe libsodium documentation is Copyright (c) 2014-2018, Frank Denis\n\u003cgithub@pureftpd.org\u003e and released under [The ISC\nLicense](https://github.com/jedisct1/libsodium-doc/blob/master/LICENSE).\n\n## Generating Random Data\n\nFunctions:\n```\n    randombytes_random() -\u003e integer\n\n    randombytes_uniform(upper_bound integer) -\u003e integer\n\n    randombytes_buf(size integer) -\u003e bytea\n\n```\n\nThe library provides a set of functions to generate unpredictable\ndata, suitable for creating secret keys.\n\n    # select randombytes_random();\n     randombytes_random\n    --------------------\n             1229887405\n    (1 row)\n\nThe `randombytes_random()` function returns an unpredictable value\nbetween 0 and 0xffffffff (included).\n\n    # select randombytes_uniform(42);\n     randombytes_uniform\n    ---------------------\n                      23\n    (1 row)\n\nThe `randombytes_uniform()` function returns an unpredictable value\nbetween `0` and `upper_bound` (excluded). Unlike `randombytes_random() %\nupper_bound`, it guarantees a uniform distribution of the possible\noutput values even when `upper_bound` is not a power of 2. Note that an\n`upper_bound \u003c 2` leaves only a single element to be chosen, namely 0.\n\n    # select randombytes_buf(42);\n                                        randombytes_buf\n    ----------------------------------------------------------------------------------------\n     \\x27cec8d2c3de16317074b57acba2109e43b5623e1fb7cae12e8806daa21a72f058430f22ec993986fcb2\n    (1 row)\n\nThe `randombytes_buf()` function returns a `bytea` with an\nunpredictable sequence of bytes.\n\n    # select randombytes_new_seed() bufseed \\gset\n    # select randombytes_buf_deterministic(42, :'bufseed');\n                                 randombytes_buf_deterministic\n    ----------------------------------------------------------------------------------------\n     \\xa183e8d4acd68119ab2cacd9e46317ec3a00a6a8820b00339072f7c24554d496086209d7911c3744b110\n    (1 row)\n\nThe `randombytes_buf_deterministic()` returns a `size` bytea\ncontaining bytes indistinguishable from random bytes without knowing\nthe seed.  For a given seed, this function will always output the same\nsequence. size can be up to 2^38 (256 GB).\n\n[C API\nDocumentation](https://doc.libsodium.org/generating_random_data)\n\n## Secret key cryptography\n\n\n[C API\nDocumentation](https://doc.libsodium.org/secret-key_cryptography)\n\n### Authenticated encryption\n\nFunctions:\n```\n    crypto_secretbox_keygen() -\u003e bytea\n\n    crypto_secretbox_noncegen() -\u003e bytea\n\n    crypto_secretbox(message bytea, nonce bytea, key bytea) -\u003e bytea\n\n    crypto_secretbox_open(ciphertext bytea, nonce bytea, key bytea) -\u003e bytea\n```\n\n`crypto_secretbox_keygen()` generates a random secret key which can be\nused to encrypt and decrypt messages.\n\n`crypto_secretbox_noncegen()` generates a random nonce which will be\nused when encrypting messages.  For security, each nonce must be used\nonly once, though it is not a secret.  The purpose of the nonce is to\nadd randomness to the message so that the same message encrypted\nmultiple times with the same key will produce different ciphertexts.\n\n`crypto_secretbox()` encrypts a message using a previously generated\nnonce and secret key or key id.  The encrypted message can be\ndecrypted using `crypto_secretbox_open()` Note that in order to\ndecrypt the message, the original nonce will be needed.\n\n`crypto_secretbox_open()` decrypts a message encrypted by\n`crypto_secretbox()`.\n\n[C API\nDocumentation](https://doc.libsodium.org/secret-key_cryptography/secretbox)\n\n### Authentication\n\nFunctions:\n```\n    crypto_auth_keygen() -\u003e bytea\n\n    crypto_auth(message bytea, key bytea) -\u003e bytea\n\n    crypto_auth_verify(mac bytea, message bytea, key bytea) -\u003e boolean\n```\n\n`crypto_auth_keygen()` generates a message-signing key for use by\n`crypto_auth()`.\n\n`crypto_auth()` generates an authentication tag (mac) for a\ncombination of message and secret key.  This does not encrypt the\nmessage; it simply provides a means to prove that the message has not\nbeen tampered with.  To verify a message tagged in this way, use\n`crypto_auth_verify()`.  This function is deterministic: for a given\nmessage and key, the generated mac will always be the same.\n\nNote that this requires access to the secret\nkey, which is not something that should normally be shared.  If\nmany users need to verify message it is usually better to use\n[Public Key Signatures](#user-content-public-key-signatures) rather\nthan sharing secret keys.\n\n`crypto_auth_verify()` verifies that the given mac (authentication\ntag) matches the supplied message and key.  This tells us that the\noriginal message has not been tampered with.\n\n[C API\nDocumentation](https://doc.libsodium.org/secret-key_cryptography/secret-key_authentication)\n## Public key cryptography\n\n[C API\nDocumentation](https://doc.libsodium.org/public-key_cryptography)\n\n### Authenticated encryption\n\nFunctions:\n```\n    crypto_box_new_keypair() -\u003e crypto_box_keypair\n\n    crypto_box_noncegen() -\u003e bytea\n\n    crypto_box(message bytea, nonce bytea,\n               public bytea, secret bytea) -\u003e bytea\n\n    crypto_box_open(ciphertext bytea, nonce bytea,\n                    public bytea, secret bytea) -\u003e bytea\n```\n\n`crypto_box_new_keypair()` returns a new, randomly generated, pair of\nkeys for public key encryption.  The public key can be shared with\nanyone.  The secret key must never be shared.\n\n`crypto_box_noncegen()` generates a random nonce which will be used\nwhen encrypting messages.  For security, each nonce must be used only\nonce, though it is not a secret.  The purpose of the nonce is to add\nrandomness to the message so that the same message encrypted multiple\ntimes with the same key will produce different ciphertexts.\n\n`crypto_box()` encrypts a message using a nonce, the intended\nrecipient's public key and the sender's secret key.  The resulting\nciphertext can only be decrypted by the intended recipient using their\nsecret key.  The nonce must be sent along with the ciphertext.\n\n`crypto_box_open()` decrypts a ciphertext encrypted using\n`crypto_box()`.  It takes the ciphertext, nonce, the sender's public\nkey and the recipient's secret key as parameters, and returns the\noriginal message.  Note that the recipient should ensure that the\npublic key belongs to the sender.\n\n[C API\nDocumentation](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption)\n\n### Public key signatures\n\n\nFunctions:\n```\n    crypto_sign_new_keypair() -\u003e crypto_sign_keypair\n\n  combined mode functions:\n\n    crypto_sign(message bytea, key bytea) -\u003e bytea\n\n    crypto_sign_open(signed_message bytea, key bytea) -\u003e bytea\n\n  detached mode functions:\n\n    crypto_sign_detached(message bytea, key bytea) -\u003e bytea\n\n    crypto_sign_verify_detached(sig bytea, message bytea, key bytea) -\u003e boolean\n\n  multi-part message functions:\n\n    crypto_sign_init() -\u003e bytea\n\n    crypto_sign_update(state bytea, message bytea) -\u003e bytea\n\n    crypto_sign_final_create(state bytea, key bytea) -\u003e bytea\n\n    crypto_sign_final_verify(state bytea, signature bytea, key bytea) -\u003e boolean\n```\n\nAggregates:\n```\n    crypto_sign_update_agg(message bytea) -\u003e bytea\n\n    crypto_sign_update_agg(state, bytea message bytea) -\u003e bytea\n```\n\nThese functions are used to authenticate that messages have have come\nfrom a specific originator (the holder of the secret key for which you\nhave the public key), and have not been tampered with.\n\n`crypto_sign_new_keypair()` returns a new, randomly generated, pair of\nkeys for public key signatures.  The public key can be shared with\nanyone.  The secret key must never be shared.\n\n`crypto_sign()` and `crypto_sign_verify()` operate in combined mode.\nIn this mode the message that is being signed is combined with its\nsignature as a single unit.\n\n`crypto_sign()` creates a signature, using the signer's secret key,\nwhich it prepends to the message.  The result can be authenticated\nusing `crypto_sign_open()`.\n\n`crypto_sign_open()` takes a signed message created by\n`crypto_sign()`, checks its validity using the sender's public key and\nreturns the original message if it is valid, otherwise raises a data\nexception.\n\n`crypto_sign_detached()` and `crypto_sign_verify_detached()` operate\nin detached mode.   In this mode the message is kept independent from\nits signature.  This can be useful when wishing to sign objects that\nhave already been stored, or where multiple signatures are desired for\nan object.\n\n`crypto_sign_detached()` generates a signature for message using the\nsigner's secret key.  The result is a signature which exists\nindependently of the message, which can be verified using\n`crypto_sign_verify_detached()`.\n\n`crypto_sign_verify_detached()` is used to verify a signature\ngenerated by `crypto_sign_detached()`.  It takes the generated\nsignature, the original message, and the signer's public key and\nreturns true if the signature matches the message and key, and false\notherwise.\n\n`crypto_sign_init()`, `crypto_sign_update()`,\n`crypto_sign_final_create()`, `crypto_sign_final_verify()`, and the\naggregates `crypto_sign_update_agg()` handle signatures for\nmulti-part messages.  To create or verify a signature for a multi-part\nmessage `crypto_sign_init()` is used to start the process, and then each\nmessage-part is passed to `crypto_sign_update()` or\n`crypto_sign_update_agg()`.  Finally the signature is generated using\n`crypto_sign_final_update()` or verified using\n`crypto_sign_final_verify()`.\n\n`crypto_sign_init()` creates an initial state value which will be\npassed to `crypto_sign_update()` or `crypto_sign_update_agg()`.\n\n`crypto_sign_update()` or `crypto_sign_update_agg()` will be used to\nupdate the state for each part of the multi-part message.\n`crypto_sign_update()` takes as a parameter the state returned from\n`crypto_sign_init()` or the preceding call to `crypto_sign_update()`\nor `crypto_sign_update_agg()`.  `crypto_sign_update_agg()` has two\nvariants: one takes a previous state value, allowing multiple\naggregates to be processed sequentially, and one takes no state\nparameter, initialising the state itself.  Note that the order in\nwhich the parts of a multi-part message are processed is critical.\nThey must be processed in the same order for signing and verifying.\n\n`crypto_sign_final_update()` takes the state returned from the last\ncall to `crypto_sign_update()` or `crypto_sign_update_agg()` and the\nsigner's secret key and produces the final signature.  This can be\nchecked using `crypto_sign_final_verify()`.\n\n`crypto_sign_final_verify()` is used to verify a multi-part message\nsignature created by `crypto_sign_final_update()`.  It must be\npreceded by the same set of calls to `crypto_sign_update()` or\n`crypto_sign_update_agg()` (with the same message-parts, in the same\norder) that were used to create the signature.  It takes the state\nreturned from the last such call, along with the signature and the\nsigner's public key and returns true if the messages, key and\nsignature all match.\n\nTo sign or verify multi-part messages in SQL, CTE (Common Table\nExpression) queries are particularly effective.  For example to sign a\nmessage consisting of a timestamp and several message_parts:\n\n```.sql\nwith init as\n  (\n    select crypto_sign_init() as state\n  ),\ntimestamp_part as\n  (\n    select crypto_sign_update(i.state, m.timestamp::bytea) as state\n      from init i\n     cross join messages m\n     where m.message_id = 42\n  ),\nremaining_parts as\n  (\n    select crypto_sign_update(t.state, p.message_part::bytea) as state\n      from timestamp_part t\n     cross join (\n       select message_part\n         from message_parts\n        where message_id = 42\n        order by message_part_num) p\n  )\nselect crypto_sign_final_create(r.state, k.secret_key) as sig\n  from remaining_parts r\n cross join keys k\n where k.key_name = 'xyzzy';\n```\n\nNote that storing secret keys in a table, as is done in the example\nabove, is a bad practice unless you have effective row-level security\nin place.\n\n[C API\nDocumentation](https://doc.libsodium.org/public-key_cryptography/public-key_signatures)\n\n### Sealed boxes\n\nSealed boxes are designed to anonymously send messages to a recipient\ngiven its public key.  Only the recipient can decrypt these messages,\nusing its private key. While the recipient can verify the integrity of\nthe message, it cannot verify the identity of the sender.\n\n    SELECT public, secret FROM crypto_box_new_keypair() \\gset bob_\n\n    SELECT crypto_box_seal('bob is your uncle', :'bob_public') sealed \\gset\n\nThe `sealed` psql variable is now the encrypted sealed box.  To unseal\nit, bob needs his public and secret key:\n\n    SELECT is(crypto_box_seal_open(:'sealed', :'bob_public', :'bob_secret'),\n              'bob is your uncle', 'crypto_box_seal/open');\n\n\n[C API Documentation](https://doc.libsodium.org/public-key_cryptography/sealed_boxes)\n\n## Hashing\n\nThis API computes a fixed-length fingerprint for an arbitrary long message.\nSample use cases:\n\n  - File integrity checking\n  - Creating unique identifiers to index arbitrary long data\n\nThe `crypto_generichash` and `crypto_shorthash` functions can be used\nto generate hashes.  `crypto_generichash` takes an optional hash key\nargument which can be NULL. In this case, a message will always have\nthe same fingerprint, similar to the MD5 or SHA-1 functions for which\ncrypto_generichash() is a faster and more secure alternative.\n\nBut a key can also be specified. A message will always have the same\nfingerprint for a given key, but different keys used to hash the same\nmessage are very likely to produce distinct fingerprints.  In\nparticular, the key can be used to make sure that different\napplications generate different fingerprints even if they process the\nsame data.\n\n    SELECT is(crypto_generichash('bob is your uncle'),\n              '\\x6c80c5f772572423c3910a9561710313e4b6e74abc0d65f577a8ac1583673657',\n              'crypto_generichash');\n\n    SELECT is(crypto_generichash('bob is your uncle', NULL),\n              '\\x6c80c5f772572423c3910a9561710313e4b6e74abc0d65f577a8ac1583673657',\n              'crypto_generichash NULL key');\n\n    SELECT is(crypto_generichash('bob is your uncle', 'super sekret key'),\n              '\\xe8e9e180d918ea9afe0bf44d1945ec356b2b6845e9a4c31acc6c02d826036e41',\n              'crypto_generichash with key');\n\nMany applications and programming language implementations were\nrecently found to be vulnerable to denial-of-service attacks when a\nhash function with weak security guarantees, such as Murmurhash 3, was\nused to construct a hash table .\n\nIn order to address this, Sodium provides the crypto_shorthash()\nfunction, which outputs short but unpredictable (without knowing the\nsecret key) values suitable for picking a list in a hash table for a\ngiven key.  This function is optimized for short inputs.  The output\nof this function is only 64 bits. Therefore, it should not be\nconsidered collision-resistant.\n\nUse cases:\n\n- Hash tables Probabilistic\n- data structures such as Bloom filters\n- Integrity checking in interactive protocols\n\nExample:\n\n    SELECT is(crypto_shorthash('bob is your uncle', 'super sekret key'),\n              '\\xe080614efb824a15',\n              'crypto_shorthash');\n\n\n[C API Documentation](https://doc.libsodium.org/hashing)\n\n## Password hashing\n\n    SELECT lives_ok($$SELECT crypto_pwhash_saltgen()$$, 'crypto_pwhash_saltgen');\n\n    SELECT is(crypto_pwhash('Correct Horse Battery Staple', '\\xccfe2b51d426f88f6f8f18c24635616b'),\n            '\\x77d029a9b3035c88f186ed0f69f58386ad0bd5252851b4e89f0d7057b5081342',\n            'crypto_pwhash');\n\n    SELECT ok(crypto_pwhash_str_verify(crypto_pwhash_str('Correct Horse Battery Staple'),\n              'Correct Horse Battery Staple'),\n              'crypto_pwhash_str_verify');\n\n\n[C API Documentation](https://doc.libsodium.org/password_hashing)\n\n## Key Derivation\n\nMultiple secret subkeys can be derived from a single primary key.\nGiven the primary key and a key identifier, a subkey can be\ndeterministically computed. However, given a subkey, an attacker\ncannot compute the primary key nor any other subkeys.\n\n    SELECT crypto_kdf_keygen() kdfkey \\gset\n    SELECT length(crypto_kdf_derive_from_key(64, 1, '__auth__', :'kdfkey')) kdfsubkeylen \\gset\n    SELECT is(:kdfsubkeylen, 64, 'kdf byte derived subkey');\n\n    SELECT length(crypto_kdf_derive_from_key(32, 1, '__auth__', :'kdfkey')) kdfsubkeylen \\gset\n    SELECT is(:kdfsubkeylen, 32, 'kdf 32 byte derived subkey');\n\n    SELECT is(crypto_kdf_derive_from_key(32, 2, '__auth__', :'kdfkey'),\n        crypto_kdf_derive_from_key(32, 2, '__auth__', :'kdfkey'), 'kdf subkeys are deterministic.');\n\n[C API Documentation](https://doc.libsodium.org/key_derivation)\n\n## Key Exchange\n\nUsing the key exchange API, two parties can securely compute a set of\nshared keys using their peer's public key and their own secret key.\n\n    SELECT crypto_kx_new_seed() kxseed \\gset\n\n    SELECT public, secret FROM crypto_kx_seed_new_keypair(:'kxseed') \\gset seed_bob_\n    SELECT public, secret FROM crypto_kx_seed_new_keypair(:'kxseed') \\gset seed_alice_\n\n    SELECT tx, rx FROM crypto_kx_client_session_keys(\n        :'seed_bob_public', :'seed_bob_secret',\n        :'seed_alice_public') \\gset session_bob_\n\n    SELECT tx, rx FROM crypto_kx_server_session_keys(\n        :'seed_alice_public', :'seed_alice_secret',\n        :'seed_bob_public') \\gset session_alice_\n\n    SELECT crypto_secretbox('hello alice', :'secretboxnonce', :'session_bob_tx') bob_to_alice \\gset\n\n    SELECT is(crypto_secretbox_open(:'bob_to_alice', :'secretboxnonce', :'session_alice_rx'),\n              'hello alice', 'secretbox_open session key');\n\n    SELECT crypto_secretbox('hello bob', :'secretboxnonce', :'session_alice_tx') alice_to_bob \\gset\n\n    SELECT is(crypto_secretbox_open(:'alice_to_bob', :'secretboxnonce', :'session_bob_rx'),\n              'hello bob', 'secretbox_open session key');\n\n\n[C API Documentation](https://doc.libsodium.org/key_exchange)\n\n## HMAC512/256\n\n[https://en.wikipedia.org/wiki/HMAC]\n\nIn cryptography, an HMAC (sometimes expanded as either keyed-hash\nmessage authentication code or hash-based message authentication code)\nis a specific type of message authentication code (MAC) involving a\ncryptographic hash function and a secret cryptographic key. As with\nany MAC, it may be used to simultaneously verify both the data\nintegrity and authenticity of a message.\n\n    select crypto_auth_hmacsha512_keygen() hmac512key \\gset\n    select crypto_auth_hmacsha512('food', :'hmac512key') hmac512 \\gset\n\n    select is(crypto_auth_hmacsha512_verify(:'hmac512', 'food', :'hmac512key'), true, 'hmac512 verified');\n    select is(crypto_auth_hmacsha512_verify(:'hmac512', 'fo0d', :'hmac512key'), false, 'hmac512 not verified');\n\n[C API Documentation](https://doc.libsodium.org/advanced/hmac-sha2)\n\n## Advanced Stream API (XChaCha20)\n\nThe stream API is for advanced users only and only provide low level\nencryption without authentication.\n\n[C API Documentation](https://doc.libsodium.org/advanced/stream_ciphers/xchacha20)\n\n## XChaCha20-SIV\n\nDeterministic/nonce-reuse resistant authenticated encryption scheme\nusing XChaCha20.\n\n[C API Documentation](https://github.com/jedisct1/libsodium-xchacha20-siv)\n\n## SignCryption\n\nTraditional authenticated encryption with a shared key allows two or\nmore parties to decrypt a ciphertext and verify that it was created by\na member of the group knowing that secret key.\n\nHowever, [it doesn't allow\nverification](https://theworld.com/~dtd/sign_encrypt/sign_encrypt7.html)\nof who in a group originally created a message.\n\nIn order to do so, authenticated encryption has to be combined with\nsignatures.\n\nThe Toorani-Beheshti signcryption scheme achieves this using a single\nkey pair per device, with forward security and public verifiability.\n\n[C API Documentation](https://github.com/jedisct1/libsodium-signcryption)\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichelp%2Fpgsodium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichelp%2Fpgsodium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichelp%2Fpgsodium/lists"}