# ECLYPSE local writing encryption

An optional encrypted-file workflow. No inference, network operations, automatic storage, uploads, clipboard access or key escrow. The module runs in a current browser's WebCrypto secure context or Node 22+ native WebCrypto. The hosted ECLYPSE workspace is **not end-to-end encrypted**, and this utility does not change that service.

Use `/privacy-tools` for the site interface or `/open/privacy/index.html` for the isolated page. The isolated page's Content Security Policy uses `connect-src 'none'`, disallows form submissions and loads only its own scripts and styles. Asset loading is distinct from uploading writing. No encryption key or plaintext is sent by these tools.

The key is a separate raw secret **key file**, not a password, login passkey, account key or wallet key. Keep it separately from the encrypted writing. Anyone holding both files can decrypt. If the key is lost, there is no recovery. Encryption does not remove an original already held elsewhere.

## Module API

```js
import {encryptWriting, decryptWriting, parseEnvelope, parseKeyFile} from './crypto.mjs';

// Keep both returned objects private. Download or retain them only by your own explicit choice.
const {envelope, keyFile} = await encryptWriting(writing);
const recoveredWriting = await decryptWriting(envelope, keyFile);

// For imported local files: bounded UTF-8 JSON, strict fields and canonical base64url.
const importedEnvelope = parseEnvelope(encryptedFileJson);
const importedKeyFile = parseKeyFile(secretKeyFileJson);
const recoveredCopy = await decryptWriting(importedEnvelope, importedKeyFile);
```

The module never prints its arguments, plaintext, keys or outputs. It throws `PrivacyError` with a fixed public message and `code`; errors include no supplied content. `validateEnvelope` and `validateKeyFile` accept already parsed plain data objects and return validated copies. TypeScript declarations are included next to the module.

## Version 1 protocol

- Algorithm: AES-256-GCM, 128-bit authentication tag.
- Key: 32 fresh random bytes for **every encryption**, from `crypto.getRandomValues`.
- IV: 12 fresh random bytes for every encryption, from the same cryptographic source.
- Additional authenticated data: exact UTF-8 bytes of `eclypse.encrypted-writing|v=1|alg=A256GCM`.
- Plaintext: valid Unicode writing encoded as UTF-8, at most 131,072 bytes (128 KiB). Empty writing is valid. Ill-formed Unicode is rejected rather than silently replaced.
- The `ciphertext` field contains encrypted bytes followed by WebCrypto's 16-byte GCM tag. It decodes to 16–131,088 bytes.
- Binary fields use canonical, unpadded base64url. Whitespace, `=`, non-url alphabet characters, impossible lengths and nonzero unused bits are rejected.
- JSON is a single strict object. Unknown/extra fields, duplicate fields, unsupported versions or algorithms, nested values, missing fields and invalid field types are rejected.
- Imported envelope JSON is capped at 175,808 UTF-8 bytes; key-file JSON at 512 bytes. Object input separately enforces decoded field sizes.
- Decryption fails without returning any plaintext if authentication fails. Wrong key, altered IV, changed ciphertext or tag and a mismatched AAD all fail closed.

Encrypted writing:

```json
{"v":1,"kind":"eclypse.encrypted-writing","alg":"A256GCM","iv":"<base64url of 12 bytes>","ciphertext":"<base64url ciphertext plus tag>"}
```

Separate secret key file:

```json
{"v":1,"kind":"eclypse.local-encryption-key","key":"<base64url of 32 bytes>"}
```

The angle-bracket strings above describe fields; they are not valid cryptographic examples or usable keys. Runtime checks supplement the adjacent JSON Schemas, including canonical base64 checks, decoded lengths and duplicate-field rejection.

## Local copies and limits

Download this directory's `index.html`, `style.css`, `tools.mjs` and `crypto.mjs` together to use the isolated interface independently of the business. Serve that folder from a local HTTP server on `localhost`, or from an HTTPS static host, then open `index.html`. Browser ES modules may not load when a file is opened directly with `file://`. No ECLYPSE service endpoint is needed.

Encryption makes a private copy; it does not authenticate an author, hide the file's existence or size, control a device, erase other copies or confer absolute data sovereignty. Browser extensions, compromised page assets or device software may read writing or keys while in use. The integrated page shares the site context; the isolated page has a narrower connection policy. Neither is an independently audited secure enclave.

Transient byte buffers are cleared where practical. JavaScript strings, CryptoKey lifetimes, browser history, memory snapshots and downloaded files cannot be securely wiped by this tool. The clear action drops the tool's current field values and references; it is not a memory-erasure certificate. Keep appropriate device security and trusted offline copies.

## Checks

From the repository root:

```sh
node --test tests/local-writing-encryption.test.mjs
```

The tests use native Node WebCrypto, including independent interoperability checks, wrong-key and tamper rejection, UTF-8 byte limits, strict parsing, fresh keys/IVs, and absence of logging or network/storage operations. The schemas and API are versioned so a future server may store opaque envelopes without receiving a secret key; no such upload feature is part of this utility.

MIT license for this directory only. Protected ECLYPSE room texts, recordings and workbooks are not included.
