|
| 1 | +--- |
| 2 | +sidebar_position: 4 |
| 3 | +--- |
| 4 | + |
| 5 | +# Using the App |
| 6 | + |
| 7 | +A step-by-step guide to capturing authenticated photos with the SignedShot iOS app. |
| 8 | + |
| 9 | +## Overview |
| 10 | + |
| 11 | +The SignedShot app captures photos with cryptographic proof of authenticity. Each photo is signed by your device's hardware key and verified by the SignedShot API. The result is two files: the original photo and a sidecar proof that anyone can verify. |
| 12 | + |
| 13 | +## Step 1: Register Your Device |
| 14 | + |
| 15 | +When you first open the app, you'll see a **Device Not Registered** prompt. |
| 16 | + |
| 17 | +1. Tap **Register Device** |
| 18 | +2. Your device will be registered with the SignedShot API |
| 19 | +3. A green shield icon appears in the status bar confirming registration |
| 20 | + |
| 21 | +This is a one-time setup. Your device receives a unique identity used to sign future captures. The registration uses Apple's App Attest to verify that requests come from a genuine device. |
| 22 | + |
| 23 | +:::tip |
| 24 | +If registration fails, check your internet connection and try again. The app will show a **Retry** button on errors. |
| 25 | +::: |
| 26 | + |
| 27 | +## Step 2: Start a Capture Session |
| 28 | + |
| 29 | +Before each photo, you need to start a capture session. |
| 30 | + |
| 31 | +1. Tap **Start Session** |
| 32 | +2. A **Session Active** indicator appears with a countdown timer |
| 33 | +3. The capture button turns white, indicating you can now take a photo |
| 34 | + |
| 35 | +Sessions expire after **5 minutes** as a security measure to prevent replay attacks. If a session expires, tap **Create New Session** to start a fresh one. |
| 36 | + |
| 37 | +:::info |
| 38 | +Each session generates a one-time nonce that ties your capture to a specific moment in time. This ensures the proof can't be reused. |
| 39 | +::: |
| 40 | + |
| 41 | +## Step 3: Capture a Photo |
| 42 | + |
| 43 | +With an active session: |
| 44 | + |
| 45 | +1. Frame your shot using the camera preview |
| 46 | +2. Tap the **capture button** (white circle at the bottom) |
| 47 | +3. Wait for the capture to complete |
| 48 | + |
| 49 | +Behind the scenes, the app: |
| 50 | +- Captures the raw JPEG bytes |
| 51 | +- Signs the content hash with your device's hardware key (Secure Enclave) |
| 52 | +- Exchanges the session nonce for a trust token from the API |
| 53 | +- Generates a sidecar file combining the trust token and media integrity proof |
| 54 | + |
| 55 | +## Step 4: View the Result |
| 56 | + |
| 57 | +After a successful capture, you'll see: |
| 58 | + |
| 59 | +- A thumbnail of your photo |
| 60 | +- The filename (e.g., `photo_20260209_143052.jpg`) |
| 61 | +- **Trust Token Received** confirmation |
| 62 | +- The sidecar filename (e.g., `photo_20260209_143052.sidecar.json`) |
| 63 | +- **Saved to Files → SignedShot** indicating where your files are stored |
| 64 | + |
| 65 | +### Finding Your Files |
| 66 | + |
| 67 | +Photos and sidecar proofs are saved to the **Files** app under the **SignedShot** folder. You can also tap **Open in Files** to jump there directly. |
| 68 | + |
| 69 | +Each capture produces two files: |
| 70 | + |
| 71 | +| File | Description | |
| 72 | +|------|-------------| |
| 73 | +| `photo_YYYYMMDD_HHMMSS.jpg` | The original photo (unmodified JPEG) | |
| 74 | +| `photo_YYYYMMDD_HHMMSS.sidecar.json` | The cryptographic proof | |
| 75 | + |
| 76 | +Both files are needed for verification. The sidecar alone proves nothing — it must be verified against the original media. |
| 77 | + |
| 78 | +## Verifying Your Photo |
| 79 | + |
| 80 | +You can verify a captured photo using the CLI or the API. |
| 81 | + |
| 82 | +### CLI |
| 83 | + |
| 84 | +```bash |
| 85 | +pip install signedshot |
| 86 | +signedshot validate photo_20260209_143052.sidecar.json photo_20260209_143052.jpg |
| 87 | +``` |
| 88 | + |
| 89 | +### API |
| 90 | + |
| 91 | +Upload both files to the `/validate` endpoint: |
| 92 | + |
| 93 | +```bash |
| 94 | +curl -X POST https://api.signedshot.io/validate \ |
| 95 | + -F "sidecar=@photo_20260209_143052.sidecar.json" \ |
| 96 | + -F "media=@photo_20260209_143052.jpg" |
| 97 | +``` |
| 98 | + |
| 99 | +### What Gets Verified |
| 100 | + |
| 101 | +The validator checks three things: |
| 102 | + |
| 103 | +1. **Capture Trust** — The JWT was signed by the SignedShot API (verified via JWKS) |
| 104 | +2. **Media Integrity** — The SHA-256 hash matches and the device signature is valid |
| 105 | +3. **Cross-Validation** — The capture ID in the JWT matches the one in the media integrity proof |
| 106 | + |
| 107 | +If any check fails, the photo cannot be considered authentic. |
| 108 | + |
| 109 | +## Troubleshooting |
| 110 | + |
| 111 | +### Session Expired |
| 112 | + |
| 113 | +Sessions last 5 minutes. If you see **Session Expired**, tap **Create New Session** and capture again. |
| 114 | + |
| 115 | +### Network Errors |
| 116 | + |
| 117 | +The app requires an internet connection to create sessions and exchange trust tokens. If you see a network error, check your connection and tap **Retry**. |
| 118 | + |
| 119 | +### Unauthorized (401) |
| 120 | + |
| 121 | +If your device session has expired on the server, the app will automatically clear credentials and prompt you to register again. Tap **Register Device** to re-register. |
| 122 | + |
| 123 | +## Next Steps |
| 124 | + |
| 125 | +- [Quick Start](/guides/quick-start) — Verify photos with the Python library or CLI |
| 126 | +- [Sidecar Format](/concepts/sidecar-format) — Understand the proof structure |
| 127 | +- [Two-Layer Trust](/concepts/two-layer-trust) — How Capture Trust and Media Integrity work together |
0 commit comments