Skip to content

Commit d33e63c

Browse files
SimplyDannymssun
authored andcommitted
Add ability to import SSH keys from the Files app
1 parent 94a5f8c commit d33e63c

File tree

8 files changed

+176
-0
lines changed

8 files changed

+176
-0
lines changed

pass.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
3032327422C7F710009EBD9C /* KeyFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3032327322C7F710009EBD9C /* KeyFileManager.swift */; };
2121
3032328A22C9FBA2009EBD9C /* KeyFileManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3032328922C9FBA2009EBD9C /* KeyFileManagerTest.swift */; };
2222
3032328E22CBD4CD009EBD9C /* CryptographicKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3032328D22CBD4CD009EBD9C /* CryptographicKeys.swift */; };
23+
30650E7123F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30650E7023F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift */; };
2324
30650E7323F847FC005CCD5E /* KeyImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30650E7223F847FC005CCD5E /* KeyImporter.swift */; };
2425
3066AD6823EE0D6500F65535 /* PGPKeyImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3066AD6723EE0D6500F65535 /* PGPKeyImporter.swift */; };
2526
30697C2A21F63C5A0064FCAC /* NotificationNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2321F63C580064FCAC /* NotificationNames.swift */; };
@@ -242,6 +243,7 @@
242243
3032327322C7F710009EBD9C /* KeyFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyFileManager.swift; sourceTree = "<group>"; };
243244
3032328922C9FBA2009EBD9C /* KeyFileManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyFileManagerTest.swift; sourceTree = "<group>"; };
244245
3032328D22CBD4CD009EBD9C /* CryptographicKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptographicKeys.swift; sourceTree = "<group>"; };
246+
30650E7023F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHKeyFileImportTableViewController.swift; sourceTree = "<group>"; };
245247
30650E7223F847FC005CCD5E /* KeyImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyImporter.swift; sourceTree = "<group>"; };
246248
3066AD6723EE0D6500F65535 /* PGPKeyImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PGPKeyImporter.swift; sourceTree = "<group>"; };
247249
30697C2321F63C580064FCAC /* NotificationNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationNames.swift; sourceTree = "<group>"; };
@@ -721,6 +723,7 @@
721723
DCAAF7441E2FA66800AB94BC /* SettingsTableViewController.swift */,
722724
DC037CA91E4B8EAE00609409 /* SpecialThanksTableViewController.swift */,
723725
DCC441531E916382008A90C4 /* SSHKeyArmorImportTableViewController.swift */,
726+
30650E7023F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift */,
724727
DC8963BF1E38EEB900828B09 /* SSHKeyUrlImportTableViewController.swift */,
725728
);
726729
path = Controllers;
@@ -1383,6 +1386,7 @@
13831386
A2A61C201EEFABAD00CFE063 /* UtilsExtension.swift in Sources */,
13841387
DC8963C01E38EEB900828B09 /* SSHKeyUrlImportTableViewController.swift in Sources */,
13851388
3066AD6823EE0D6500F65535 /* PGPKeyImporter.swift in Sources */,
1389+
30650E7123F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift in Sources */,
13861390
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */,
13871391
DCFB77AB1E503729008DE471 /* ContentProvider.swift in Sources */,
13881392
DCA0499C1E3362F400522E8F /* PGPKeyUrlImportTableViewController.swift in Sources */,

pass/Base.lproj/Main.storyboard

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@
496496
<segue destination="7K9-cE-9qq" kind="unwind" identifier="saveGitServerSettingSegue" unwindAction="saveGitServerSettingWithSegue:" id="5UN-sC-xCA"/>
497497
<segue destination="hqC-Ic-NMi" kind="show" identifier="setGitSSHKeyByURLSegue" id="AP7-FV-2Ow"/>
498498
<segue destination="WgM-cY-mig" kind="show" identifier="setGitSSHKeyByArmorSegue" id="HLm-0q-hUg"/>
499+
<segue destination="Jnt-d8-bQx" kind="show" identifier="setGitSSHKeyByFileSegue" id="4Bn-TN-gBI"/>
499500
</connections>
500501
</tableViewController>
501502
<placeholder placeholderIdentifier="IBFirstResponder" id="7c1-c7-Qyp" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -1878,6 +1879,87 @@ Secret Question 1: What is your childhood best friend's most bizarre superhero f
18781879
</objects>
18791880
<point key="canvasLocation" x="3845" y="2969"/>
18801881
</scene>
1882+
<!--SSH Key-->
1883+
<scene sceneID="kOg-Uk-VyV">
1884+
<objects>
1885+
<tableViewController id="Jnt-d8-bQx" customClass="SSHKeyFileImportTableViewController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
1886+
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="urc-Su-PL8">
1887+
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
1888+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
1889+
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
1890+
<sections>
1891+
<tableViewSection id="Nlg-0d-JGw">
1892+
<cells>
1893+
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="11" reuseIdentifier="sshPrivateKeyFile" textLabel="1h3-cQ-4bj" detailTextLabel="pqH-wg-EIn" style="IBUITableViewCellStyleSubtitle" id="yyX-RO-fws" userLabel="SSH private key from file description">
1894+
<rect key="frame" x="0.0" y="18" width="414" height="44"/>
1895+
<autoresizingMask key="autoresizingMask"/>
1896+
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="yyX-RO-fws" id="QcH-CI-X9n">
1897+
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
1898+
<autoresizingMask key="autoresizingMask"/>
1899+
<subviews>
1900+
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="ASCII-Armor Keys" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="1h3-cQ-4bj">
1901+
<rect key="frame" x="20.000000000000007" y="6" width="121.66666666666667" height="17"/>
1902+
<autoresizingMask key="autoresizingMask"/>
1903+
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="14"/>
1904+
<nil key="textColor"/>
1905+
<nil key="highlightedColor"/>
1906+
</label>
1907+
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="SshAsciiArmorFileExplanation." lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="pqH-wg-EIn" customClass="UICodeHighlightingLabel" customModule="pass" customModuleProvider="target">
1908+
<rect key="frame" x="20" y="23" width="191.33333333333334" height="16.333333333333332"/>
1909+
<autoresizingMask key="autoresizingMask"/>
1910+
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
1911+
<color key="textColor" white="0.40782000000000002" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
1912+
<nil key="highlightedColor"/>
1913+
</label>
1914+
</subviews>
1915+
</tableViewCellContentView>
1916+
</tableViewCell>
1917+
</cells>
1918+
</tableViewSection>
1919+
<tableViewSection headerTitle="PRIVATE KEY" id="pEq-Ii-lwe" userLabel="PRIVATE KEY">
1920+
<cells>
1921+
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="sshPrivateKeyFile" textLabel="9KE-VA-cx2" rowHeight="52" style="IBUITableViewCellStyleDefault" id="qWo-Q3-m4Z" userLabel="SSH private key file">
1922+
<rect key="frame" x="0.0" y="118" width="414" height="52"/>
1923+
<autoresizingMask key="autoresizingMask"/>
1924+
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="qWo-Q3-m4Z" id="Jjt-3W-boo">
1925+
<rect key="frame" x="0.0" y="0.0" width="383" height="52"/>
1926+
<autoresizingMask key="autoresizingMask"/>
1927+
<subviews>
1928+
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Select file ..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9KE-VA-cx2">
1929+
<rect key="frame" x="20" y="0.0" width="355" height="52"/>
1930+
<autoresizingMask key="autoresizingMask"/>
1931+
<fontDescription key="fontDescription" type="system" pointSize="17"/>
1932+
<nil key="textColor"/>
1933+
<nil key="highlightedColor"/>
1934+
</label>
1935+
</subviews>
1936+
</tableViewCellContentView>
1937+
</tableViewCell>
1938+
</cells>
1939+
</tableViewSection>
1940+
</sections>
1941+
<connections>
1942+
<outlet property="dataSource" destination="Jnt-d8-bQx" id="Dse-Bk-idM"/>
1943+
<outlet property="delegate" destination="Jnt-d8-bQx" id="fKs-GA-48h"/>
1944+
</connections>
1945+
</tableView>
1946+
<navigationItem key="navigationItem" title="SSH Key" id="vaA-as-6yJ">
1947+
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="OmP-jt-rJh">
1948+
<connections>
1949+
<action selector="doneButtonTapped:" destination="Jnt-d8-bQx" id="skg-sj-oLw"/>
1950+
</connections>
1951+
</barButtonItem>
1952+
</navigationItem>
1953+
<connections>
1954+
<outlet property="sshPrivateKeyFile" destination="qWo-Q3-m4Z" id="vrz-89-rLv"/>
1955+
<segue destination="T4H-XT-sbN" kind="unwind" identifier="importSSHKeySegue" unwindAction="importSSHKeyWithSegue:" id="yy9-zG-Yes"/>
1956+
</connections>
1957+
</tableViewController>
1958+
<placeholder placeholderIdentifier="IBFirstResponder" id="rw2-Uq-xF8" userLabel="First Responder" sceneMemberID="firstResponder"/>
1959+
<exit id="T4H-XT-sbN" userLabel="Exit" sceneMemberID="exit"/>
1960+
</objects>
1961+
<point key="canvasLocation" x="6990" y="2967"/>
1962+
</scene>
18811963
</scenes>
18821964
<resources>
18831965
<image name="Lock" width="25" height="25"/>

pass/Controllers/GitRepositorySettingsTableViewController.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ class GitRepositorySettingsTableViewController: UITableViewController {
247247
optionMenu.addAction(UIAlertAction(title: SSHKeyArmorImportTableViewController.menuLabel, style: .default) { _ in
248248
self.performSegue(withIdentifier: "setGitSSHKeyByArmorSegue", sender: self)
249249
})
250+
optionMenu.addAction(UIAlertAction(title: SSHKeyFileImportTableViewController.menuLabel, style: .default) { _ in
251+
self.performSegue(withIdentifier: "setGitSSHKeyByFileSegue", sender: self)
252+
})
250253

251254
if isReadyToUse() {
252255
optionMenu.addAction(UIAlertAction(title: "\(Self.menuLabel) (\("Import".localize()))", style: .default) { _ in
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//
2+
// SSHKeyFileImportTableViewController.swift
3+
// pass
4+
//
5+
// Created by Danny Moesch on 15.02.20.
6+
// Copyright © 2020 Bob Sun. All rights reserved.
7+
//
8+
9+
import passKit
10+
import SVProgressHUD
11+
12+
class SSHKeyFileImportTableViewController: AutoCellHeightUITableViewController {
13+
14+
@IBOutlet weak var sshPrivateKeyFile: UITableViewCell!
15+
16+
private var privateKey: String? = nil
17+
18+
@IBAction func doneButtonTapped(_ sender: Any) {
19+
performSegue(withIdentifier: "importSSHKeySegue", sender: self)
20+
}
21+
22+
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
23+
let cell = tableView.cellForRow(at: indexPath)
24+
let picker = UIDocumentPickerViewController(documentTypes: ["public.data"], in: .open)
25+
cell?.isSelected = false
26+
guard cell == sshPrivateKeyFile else {
27+
return
28+
}
29+
picker.delegate = self
30+
if #available(iOS 13.0, *) {
31+
picker.shouldShowFileExtensions = true
32+
}
33+
present(picker, animated: true, completion: nil)
34+
}
35+
}
36+
37+
extension SSHKeyFileImportTableViewController: UIDocumentPickerDelegate {
38+
39+
func documentPicker(_: UIDocumentPickerViewController, didPickDocumentsAt url: [URL]) {
40+
guard let url = url.first else {
41+
return
42+
}
43+
let fileName = url.lastPathComponent
44+
do {
45+
privateKey = try String(contentsOf: url, encoding: .ascii)
46+
sshPrivateKeyFile.textLabel?.text = fileName
47+
} catch {
48+
Utils.alert(title: "CannotImportFile".localize(), message: "FileCannotBeImported.".localize(fileName), controller: self)
49+
}
50+
}
51+
}
52+
53+
extension SSHKeyFileImportTableViewController: KeyImporter {
54+
55+
static let keySource = KeySource.file
56+
static let label = "LoadFromFiles".localize()
57+
58+
func isReadyToUse() -> Bool {
59+
guard privateKey != nil else {
60+
Utils.alert(title: "CannotSave".localize(), message: "SetPrivateKeyUrl.".localize(), controller: self)
61+
return false
62+
}
63+
return true
64+
}
65+
66+
func importKeys() throws {
67+
guard let privateKey = privateKey else {
68+
return
69+
}
70+
try KeyFileManager.PrivateSsh.importKey(from: privateKey)
71+
}
72+
}

pass/de.lproj/Localizable.strings

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ gibt den Schlüssel in diesem speziellen Format aus. Die Zwischenablage wird nac
280280

281281
gibt den Schlüssel in diesem speziellen Format aus. Kopiere ihn so zu einem Key-Server.";
282282

283+
"SshAsciiArmorFileExplanation." = "Das Format \"ASCII-Armor\" ist anders als das Binärformat eine einfache Zeichenkette. Der Befehl
284+
285+
$ cat ~/.ssh/id_rsa
286+
287+
gibt den Schlüssel in diesem speziellen Format aus. Kopiere ihn so zu einem Speicherort, der für die Dateien-App zugänglich ist.";
288+
283289
"GpgAsciiArmorCopyExplanation." = "GnuPG unterstützt die Kommandozeilenoption \"-a\", welche die Schlüssel im Format \"ASCII-Armor\" ausgibt. Es ist anders als das Binärformat eine einfache Zeichenkette. Die Befehle
284290

285291
$ gpg --export -a KEY_ID

pass/de.lproj/Main.strings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
/* Class = "UIBarButtonItem"; title = "Back"; ObjectID = "9yM-Mg-Cg8"; */
2424
"9yM-Mg-Cg8.title" = "Zurück";
2525

26+
/* Class = "UILabel"; text = "Select file ..."; ObjectID = "9KE-VA-cx2"; */
27+
"9KE-VA-cx2.text" = "Datei auswählen ...";
28+
2629
/* Class = "UILabel"; text = "Private Key URL"; ObjectID = "C2w-dd-roS"; */
2730
"C2w-dd-roS.text" = "URL des privaten Schlüssels";
2831

pass/en.lproj/Localizable.strings

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ to get the key in this specific format. The clipboard will be cleared 45s after
280280

281281
to get the key in this specific format. Subsequently, copy it to your secured key server.";
282282

283+
"SshAsciiArmorFileExplanation." = "The ASCII-armored key format is similar to unencoded documents rather than the binary format. Use
284+
285+
$ cat ~/.ssh/id_rsa
286+
287+
to get the key in this specific format. Subsequently, copy it to a location accessible by the Files app.";
288+
283289
"GpgAsciiArmorCopyExplanation." = "GnuPG supports the command-line option \"-a\" that causes output to be generated in an ASCII-armored format similar to unencoded documents rather than the binary format. Use
284290

285291
$ gpg --export -a KEY_ID

pass/en.lproj/Main.strings

232 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)