commit 8b7b77c2e82e3924527bdf4d0d24a652200d1741
parent 1f6585e4193dd4f9ee2d47b2c85606c54cdbd7d6
Author: William Casarin <jb55@jb55.com>
Date: Sun, 25 Dec 2022 13:42:56 -0800
Merge PR #111: Save the private key to the iOS keychain and not user defaults
Closes: #111
Changelog-Changed: Save privkey in keychain instead of user defaults
Diffstat:
7 files changed, 93 insertions(+), 19 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -130,6 +130,7 @@
4CEE2AF9280B2EAC00AB5EEF /* PowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */; };
4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */; };
E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E990020E2955F837003BBC5A /* EditMetadataView.swift */; };
+ 6C7DE41F2955169800E66263 /* Vault in Frameworks */ = {isa = PBXBuildFile; productRef = 6C7DE41E2955169800E66263 /* Vault */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -316,6 +317,7 @@
buildActionMask = 2147483647;
files = (
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */,
+ 6C7DE41F2955169800E66263 /* Vault in Frameworks */,
4CE6DF1227F7A2B300C66700 /* Starscream in Frameworks */,
4C649881286E0EE300EAE2B3 /* secp256k1 in Frameworks */,
);
@@ -626,6 +628,7 @@
4CE6DF1127F7A2B300C66700 /* Starscream */,
4C649880286E0EE300EAE2B3 /* secp256k1 */,
4C06670328FC7EC500038D2A /* Kingfisher */,
+ 6C7DE41E2955169800E66263 /* Vault */,
);
productName = damus;
productReference = 4CE6DEE327F7A08100C66700 /* damus.app */;
@@ -705,6 +708,7 @@
4C64987F286E0EE300EAE2B3 /* XCRemoteSwiftPackageReference "secp256k1" */,
4C06670228FC7EC500038D2A /* XCRemoteSwiftPackageReference "Kingfisher" */,
3169CAE9294FCABA00EE4006 /* XCRemoteSwiftPackageReference "Shimmer" */,
+ 6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */,
);
productRefGroup = 4CE6DEE427F7A08100C66700 /* Products */;
projectDirPath = "";
@@ -1242,6 +1246,14 @@
minimumVersion = 4.0.0;
};
};
+ 6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/SparrowTek/Vault";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 1.0.0;
+ };
+ };
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@@ -1260,6 +1272,11 @@
package = 4CE6DF1027F7A2B300C66700 /* XCRemoteSwiftPackageReference "Starscream" */;
productName = Starscream;
};
+ 6C7DE41E2955169800E66263 /* Vault */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */;
+ productName = Vault;
+ };
/* End XCSwiftPackageProductDependency section */
};
rootObject = 4CE6DEDB27F7A08100C66700 /* Project object */;
diff --git a/damus.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/damus.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -34,6 +34,15 @@
"revision" : "df8d82047f6654d8e4b655d1b1525c64e1059d21",
"version" : "4.0.4"
}
+ },
+ {
+ "identity" : "vault",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/SparrowTek/Vault",
+ "state" : {
+ "revision" : "f5707fac23f4a17b3e5ed32dd444f502773615ae",
+ "version" : "1.0.2"
+ }
}
],
"version" : 2
diff --git a/damus/Util/Keys.swift b/damus/Util/Keys.swift
@@ -7,6 +7,7 @@
import Foundation
import secp256k1
+import Vault
let PUBKEY_HRP = "npub"
let PRIVKEY_HRP = "nsec"
@@ -29,6 +30,12 @@ enum Bech32Key {
case sec(String)
}
+struct DamusKeychainConfiguration: KeychainConfiguration {
+ var serviceName = "damus"
+ var accessGroup: String? = nil
+ var accountName = "privkey"
+}
+
func decode_bech32_key(_ key: String) -> Bech32Key? {
guard let decoded = try? bech32_decode(key) else {
return nil
@@ -86,32 +93,38 @@ func save_pubkey(pubkey: String) {
UserDefaults.standard.set(pubkey, forKey: "pubkey")
}
-func save_privkey(privkey: String) {
- UserDefaults.standard.set(privkey, forKey: "privkey")
+func save_privkey(privkey: String) throws {
+ try Vault.savePrivateKey(privkey, keychainConfiguration: DamusKeychainConfiguration())
}
-func clear_saved_privkey() {
- UserDefaults.standard.removeObject(forKey: "privkey")
+func clear_saved_privkey() throws {
+ try Vault.deletePrivateKey(keychainConfiguration: DamusKeychainConfiguration())
}
func clear_saved_pubkey() {
UserDefaults.standard.removeObject(forKey: "pubkey")
}
-func save_keypair(pubkey: String, privkey: String) {
+func save_keypair(pubkey: String, privkey: String) throws {
save_pubkey(pubkey: pubkey)
- save_privkey(privkey: privkey)
+ try save_privkey(privkey: privkey)
}
-func clear_keypair() {
- clear_saved_privkey()
+func clear_keypair() throws {
+ try clear_saved_privkey()
clear_saved_pubkey()
}
func get_saved_keypair() -> Keypair? {
- get_saved_pubkey().flatMap { pubkey in
- let privkey = get_saved_privkey()
- return Keypair(pubkey: pubkey, privkey: privkey)
+ do {
+ try removePrivateKeyFromUserDefaults()
+
+ return get_saved_pubkey().flatMap { pubkey in
+ let privkey = get_saved_privkey()
+ return Keypair(pubkey: pubkey, privkey: privkey)
+ }
+ } catch {
+ return nil
}
}
@@ -120,5 +133,11 @@ func get_saved_pubkey() -> String? {
}
func get_saved_privkey() -> String? {
- return UserDefaults.standard.string(forKey: "privkey")
+ try? Vault.getPrivateKey(keychainConfiguration: DamusKeychainConfiguration())
+}
+
+fileprivate func removePrivateKeyFromUserDefaults() throws {
+ guard let privKey = UserDefaults.standard.string(forKey: "privkey") else { return }
+ try save_privkey(privkey: privKey)
+ UserDefaults.standard.removeObject(forKey: "privkey")
}
diff --git a/damus/Views/LoginView.swift b/damus/Views/LoginView.swift
@@ -52,14 +52,24 @@ struct LoginView: View {
func process_login(_ key: ParsedKey, is_pubkey: Bool) -> Bool {
switch key {
case .priv(let priv):
- save_privkey(privkey: priv)
+ do {
+ try save_privkey(privkey: priv)
+ } catch {
+ return false
+ }
+
guard let pk = privkey_to_pubkey(privkey: priv) else {
return false
}
save_pubkey(pubkey: pk)
case .pub(let pub):
- clear_saved_privkey()
+ do {
+ try clear_saved_privkey()
+ } catch {
+ return false
+ }
+
save_pubkey(pubkey: pub)
case .nip05(let id):
@@ -82,10 +92,20 @@ struct LoginView: View {
case .hex(let hexstr):
if is_pubkey {
- clear_saved_privkey()
+ do {
+ try clear_saved_privkey()
+ } catch {
+ return false
+ }
+
save_pubkey(pubkey: hexstr)
} else {
- save_privkey(privkey: hexstr)
+ do {
+ try save_privkey(privkey: hexstr)
+ } catch {
+ return false
+ }
+
guard let pk = privkey_to_pubkey(privkey: hexstr) else {
return false
}
diff --git a/damus/Views/SaveKeysView.swift b/damus/Views/SaveKeysView.swift
@@ -107,8 +107,13 @@ struct SaveKeysView: View {
self.pool.send(.event(contacts_ev))
}
- save_keypair(pubkey: account.pubkey, privkey: account.privkey)
- notify(.login, account.keypair)
+ do {
+ try save_keypair(pubkey: account.pubkey, privkey: account.privkey)
+ notify(.login, account.keypair)
+ } catch {
+ self.error = "Failed to save keys"
+ }
+
case .error(let err):
self.loading = false
self.error = "\(err.debugDescription)"
diff --git a/damus/damus.entitlements b/damus/damus.entitlements
@@ -4,5 +4,9 @@
<dict>
<key>aps-environment</key>
<string>development</string>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>$(AppIdentifierPrefix)com.jb55.damus2</string>
+ </array>
</dict>
</plist>
diff --git a/damus/damusApp.swift b/damus/damusApp.swift
@@ -36,7 +36,7 @@ struct MainView: View {
}
}
.onReceive(handle_notify(.logout)) { _ in
- clear_keypair()
+ try? clear_keypair()
keypair = nil
}
.onAppear {