-- # Public Key Cryptography
--
\pset linestyle unicode
\pset border 2
\pset pager off
create extension if not exists pgsodium; -- pragma:hide
set search_path to pgsodium,public; -- pragma:hide
--
-- The `box` API uses public key encryption
-- to securely send messages between two parties who only know each
-- others public keys.  Each party has a secret key that is used to
-- encrypt messages.
--
-- [Libsodium Documentation](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption)
--
-- `crypto_box_new_keypair()` returns a new, randomly generated, pair of
-- keys for public key encryption.  The public key can be shared with
-- anyone.  The secret key must never be shared.
--
-- `crypto_box_noncegen()` generates a random nonce which will be used
-- when encrypting messages.  For security, each nonce must be used only
-- once, though it is not a secret.  The purpose of the nonce is to add
-- randomness to the message so that the same message encrypted multiple
-- times with the same key will produce different ciphertexts.
--
-- `crypto_box()` encrypts a message using a nonce, the intended
-- recipient's public key and the sender's secret key.  The resulting
-- ciphertext can only be decrypted by the intended recipient using their
-- secret key.  The nonce must be sent along with the ciphertext.
--
-- `crypto_box_open()` descrypts a ciphertext encrypted using
-- `crypto_box()`.  It takes the ciphertext, nonce, the sender's public
-- key and the recipient's secret key as parameters, and returns the
-- original message.  Note that the recipient should ensure that the
-- public key belongs to the sender.
--
--
-- Public key encryption requires each party have a pair of keys, one
-- public and one private, and a nonce.  The nonce doesn't have to be
-- confidential, but it should never ever be reused with the same
-- key. The easiest way to generate a nonce is to use
-- `crypto_box_noncegen`:

select crypto_box_new_seed() seed \gset
SELECT pgsodium.crypto_box_noncegen() nonce \gset

-- Now create a new keypair for both bob and alice.

SELECT public, secret FROM crypto_box_new_keypair() \gset bob_
SELECT public, secret FROM crypto_box_seed_new_keypair(:'seed') \gset alice_

SELECT pgsodium.crypto_box('hello bob', :'nonce', :'bob_public', :'alice_secret') atob \gset
SELECT :'atob';

select pgsodium.crypto_box_open(:'atob', :'nonce', :'alice_public', :'bob_secret');

-- Sealed boxes are designed to anonymously send messages to a recipient
-- given its public key.
--
-- Only the recipient can decrypt these messages, using its private
-- key. While the recipient can verify the integrity of the message, it
-- cannot verify the identity of the sender.
--
-- A message is encrypted using an ephemeral key pair, whose secret part
-- is destroyed right after the encryption process.
--
-- Without knowing the secret key used for a given message, the sender
-- cannot decrypt its own message later. And without additional data, a
-- message cannot be correlated with the identity of its sender.

SELECT pgsodium.crypto_box_seal('bob is your uncle', :'bob_public') sealed \gset
SELECT pgsodium.crypto_box_seal_open(:'sealed', :'bob_public', :'bob_secret');

