initial commit: Proximity iOS app proposal, full Swift code scaffold, reference backend, testing docs, generated Xcode project
This commit is contained in:
57
Proximity/Services/Security/CryptoManager.swift
Normal file
57
Proximity/Services/Security/CryptoManager.swift
Normal file
@@ -0,0 +1,57 @@
|
||||
import Foundation
|
||||
import CryptoKit
|
||||
|
||||
/// End-to-end encryption for revealed conversations.
|
||||
///
|
||||
/// Uses X25519 key agreement + ChaChaPoly AEAD, the same primitives family
|
||||
/// used by Signal. The server only ever sees ciphertext and opaque key IDs —
|
||||
/// it cannot read message contents.
|
||||
struct CryptoManager {
|
||||
|
||||
// MARK: - Key pair
|
||||
|
||||
func generateKeyPair() -> (privateKey: Curve25519.KeyAgreement.PrivateKey,
|
||||
publicKey: Curve25519.KeyAgreement.PublicKey) {
|
||||
let privateKey = Curve25519.KeyAgreement.PrivateKey()
|
||||
return (privateKey, privateKey.publicKey)
|
||||
}
|
||||
|
||||
// MARK: - Session establishment
|
||||
|
||||
/// Derive a shared symmetric session key from two key pairs.
|
||||
func deriveSessionKey(
|
||||
myPrivate: Curve25519.KeyAgreement.PrivateKey,
|
||||
theirPublic: Curve25519.KeyAgreement.PublicKey
|
||||
) throws -> SymmetricKey {
|
||||
let shared = try myPrivate.sharedSecretFromKeyAgreement(with: theirPublic)
|
||||
// Salt with a fixed app domain string to keep keys per-app.
|
||||
return shared.hkdfDerivedSymmetricKey(
|
||||
using: SHA256.self,
|
||||
salt: Data("proximity.e2e.v1".utf8),
|
||||
sharedInfo: Data(),
|
||||
outputByteCount: 32
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Message encryption
|
||||
|
||||
func encrypt(_ plaintext: Data, using key: SymmetricKey) throws -> Data {
|
||||
let sealed = try ChaChaPoly.seal(plaintext, using: key)
|
||||
return sealed.combined
|
||||
}
|
||||
|
||||
func decrypt(_ combined: Data, using key: SymmetricKey) throws -> Data {
|
||||
let box = try ChaChaPoly.SealedBox(combined: combined)
|
||||
return try ChaChaPoly.open(box, using: key)
|
||||
}
|
||||
|
||||
// MARK: - Signatures (for token authenticity)
|
||||
|
||||
func sign(_ data: Data, with key: Curve25519.Signing.PrivateKey) throws -> Data {
|
||||
try key.signature(for: data)
|
||||
}
|
||||
|
||||
func verify(_ data: Data, signature: Data, with key: Curve25519.Signing.PublicKey) -> Bool {
|
||||
key.isValidSignature(signature, for: data)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user