Record sharing
Passwork provides three ways to share records: vault access, direct record transfer, and external links.
Sharing methods overview
| Method | Recipient | Account required | Protection key |
|---|---|---|---|
| Vault access | Passwork user | ✓ | Recipient's RSA key |
| Direct record transfer | Passwork user | ✓ | Recipient's RSA key |
| External link | Anyone | — | Link key in URL |
Internal sharing (between users)
Granting vault access
When adding a user to a vault, cryptographic key exchange occurs.
Access granting process:
- Vault owner initiates adding user B
- Server returns user B's public RSA key
- Owner decrypts vault key with their private RSA key (WebCrypto)
- Owner encrypts vault key with user B's public RSA key (WebCrypto)
- Encrypted key copy is sent to server
- Server saves the copy linked to user B
- User B gains vault access on next login
Important: Server sees only encrypted keys. Only the owner of the corresponding private RSA key can decrypt them.
Owner's process
- Select user to grant access
- Obtain that user's public RSA key
- Encrypt vault key with recipient's public key (RSA-OAEP)
- Send encrypted copy to server
Recipient's process
- On login, recipient sees new vault in list
- Downloads encrypted vault key copy
- Decrypts it with their private RSA key (WebCrypto)
- Gains access to all records in vault
Access levels
When granting access, you can specify permission level:
- View — read-only access to records
- Edit — modify existing records
- Full access — create, edit, delete records
- Administrator — manage other users' permissions
Access level is controlled at application level. Cryptographically, all users with vault access have the same key. Permission differentiation is enforced by server logic.
Direct record transfer (Inbox section)
A record can be transferred to a specific user without adding them to the vault.
Direct transfer process:
- Sender decrypts record key (via vault key, AES-256-CBC)
- Sender requests recipient's public RSA key
- Sender encrypts record key with recipient's public RSA key (WebCrypto)
- Encrypted key copy is sent to server
- Record appears in recipient's "Inbox" section
- Recipient decrypts record key with their private RSA key
Difference from vault access: The specific record's key is transferred, not the vault key. Recipient doesn't see other records in the vault.
Revoking access
When revoking vault or record access:
- Server deletes encrypted key copy for the user
- User can no longer obtain key from server
- Data becomes inaccessible through the interface
Important to understand: If a user previously obtained the vault/record key and saved it locally, they could theoretically decrypt data if they have the encrypted content (e.g., from a database backup).
This is a fundamental limitation of shared-key cryptography. For complete protection after access revocation, it's recommended to:
- Change passwords in critical records
- If necessary — recreate vault with new key
External links
External links allow sharing a record with someone who doesn't have a Passwork account.
How it works
Creating a link (owner):
- Owner selects record to share
- Random link key (256 bits) is generated on client
- Copy of selected record fields is created
- Copy is encrypted with link key (AES-256-CBC)
- Sent to server: encrypted copy + key hash + settings
- Server generates link token (43 characters)
- Owner receives URL like
https://passwork.example/g/p/{token}
Opening a link (recipient):
- Owner sends URL to recipient (email, messenger)
- Recipient opens URL
- Browser sends request to server (token only, without key)
- Server verifies token (exists, not expired, not one-time)
- Server returns encrypted data
- JavaScript extracts key from URL hash part (
#code=...) - Data is decrypted with link key in browser (AES-256-CBC)
- Recipient sees the record
Link token and key
External link contains two components:
| Parameter | Link token | Link key |
|---|---|---|
| Purpose | Link identifier | Data encryption |
| Location | URL path (/g/p/{token}) | URL hash (#code={key}) |
| Generation | On server | On client |
| Length | 43 characters | 100 characters → 256 bits |
| Alphabet | A-Z, a-z, 0-9 (62) | A-Z, a-z, 0-9, @, ! (64) |
| Input entropy | ~256 bits | ~596 bits |
| Server sees | ✓ | — (only hash) |
Key transformation: 100-character string is converted to 256-bit AES key via key derivation function (KDF) — similar to vault, record, and attachment keys.
Client-side link key is generated only when client-side encryption is enabled (CSE). If CSE is disabled, link data is not encrypted on client — only server-side encryption applies.
URL format:
https://passwork.example.com/g/p/{token}#code={link_key}
Link key is passed in the hash part of URL (after #). Per HTTP standard, the fragment (URL part after #) is never sent to server — it's processed only by the browser on the client side.
This means:
- When following the link, server sees only
{token}, but doesn't see the key - Key is only available to JavaScript code in recipient's browser
- Even if request is intercepted on server side, key remains protected
- Zero-Knowledge principle is maintained at HTTP protocol level
Key storage on server
Link key is not stored on server in plaintext:
- Server saves only SHA-256 hash of the key for correctness verification when opening
- When opening link, client computes hash of entered key and sends it to server
- Server compares hashes and returns encrypted data
Link data structure
Stored on server:
| Data | Encryption |
|---|---|
| Link identifier (token) | — |
| Record data copy | With link key + server key |
| SHA-256 key hash | With server key |
| Settings (TTL, one-time) | With server key |
Copied record fields
When creating a link, the following are copied:
| Field | Included |
|---|---|
| Name | ✓ |
| Login | Yes (optional) |
| Password (encrypted) | ✓ |
| URL | Yes (optional) |
| Description | Yes (optional) |
| Custom fields | Yes (optional) |
| Attachments | Yes (optional, metadata + keys) |
Link settings
| Setting | Description |
|---|---|
| Time to live (TTL) | Link automatically deleted after specified time |
| One-time use | Link becomes invalid after first view |
| Password protection | Additional password for access |
| Field selection | Which record fields to include in link |
External link security
Zero-Knowledge principle
- Link key is passed in URL hash part (
#code=...) — browser doesn't send it to server - When following link, server sees only token, key stays only in browser
- Server stores only key hash for correctness verification
- Data on server is encrypted and cannot be read without key
Threat model
| Threat | Protection |
|---|---|
| Server request interception | Key in hash part not sent to server |
| Full URL interception | Requires client-side interception |
| Server compromise | Data encrypted, key not on server |
| Token brute-force | 256 bits entropy makes brute-force impossible |
| Reuse | One-time links |
| Server URL logging | Logs contain only token, without key |
Recommendations
- For critical data — use one-time links
- For temporary access — set short TTL
- For additional protection — transmit key via separate channel
- For audit — track link usage in logs
Including attachments in links
When creating a link with attachments:
Original record structure: record key, file (encrypted with attachment key), attachment key (encrypted with record key).
When creating link: link key is generated, attachment key is re-encrypted with link key, file data remains unchanged on server, link includes: file ID + name + re-encrypted key.
When opening link: recipient decrypts attachment key with link key, requests file from server by ID, decrypts file with attachment key.
Sharing methods comparison
| Criterion | Vault access | Direct transfer | External link |
|---|---|---|---|
| Account required | ✓ | ✓ | — |
| Access to all records | ✓ | — (only one) | — (only one) |
| Access audit | ✓ | ✓ | ⚠️ Limited |
| Can be revoked | ✓ | ✓ | ✓ |
| Zero-Knowledge | ✓ | ✓ | ✓ |
| Change sync | ✓ | ⚠️ | — (data copy) |