Encryption
Apertur supports end-to-end encrypted uploads using RSA-OAEP key wrapping and AES-256-GCM encryption. Images are encrypted client-side before being sent to the server.
How It Works
The encryption flow uses a hybrid scheme: a random AES-256-GCM symmetric key encrypts the image, and the server's RSA public key wraps the AES key.
- Fetch the server's RSA public key from the encryption endpoint.
- Generate a random AES-256-GCM key and nonce on the client.
- Encrypt the image data with AES-256-GCM.
- Wrap the AES key using RSA-OAEP with the server's public key, then upload the ciphertext along with the wrapped key and nonce.
Get Server Key
/api/v1/encryption/keyRetrieve the server's RSA public key in PEM format. This key is used to wrap the AES session key.
curl https://api.apertur.ca/api/v1/encryption/key \
-H "Authorization: Bearer aptr_live_xxxx"
# Response:
# {
# "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----"
# }Encrypted Upload
The Node.js and PHP SDKs handle encryption automatically via imageEncrypted(). For other languages, implement the AES-256-GCM + RSA-OAEP flow manually.
# End-to-end encrypted uploads require client-side encryption. # Use the Node.js or PHP SDK for automatic encryption handling. # # Manual flow: # 1. GET /api/v1/encryption/key → RSA public key # 2. Generate a random AES-256-GCM key # 3. Encrypt the image with AES-256-GCM # 4. Wrap the AES key with RSA-OAEP using the server's public key # 5. POST /api/v1/sessions/:id/upload with encrypted payload + wrapped key
Security Note
Encrypted uploads ensure that image data is protected in transit and at rest. The server never sees the raw AES key — only the wrapped version that can be decrypted server-side.