Add ability to import SSH keys from the Files app
This commit is contained in:
parent
94a5f8c501
commit
d33e63cd83
8 changed files with 176 additions and 0 deletions
|
|
@ -20,6 +20,7 @@
|
|||
3032327422C7F710009EBD9C /* KeyFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3032327322C7F710009EBD9C /* KeyFileManager.swift */; };
|
||||
3032328A22C9FBA2009EBD9C /* KeyFileManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3032328922C9FBA2009EBD9C /* KeyFileManagerTest.swift */; };
|
||||
3032328E22CBD4CD009EBD9C /* CryptographicKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3032328D22CBD4CD009EBD9C /* CryptographicKeys.swift */; };
|
||||
30650E7123F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30650E7023F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift */; };
|
||||
30650E7323F847FC005CCD5E /* KeyImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30650E7223F847FC005CCD5E /* KeyImporter.swift */; };
|
||||
3066AD6823EE0D6500F65535 /* PGPKeyImporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3066AD6723EE0D6500F65535 /* PGPKeyImporter.swift */; };
|
||||
30697C2A21F63C5A0064FCAC /* NotificationNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2321F63C580064FCAC /* NotificationNames.swift */; };
|
||||
|
|
@ -242,6 +243,7 @@
|
|||
3032327322C7F710009EBD9C /* KeyFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyFileManager.swift; sourceTree = "<group>"; };
|
||||
3032328922C9FBA2009EBD9C /* KeyFileManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyFileManagerTest.swift; sourceTree = "<group>"; };
|
||||
3032328D22CBD4CD009EBD9C /* CryptographicKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptographicKeys.swift; sourceTree = "<group>"; };
|
||||
30650E7023F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHKeyFileImportTableViewController.swift; sourceTree = "<group>"; };
|
||||
30650E7223F847FC005CCD5E /* KeyImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyImporter.swift; sourceTree = "<group>"; };
|
||||
3066AD6723EE0D6500F65535 /* PGPKeyImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PGPKeyImporter.swift; sourceTree = "<group>"; };
|
||||
30697C2321F63C580064FCAC /* NotificationNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationNames.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -721,6 +723,7 @@
|
|||
DCAAF7441E2FA66800AB94BC /* SettingsTableViewController.swift */,
|
||||
DC037CA91E4B8EAE00609409 /* SpecialThanksTableViewController.swift */,
|
||||
DCC441531E916382008A90C4 /* SSHKeyArmorImportTableViewController.swift */,
|
||||
30650E7023F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift */,
|
||||
DC8963BF1E38EEB900828B09 /* SSHKeyUrlImportTableViewController.swift */,
|
||||
);
|
||||
path = Controllers;
|
||||
|
|
@ -1383,6 +1386,7 @@
|
|||
A2A61C201EEFABAD00CFE063 /* UtilsExtension.swift in Sources */,
|
||||
DC8963C01E38EEB900828B09 /* SSHKeyUrlImportTableViewController.swift in Sources */,
|
||||
3066AD6823EE0D6500F65535 /* PGPKeyImporter.swift in Sources */,
|
||||
30650E7123F82AF8005CCD5E /* SSHKeyFileImportTableViewController.swift in Sources */,
|
||||
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */,
|
||||
DCFB77AB1E503729008DE471 /* ContentProvider.swift in Sources */,
|
||||
DCA0499C1E3362F400522E8F /* PGPKeyUrlImportTableViewController.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -496,6 +496,7 @@
|
|||
<segue destination="7K9-cE-9qq" kind="unwind" identifier="saveGitServerSettingSegue" unwindAction="saveGitServerSettingWithSegue:" id="5UN-sC-xCA"/>
|
||||
<segue destination="hqC-Ic-NMi" kind="show" identifier="setGitSSHKeyByURLSegue" id="AP7-FV-2Ow"/>
|
||||
<segue destination="WgM-cY-mig" kind="show" identifier="setGitSSHKeyByArmorSegue" id="HLm-0q-hUg"/>
|
||||
<segue destination="Jnt-d8-bQx" kind="show" identifier="setGitSSHKeyByFileSegue" id="4Bn-TN-gBI"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<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
|
|||
</objects>
|
||||
<point key="canvasLocation" x="3845" y="2969"/>
|
||||
</scene>
|
||||
<!--SSH Key-->
|
||||
<scene sceneID="kOg-Uk-VyV">
|
||||
<objects>
|
||||
<tableViewController id="Jnt-d8-bQx" customClass="SSHKeyFileImportTableViewController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<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">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<sections>
|
||||
<tableViewSection id="Nlg-0d-JGw">
|
||||
<cells>
|
||||
<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">
|
||||
<rect key="frame" x="0.0" y="18" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="yyX-RO-fws" id="QcH-CI-X9n">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="ASCII-Armor Keys" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="1h3-cQ-4bj">
|
||||
<rect key="frame" x="20.000000000000007" y="6" width="121.66666666666667" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="14"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<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">
|
||||
<rect key="frame" x="20" y="23" width="191.33333333333334" height="16.333333333333332"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
|
||||
<color key="textColor" white="0.40782000000000002" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="PRIVATE KEY" id="pEq-Ii-lwe" userLabel="PRIVATE KEY">
|
||||
<cells>
|
||||
<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">
|
||||
<rect key="frame" x="0.0" y="118" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="qWo-Q3-m4Z" id="Jjt-3W-boo">
|
||||
<rect key="frame" x="0.0" y="0.0" width="383" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Select file ..." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9KE-VA-cx2">
|
||||
<rect key="frame" x="20" y="0.0" width="355" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="Jnt-d8-bQx" id="Dse-Bk-idM"/>
|
||||
<outlet property="delegate" destination="Jnt-d8-bQx" id="fKs-GA-48h"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="SSH Key" id="vaA-as-6yJ">
|
||||
<barButtonItem key="rightBarButtonItem" style="done" systemItem="done" id="OmP-jt-rJh">
|
||||
<connections>
|
||||
<action selector="doneButtonTapped:" destination="Jnt-d8-bQx" id="skg-sj-oLw"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="sshPrivateKeyFile" destination="qWo-Q3-m4Z" id="vrz-89-rLv"/>
|
||||
<segue destination="T4H-XT-sbN" kind="unwind" identifier="importSSHKeySegue" unwindAction="importSSHKeyWithSegue:" id="yy9-zG-Yes"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="rw2-Uq-xF8" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="T4H-XT-sbN" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6990" y="2967"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Lock" width="25" height="25"/>
|
||||
|
|
|
|||
|
|
@ -247,6 +247,9 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
optionMenu.addAction(UIAlertAction(title: SSHKeyArmorImportTableViewController.menuLabel, style: .default) { _ in
|
||||
self.performSegue(withIdentifier: "setGitSSHKeyByArmorSegue", sender: self)
|
||||
})
|
||||
optionMenu.addAction(UIAlertAction(title: SSHKeyFileImportTableViewController.menuLabel, style: .default) { _ in
|
||||
self.performSegue(withIdentifier: "setGitSSHKeyByFileSegue", sender: self)
|
||||
})
|
||||
|
||||
if isReadyToUse() {
|
||||
optionMenu.addAction(UIAlertAction(title: "\(Self.menuLabel) (\("Import".localize()))", style: .default) { _ in
|
||||
|
|
|
|||
72
pass/Controllers/SSHKeyFileImportTableViewController.swift
Normal file
72
pass/Controllers/SSHKeyFileImportTableViewController.swift
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// SSHKeyFileImportTableViewController.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Danny Moesch on 15.02.20.
|
||||
// Copyright © 2020 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import passKit
|
||||
import SVProgressHUD
|
||||
|
||||
class SSHKeyFileImportTableViewController: AutoCellHeightUITableViewController {
|
||||
|
||||
@IBOutlet weak var sshPrivateKeyFile: UITableViewCell!
|
||||
|
||||
private var privateKey: String? = nil
|
||||
|
||||
@IBAction func doneButtonTapped(_ sender: Any) {
|
||||
performSegue(withIdentifier: "importSSHKeySegue", sender: self)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let cell = tableView.cellForRow(at: indexPath)
|
||||
let picker = UIDocumentPickerViewController(documentTypes: ["public.data"], in: .open)
|
||||
cell?.isSelected = false
|
||||
guard cell == sshPrivateKeyFile else {
|
||||
return
|
||||
}
|
||||
picker.delegate = self
|
||||
if #available(iOS 13.0, *) {
|
||||
picker.shouldShowFileExtensions = true
|
||||
}
|
||||
present(picker, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension SSHKeyFileImportTableViewController: UIDocumentPickerDelegate {
|
||||
|
||||
func documentPicker(_: UIDocumentPickerViewController, didPickDocumentsAt url: [URL]) {
|
||||
guard let url = url.first else {
|
||||
return
|
||||
}
|
||||
let fileName = url.lastPathComponent
|
||||
do {
|
||||
privateKey = try String(contentsOf: url, encoding: .ascii)
|
||||
sshPrivateKeyFile.textLabel?.text = fileName
|
||||
} catch {
|
||||
Utils.alert(title: "CannotImportFile".localize(), message: "FileCannotBeImported.".localize(fileName), controller: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SSHKeyFileImportTableViewController: KeyImporter {
|
||||
|
||||
static let keySource = KeySource.file
|
||||
static let label = "LoadFromFiles".localize()
|
||||
|
||||
func isReadyToUse() -> Bool {
|
||||
guard privateKey != nil else {
|
||||
Utils.alert(title: "CannotSave".localize(), message: "SetPrivateKeyUrl.".localize(), controller: self)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func importKeys() throws {
|
||||
guard let privateKey = privateKey else {
|
||||
return
|
||||
}
|
||||
try KeyFileManager.PrivateSsh.importKey(from: privateKey)
|
||||
}
|
||||
}
|
||||
|
|
@ -280,6 +280,12 @@ gibt den Schlüssel in diesem speziellen Format aus. Die Zwischenablage wird nac
|
|||
|
||||
gibt den Schlüssel in diesem speziellen Format aus. Kopiere ihn so zu einem Key-Server.";
|
||||
|
||||
"SshAsciiArmorFileExplanation." = "Das Format \"ASCII-Armor\" ist anders als das Binärformat eine einfache Zeichenkette. Der Befehl
|
||||
|
||||
$ cat ~/.ssh/id_rsa
|
||||
|
||||
gibt den Schlüssel in diesem speziellen Format aus. Kopiere ihn so zu einem Speicherort, der für die Dateien-App zugänglich ist.";
|
||||
|
||||
"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
|
||||
|
||||
$ gpg --export -a KEY_ID
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@
|
|||
/* Class = "UIBarButtonItem"; title = "Back"; ObjectID = "9yM-Mg-Cg8"; */
|
||||
"9yM-Mg-Cg8.title" = "Zurück";
|
||||
|
||||
/* Class = "UILabel"; text = "Select file ..."; ObjectID = "9KE-VA-cx2"; */
|
||||
"9KE-VA-cx2.text" = "Datei auswählen ...";
|
||||
|
||||
/* Class = "UILabel"; text = "Private Key URL"; ObjectID = "C2w-dd-roS"; */
|
||||
"C2w-dd-roS.text" = "URL des privaten Schlüssels";
|
||||
|
||||
|
|
|
|||
|
|
@ -280,6 +280,12 @@ to get the key in this specific format. The clipboard will be cleared 45s after
|
|||
|
||||
to get the key in this specific format. Subsequently, copy it to your secured key server.";
|
||||
|
||||
"SshAsciiArmorFileExplanation." = "The ASCII-armored key format is similar to unencoded documents rather than the binary format. Use
|
||||
|
||||
$ cat ~/.ssh/id_rsa
|
||||
|
||||
to get the key in this specific format. Subsequently, copy it to a location accessible by the Files app.";
|
||||
|
||||
"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
|
||||
|
||||
$ gpg --export -a KEY_ID
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue