import Foundation import P256K /// Manages the secp256k1 identity used by BitChat's Nostr relay features, /// including the proprietary private-envelope transport. struct NostrIdentity: Codable { let privateKey: Data let publicKey: Data let npub: String // Bech32-encoded public key /// Memberwise initializer init(privateKey: Data, publicKey: Data, npub: String, createdAt _: Date) { self.privateKey = privateKey self.publicKey = publicKey self.npub = npub } /// Generate a new Nostr identity static func generate() throws -> NostrIdentity { // Generate Schnorr key for Nostr let schnorrKey = try P256K.Schnorr.PrivateKey() let xOnlyPubkey = Data(schnorrKey.xonly.bytes) let npub = try Bech32.encode(hrp: "npub", data: xOnlyPubkey) return NostrIdentity( privateKey: schnorrKey.dataRepresentation, publicKey: xOnlyPubkey, // Store x-only public key npub: npub, createdAt: Date() ) } /// Initialize from existing private key data init(privateKeyData: Data) throws { let schnorrKey = try P256K.Schnorr.PrivateKey(dataRepresentation: privateKeyData) let xOnlyPubkey = Data(schnorrKey.xonly.bytes) self.privateKey = privateKeyData self.publicKey = xOnlyPubkey self.npub = try Bech32.encode(hrp: "npub", data: xOnlyPubkey) } /// Get Schnorr signing key for Nostr event signatures func schnorrSigningKey() throws -> P256K.Schnorr.PrivateKey { try P256K.Schnorr.PrivateKey(dataRepresentation: privateKey) } /// Get hex-encoded public key (for Nostr events) var publicKeyHex: String { // Public key is already stored as x-only (32 bytes) return publicKey.hexEncodedString() } }