mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 02:45:19 +00:00
Transitive verification: vouch for verified peers over Noise
When a Noise session establishes with a peer I verified and that peer advertises the .vouch capability, send signed attestations (up to 16, most recently verified first, at most once per peer per 24h) for the OTHER fingerprints I verified. Receivers accept vouches only from senders they verified themselves, verify the Ed25519 signature against the sender's announce-bound signing key, and surface the result as a new derived trust tier: vouched (unfilled seal) between casual and trusted. Protocol: - NoisePayloadType.vouch = 0x12 carries a batch of TLV attestations: voucheeFingerprint (32B), voucheeSigningKey (32B), timestamp (uint64 ms BE), Ed25519 signature over "bitchat-vouch-v1" | fingerprint | signingKey | timestamp. The voucher is implicit in the authenticated session. - PeerCapabilities.localSupported now advertises .vouch. Storage (SecureIdentityStateManager / IdentityCache): - vouches keyed by vouchee, capped at 8 vouchers each; validity is recomputed on read (voucher still verified-by-me, < 30 days old), so unverifying a voucher retires their vouches without cascade deletes. - New IdentityCache fields are Optional so pre-existing encrypted caches decode cleanly; TrustLevel.vouched is inserted mid-ladder but raw values are strings, so persisted values are unaffected (and vouched itself is never persisted). - Panic wipe clears vouch state with the rest of the identity cache. UI: unfilled checkmark.seal badge in the mesh peer list (filled seal stays exclusive to verified) and a "vouched for by N people you verified" section with voucher names in FingerprintView; VoiceOver labels and xcstrings entries included. Tests: attestation encode/decode + signature (forged/tampered/expired), accept-policy gates, batch cap, trust-level derivation incl. voucher invalidation, persistence compat, and coordinator exchange/accept policies. Full macOS suite: 1088 tests passing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -107,12 +107,55 @@ final class MockIdentityManager: SecureIdentityStateManagerProtocol {
|
||||
func removeEphemeralSession(peerID: PeerID) {}
|
||||
|
||||
func setVerified(fingerprint: String, verified: Bool) {}
|
||||
|
||||
|
||||
func isVerified(fingerprint: String) -> Bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
func getVerifiedFingerprints() -> Set<String> {
|
||||
Set()
|
||||
}
|
||||
|
||||
// MARK: Vouching (transitive verification)
|
||||
|
||||
private var vouchesByVouchee: [String: [VouchRecord]] = [:]
|
||||
private var vouchBatchSentAt: [String: Date] = [:]
|
||||
|
||||
@discardableResult
|
||||
func recordVouch(voucheeFingerprint: String, voucherFingerprint: String, timestamp: Date) -> Bool {
|
||||
guard voucheeFingerprint != voucherFingerprint else { return false }
|
||||
var records = vouchesByVouchee[voucheeFingerprint] ?? []
|
||||
records.removeAll { $0.voucherFingerprint == voucherFingerprint }
|
||||
records.append(VouchRecord(voucherFingerprint: voucherFingerprint, timestamp: timestamp))
|
||||
vouchesByVouchee[voucheeFingerprint] = records
|
||||
return true
|
||||
}
|
||||
|
||||
func validVouchers(for fingerprint: String) -> [VouchRecord] {
|
||||
vouchesByVouchee[fingerprint] ?? []
|
||||
}
|
||||
|
||||
func isVouched(fingerprint: String) -> Bool {
|
||||
!(vouchesByVouchee[fingerprint] ?? []).isEmpty
|
||||
}
|
||||
|
||||
func effectiveTrustLevel(for fingerprint: String) -> TrustLevel {
|
||||
socialIdentities[fingerprint]?.trustLevel ?? .unknown
|
||||
}
|
||||
|
||||
func lastVouchBatchSent(to fingerprint: String) -> Date? {
|
||||
vouchBatchSentAt[fingerprint]
|
||||
}
|
||||
|
||||
func markVouchBatchSent(to fingerprint: String, at date: Date) {
|
||||
vouchBatchSentAt[fingerprint] = date
|
||||
}
|
||||
|
||||
func signingPublicKey(forFingerprint fingerprint: String) -> Data? {
|
||||
nil
|
||||
}
|
||||
|
||||
func mostRecentlyVerifiedFingerprints(limit: Int, excluding fingerprint: String) -> [String] {
|
||||
[]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user