Security: jongan69/opendating-mobile
Security
User identity is a Nostr keypair generated via opendating-protocol's generateKeypair()
Uses @noble/curves secp256k1 underneath
Keys generated on-device, never transmitted
Key Storage (current v0.1 limitation)
The private key is persisted with expo-secure-store and loaded into the JavaScript OpenDatingClient for signing and encryption.
The advanced recovery screen can copy the raw recovery key to the clipboard after an explicit warning.
The key must never enter AsyncStorage, SQLite, logs, analytics, navigation params, or network payloads.
A device-bound native signer and passkey-encrypted recovery are required before production approval; see RELEASE-STATUS.md.
NDK core signs NIP-42 authentication through NDKPrivateKeySigner.
Protocol commands and encryption are performed inside the client facade.
This keeps protocol operations out of screens, but it is not the final native cryptographic boundary.
All relay communication over WSS (WebSocket Secure)
NIP-11 info fetched over HTTPS
NIP-42 AUTH required by relay
Challenge-response: relay issues challenge → client signs kind 22242 event
Challenges expire after 60 seconds, single-use, bound to relay URL
Reconnection requires re-authentication
NIP-44 : Application-level encryption for private content
NIP-59 : Gift wraps for private request/response routing
Conversation keys derived via ECDH (secp256k1)
Each private request uses a fresh random request_id
Raw GPS coordinates consumed internally, never stored
Only geohash_prefix (max 5 characters, ~5km precision) sent to backend
Country code optionally included (not required)
Location not persisted to any storage
NIP-17 direct messages encrypted end-to-end
Message plaintext never sent to relay (only encrypted gift wraps)
Decrypted messages not persisted to AsyncStorage
NDK cache stores encrypted Nostr events only
Profile information sent only through authorized discovery
Arbitrary profile enumeration prevented by relay
Current profile photos use hosted URLs. Revocable media references and short-lived authorized URLs are required before GA.
Applied locally immediately upon user action
Backend block.create sent asynchronously
Blocked users: cannot discover, like, or DM the blocker
Relay enforces blocks server-side
Blocks are private — blocked user is not notified
Reports encrypted to moderation service
Reporter identity protected
Evidence event IDs optionally included
Report content never in public Nostr tags
Removes match and messaging capability
Unmatched user not explicitly notified why
Reporting remains available after unmatch
Anyone receiving information (profile, messages) can screenshot it
The app cannot prevent this
This limitation is disclosed in privacy screen
No server-side key recovery
Users must back up their private key
Lost keys = lost account (same as self-custody crypto wallet)
The relay could theoretically observe encrypted traffic metadata
Content is encrypted, but timing and volume patterns are visible
This is inherent to the Nostr architecture
Never log private keys, nsec, or decrypted content
Never put sensitive data in React Navigation params
Never send raw GPS to any external service
Always validate service responses against expected service identity
Use fresh request_id for every operation
Clear sensitive state on logout/account deletion
There aren't any published security advisories
You can’t perform that action at this time.