upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/XX.md
blob: a9b7d66fa440ad01ace2cb3b31c73d0ff7b6c956 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# NIP-XX: ProofMode - Cryptographic Video Verification

`draft` `optional`

## Abstract

This NIP defines a standard for attaching cryptographic proof manifests to video events (NIP-71) to enable verification of video authenticity, recording continuity, and device integrity. ProofMode allows viewers to verify that a video was recorded on a specific device at a specific time without editing or tampering.

## Motivation

Social media platforms are increasingly vulnerable to deepfakes, edited videos, and synthetic media. While blockchain timestamping exists, it doesn't prove video continuity or prevent frame-level manipulation. ProofMode solves this by:

1. **Frame-level verification** - SHA256 hashes of captured frames prove recording continuity
2. **Hardware attestation** - iOS App Attest and Android Play Integrity verify the recording device
3. **Cryptographic signing** - PGP signatures ensure manifest authenticity
4. **Tamper detection** - Any edit to the video invalidates the proof chain
5. **Segment tracking** - Recording pauses are documented with sensor data

## Specification

### Event Tags

ProofMode data is attached to video events (typically Kind 34236) using the following tags:

#### Required Tags

- `["verification", "<level>"]` - Verification level (see Verification Levels below)
- `["proofmode", "<manifest_json>"]` - Complete ProofManifest as compact JSON

#### Optional Tags

- `["device_attestation", "<token>"]` - Hardware attestation token from iOS App Attest or Android Play Integrity
- `["pgp_fingerprint", "<fingerprint>"]` - PGP public key fingerprint used to sign the manifest

### Verification Levels

The `verification` tag indicates the strength of cryptographic proof:

- `verified_mobile` - Highest level: has device attestation + PGP signature + complete manifest
- `verified_web` - Medium level: has PGP signature + complete manifest (no hardware attestation)
- `basic_proof` - Low level: has proof data but no cryptographic signature
- `unverified` - No meaningful proof data

### ProofManifest Structure

The `proofmode` tag contains a JSON object with the following structure:

```json
{
  "sessionId": "<unique_session_id>",
  "challengeNonce": "<16_char_nonce>",
  "vineSessionStart": "<ISO8601_timestamp>",
  "vineSessionEnd": "<ISO8601_timestamp>",
  "totalDuration": 6500,
  "recordingDuration": 6000,
  "segments": [
    {
      "segmentId": "<segment_id>",
      "startTime": "<ISO8601_timestamp>",
      "endTime": "<ISO8601_timestamp>",
      "duration": 3000,
      "frameHashes": [
        "<sha256_hash_1>",
        "<sha256_hash_2>",
        "..."
      ],
      "frameTimestamps": [
        "<ISO8601_timestamp_1>",
        "<ISO8601_timestamp_2>",
        "..."
      ],
      "sensorData": {
        "accelerometer": {"x": 0.1, "y": 0.2, "z": 9.8},
        "gyroscope": {"x": 0.01, "y": 0.02, "z": 0.01}
      }
    }
  ],
  "pauseProofs": [
    {
      "startTime": "<ISO8601_timestamp>",
      "endTime": "<ISO8601_timestamp>",
      "duration": 500,
      "sensorData": {
        "timestamp": "<ISO8601_timestamp>",
        "accelerometer": {"x": 0.1, "y": 0.2, "z": 9.8},
        "gyroscope": {"x": 0.01, "y": 0.02, "z": 0.01},
        "magnetometer": {"x": 45.0, "y": 12.0, "z": -30.0},
        "light": 150.0
      },
      "interactions": [
        {
          "timestamp": "<ISO8601_timestamp>",
          "interactionType": "touch",
          "coordinates": {"x": 180, "y": 640},
          "pressure": 0.5
        }
      ]
    }
  ],
  "interactions": [
    {
      "timestamp": "<ISO8601_timestamp>",
      "interactionType": "start|stop|touch",
      "coordinates": {"x": 180, "y": 640},
      "pressure": 0.5,
      "metadata": {}
    }
  ],
  "finalVideoHash": "<sha256_hash_of_complete_video>",
  "deviceAttestation": {
    "token": "<platform_specific_attestation_token>",
    "platform": "iOS|Android|Web",
    "deviceId": "<device_identifier>",
    "isHardwareBacked": true,
    "createdAt": "<ISO8601_timestamp>",
    "challenge": "<challenge_nonce>",
    "metadata": {
      "attestationType": "app_attest|play_integrity|fallback",
      "deviceInfo": {
        "platform": "iOS",
        "model": "iPhone 15 Pro",
        "version": "17.0",
        "manufacturer": "Apple"
      }
    }
  },
  "pgpSignature": {
    "signature": "-----BEGIN PGP SIGNATURE-----\n...\n-----END PGP SIGNATURE-----",
    "publicKey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n...\n-----END PGP PUBLIC KEY BLOCK-----",
    "publicKeyFingerprint": "1A2B3C4D5E6F7890..."
  }
}
```

### Field Descriptions

#### Core Fields
- `sessionId` - Unique identifier for the recording session
- `challengeNonce` - Random nonce generated at session start, used in device attestation to prevent replay attacks
- `vineSessionStart` / `vineSessionEnd` - Recording session boundaries
- `totalDuration` - Total elapsed time in milliseconds (including pauses)
- `recordingDuration` - Actual recording time in milliseconds (excluding pauses)

#### Segments
Recording can be paused and resumed, creating multiple segments. Each segment contains:
- `segmentId` - Unique segment identifier
- `startTime` / `endTime` - Segment boundaries
- `frameHashes` - Array of SHA256 hashes of captured video frames
- `frameTimestamps` - Timestamps when each frame was captured (optional)
- `sensorData` - Device sensor readings during recording (optional)

#### Pause Proofs
When recording is paused, sensor data is collected to prove device continuity:
- `startTime` / `endTime` - Pause boundaries
- `sensorData` - Sensor readings during pause (accelerometer, gyroscope, magnetometer, light)
- `interactions` - User touch/tap events during pause

#### Interactions
User interactions recorded throughout the session:
- `timestamp` - When interaction occurred
- `interactionType` - Type of interaction (start, stop, touch)
- `coordinates` - Screen coordinates of interaction
- `pressure` - Touch pressure (optional)

#### Final Video Hash
- `finalVideoHash` - SHA256 hash of the complete rendered video file

#### Device Attestation
Platform-specific hardware attestation proving the device is genuine:
- **iOS**: Uses App Attest API (iOS 14+)
- **Android**: Uses Play Integrity API
- **Web/Other**: Fallback software attestation

Fields:
- `token` - Platform-specific attestation token
- `platform` - Operating system (iOS, Android, Web)
- `deviceId` - Device identifier
- `isHardwareBacked` - Whether attestation uses hardware security module
- `challenge` - Challenge nonce used in attestation (matches `challengeNonce`)
- `metadata` - Platform-specific attestation details

#### PGP Signature
Cryptographic signature of the entire manifest:
- `signature` - PGP signature in ASCII-armored format
- `publicKey` - PGP public key in ASCII-armored format
- `publicKeyFingerprint` - Key fingerprint for quick lookup

## Implementation

### Recording Phase

1. **Start Session**
   - Generate unique `sessionId` and `challengeNonce`
   - Request hardware device attestation with challenge nonce
   - Initialize ProofMode session

2. **Capture Frames**
   - During recording, periodically capture video frames
   - Generate SHA256 hash of each frame
   - Store frame hashes with timestamps
   - Optionally collect sensor data (accelerometer, gyroscope, etc.)

3. **Handle Pauses**
   - When recording pauses, stop current segment
   - Begin collecting pause proof data (sensor readings, interactions)
   - When resuming, start new segment

4. **Finalize Session**
   - Stop recording and close final segment
   - Hash complete video file
   - Compile ProofManifest with all segments, pauses, and interactions
   - Sign manifest with PGP private key
   - Attach ProofManifest to video event as tags

### Verification Phase

To verify a ProofMode video, clients should:

1. **Extract ProofManifest**
   - Parse `proofmode` tag from video event
   - Extract `deviceAttestation` and `pgpSignature` from separate tags

2. **Verify PGP Signature**
   - Extract PGP public key from manifest
   - Verify signature of manifest JSON
   - Check public key fingerprint matches `pgp_fingerprint` tag

3. **Verify Device Attestation** (if present)
   - Validate attestation token against platform-specific APIs
   - Verify challenge nonce matches manifest `challengeNonce`
   - Check attestation timestamp is recent (within 24 hours of recording)

4. **Verify Frame Hashes** (advanced)
   - Re-encode video to extract individual frames
   - Generate SHA256 hashes of extracted frames
   - Compare against hashes in manifest segments
   - Verify frame count and timestamps match recording duration

5. **Verify Recording Continuity**
   - Check that segment timestamps are contiguous
   - Verify pause durations match gaps between segments
   - Validate total recording duration matches video length

6. **Display Verification Badge**
   - `verified_mobile` - Show "Verified" badge with hardware attestation icon
   - `verified_web` - Show "Signed" badge
   - `basic_proof` - Show "Basic Proof" indicator
   - `unverified` - No badge or "Unverified" indicator

## Example Event

```json
{
  "kind": 34236,
  "pubkey": "...",
  "created_at": 1730326800,
  "tags": [
    ["d", "unique-video-identifier"],
    ["title", "My Verified Video"],
    ["url", "https://media.example.com/video.mp4", "720x1280"],
    ["thumb", "https://media.example.com/thumb.jpg", "720x1280"],
    ["duration", "6"],
    ["verification", "verified_mobile"],
    ["proofmode", "{\"sessionId\":\"session_1730326800000_1234\",\"challengeNonce\":\"a1b2c3d4e5f6789\",\"vineSessionStart\":\"2025-10-30T10:00:00.000Z\",\"vineSessionEnd\":\"2025-10-30T10:00:06.500Z\",\"totalDuration\":6500,\"recordingDuration\":6000,\"segments\":[{\"segmentId\":\"segment_1\",\"startTime\":\"2025-10-30T10:00:00.000Z\",\"endTime\":\"2025-10-30T10:00:06.000Z\",\"frameHashes\":[\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"]}],\"pauseProofs\":[],\"interactions\":[{\"timestamp\":\"2025-10-30T10:00:00.000Z\",\"interactionType\":\"start\",\"coordinates\":{\"x\":180,\"y\":640}}],\"finalVideoHash\":\"d4e5f6a7b8c9...\"}"],
    ["device_attestation", "AAABBBCCC..."],
    ["pgp_fingerprint", "1A2B3C4D5E6F7890..."]
  ],
  "content": "Check out this verified video!",
  "sig": "..."
}
```

## Security Considerations

### Threat Model

ProofMode protects against:
- ✅ **Post-recording video editing** - Frame hashes detect any modifications
- ✅ **Deepfakes and synthetic videos** - Hardware attestation proves real device
- ✅ **Timestamp manipulation** - Device attestation includes trusted timestamps
- ✅ **Replay attacks** - Challenge nonce prevents reuse of attestations

ProofMode does NOT protect against:
- ❌ **Screen recording** - A user can screen-record another video
- ❌ **Camera lens manipulation** - Physical objects placed in front of camera
- ❌ **Compromised devices** - Rooted/jailbroken devices may forge attestations
- ❌ **Social engineering** - User can intentionally create misleading content

### Privacy Considerations

- **Device Identifiers**: The `deviceId` field may be sensitive. Clients should:
  - Hash or truncate device IDs before publishing
  - Allow users to opt-out of device attestation
  - Clearly indicate when ProofMode is active

- **Sensor Data**: Accelerometer and gyroscope data may reveal user location or behavior. Clients should:
  - Allow disabling sensor data collection
  - Sanitize or omit sensitive sensor readings
  - Aggregate sensor data to reduce precision

- **PGP Keys**: Users should be able to:
  - Rotate PGP keys periodically
  - Revoke compromised keys
  - Use separate keys for different purposes

### Verification Best Practices

Verifying clients should:

1. **Always check PGP signature** - This is the minimum verification
2. **Validate device attestation** when present - But gracefully handle missing/invalid attestations
3. **Display verification level prominently** - Users should understand confidence level
4. **Cache verification results** - Re-verification is expensive
5. **Handle expired attestations** - Attestations may expire after 24-48 hours
6. **Warn on missing proofs** - But don't assume malice if ProofMode is absent

## Reference Implementation

OpenVine provides a complete reference implementation:
- **Recording**: `ProofModeSessionService` in OpenVine mobile app
- **Publishing**: `VideoEventPublisher` adds ProofMode tags to Nostr events
- **Verification**: `ProofModeHelpers` and verification UI components

Source: https://github.com/openvine/openvine

## Backwards Compatibility

This NIP is fully backwards compatible:
- Events without ProofMode tags are treated as unverified
- Older clients ignore ProofMode tags
- ProofMode is opt-in - videos without it still work normally

## Future Extensions

Possible future enhancements:

1. **Witness Signatures** - Multiple devices co-sign the same recording
2. **Location Proofs** - GPS coordinates with cryptographic verification
3. **Biometric Proof** - Prove human presence during recording
4. **Chain of Custody** - Track video transfer and handling
5. **Selective Disclosure** - Zero-knowledge proofs for privacy-preserving verification

## References

- [NIP-01: Basic protocol flow description](https://github.com/nostr-protocol/nips/blob/master/01.md)
- [NIP-71: Video Events](https://github.com/nostr-protocol/nips/blob/master/71.md)
- [iOS App Attest](https://developer.apple.com/documentation/devicecheck/establishing_your_app_s_integrity)
- [Android Play Integrity](https://developer.android.com/google/play/integrity)
- [ProofMode Original Project](https://proofmode.org)

## Authors

- Evan Henshaw-Plath (Rabble)

## License

This NIP is released into the public domain.