Documentation
Client SDK
Encrypt data anonymously

Encrypt data anonymously

Encrypt to a public key, without an account

The encryptAnonymous function encrypts data with the public key of the recipient, before it is transmitted or stored. It is a standalone function exported by @secrecy/lib, and not a method of the client: the visitor who submits the data has neither an account nor a secrecyClient, which is the whole point of the flow.

What you need to provide on your side is the public key to encrypt to. Get your user id from secrecyClient.me, then resolve it into a public key with secrecyClient.app.userPublicKey — see getting started with auth for obtaining an authenticated client. The data itself is turned into bytes with a TextEncoder before being encrypted.

formAnonymous.ts
import { encryptAnonymous } from '@secrecy/lib';
 
const encryptAnonymouslyFormData = async (
  formValues: unknown
): Promise<Uint8Array | null> => {
  // First we need to check if the secrecyClient is available
  if (!secrecyClient) {
    return null;
  }
 
  try {
    // Second we need to get the user public key
    const me = await secrecyClient.me();
    const userPublicKey = await secrecyClient.app.userPublicKey(me.id);
 
    // Third we need to encrypt the form values
    const encoder = new TextEncoder();
    const encoded = encoder.encode(JSON.stringify(formValues));
    const encrypted = encryptAnonymous(encoded, userPublicKey);
 
    // Finally we can return the encrypted form values and store it in the database
    return encrypted;
  } catch (error) {
    console.error(error);
    return null;
  }
};

The function is synchronous and returns a Uint8Array. The ciphertext is ordinary bytes: store it in your own database, as base64 for instance, exactly as you would any other column.

Decrypt the data of an anonymous form

The secrecyClient.decryptAnonymous method opens a ciphertext produced this way. It takes the bytes as its only argument and reuses the key pair of the current identity, so nothing else has to be passed to it. The decrypted bytes are then decoded back into the original structure.

decryptedAnonymousData.ts
const decryptAnonymousFormData = ({ data }: { data: Uint8Array }) => {
  // First we need to check if the secrecyClient is available
  if (!secrecyClient) {
    return null;
  }
 
  try {
    // Second we need to decrypt the form values
    const decrypted = secrecyClient.decryptAnonymous(data);
    const decoder = new TextDecoder();
    const decoded = decoder.decode(decrypted);
 
    // Finally we can return the decrypted form values
    return JSON.parse(decoded);
  } catch (error) {
    console.error(error);
    return null;
  }
};

This method is synchronous as well. A standalone decryptAnonymous function is also exported by @secrecy/lib; it takes the key pair as its second argument, in the form { publicKey, privateKey }, and is what you use outside of an authenticated client.

Decryption fails when the ciphertext was sealed to another public key than the one of the current identity. Note that the sender cannot decrypt what they sent: the key pair used to seal the data is generated on the fly and discarded immediately.