diff --git a/Package.swift b/Package.swift
index 3bc8363f52ec3a8a43c913ae95e0a02a3bad3d55..69613b7a89cfceac7bbcbe3eaa5b1e32bb39b380 100644
--- a/Package.swift
+++ b/Package.swift
@@ -69,6 +69,7 @@ let package = Package(
         .package(url: "https://github.com/google/google-api-objectivec-client-for-rest", from: "1.6.0"),
         .package(url: "https://git.xx.network/elixxir/client-ios-db.git", .upToNextMajor(from: "1.0.5")),
         .package(url: "https://github.com/firebase/firebase-ios-sdk.git", .upToNextMajor(from: "8.10.0")),
+        .package(url: "https://github.com/darrarski/Shout.git", revision: "df5a662293f0ac15eeb4f2fd3ffd0c07b73d0de0"),
         .package(url: "https://github.com/pointfreeco/swift-composable-architecture.git",.upToNextMajor(from: "0.32.0"))
     ],
     targets: [
@@ -216,7 +217,13 @@ let package = Package(
                 name: "SFTPFeature",
                 dependencies: [
                     "Shared",
-                    "InputField"
+                    "Keychain",
+                    "InputField",
+                    "DependencyInjection",
+                    .product(
+                        name: "Shout",
+                        package: "Shout"
+                    )
                 ]
             ),
 
diff --git a/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
index 8368713e723419159be8c112d8ffa729dae5d79a..f9518a57613cf453cccc293ef3862f3dd8f4d2b6 100644
--- a/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
@@ -54,9 +54,14 @@ final class BackupSFTPViewModel {
         let password = stateSubject.value.password
 
         let authParams = SFTPAuthParams(host, username, password)
-        service.justAuthenticate(authParams)
-        hudSubject.send(.none)
-        popSubject.send(())
+
+        do {
+            try service.justAuthenticate(authParams)
+            hudSubject.send(.none)
+            popSubject.send(())
+        } catch {
+            hudSubject.send(.error(.init(with: error)))
+        }
     }
 
     private func validate() {
diff --git a/Sources/Keychain/KeychainHandler.swift b/Sources/Keychain/KeychainHandler.swift
index 23f248879a7f2275b0faddd9f4c08962d9ed6246..6ac0d645d6def33360ee5ed0d0ab1e973a0487fc 100644
--- a/Sources/Keychain/KeychainHandler.swift
+++ b/Sources/Keychain/KeychainHandler.swift
@@ -1,15 +1,24 @@
 import Foundation
 import KeychainAccess
 
+public enum KeychainSFTP: String {
+    case pwd
+    case host
+    case username
+}
+
 public protocol KeychainHandling {
     func clear() throws
     func getPassword() throws -> Data?
     func store(password pwd: Data) throws
+
+    func get(key: KeychainSFTP) throws -> String?
+    func store(key: KeychainSFTP, value: String) throws
 }
 
 public struct KeychainHandler: KeychainHandling {
-    private let password = "password"
     private let keychain: Keychain
+    private let password = "password"
 
     public init() {
         self.keychain = Keychain(service: "XXM")
@@ -26,4 +35,12 @@ public struct KeychainHandler: KeychainHandling {
     public func getPassword() throws -> Data? {
         try keychain.getData(password)
     }
+
+    public func get(key: KeychainSFTP) throws -> String? {
+        try keychain.get(key.rawValue)
+    }
+
+    public func store(key: KeychainSFTP, value: String) throws {
+        try keychain.set(value, key: key.rawValue)
+    }
 }
diff --git a/Sources/Keychain/MockKeychainHandler.swift b/Sources/Keychain/MockKeychainHandler.swift
index c1ff10dd802d5cd230cffbe25f20b744aa06126b..39d4a33ddb1e0e6d8a75d8b5a1ea980d8fb189bf 100644
--- a/Sources/Keychain/MockKeychainHandler.swift
+++ b/Sources/Keychain/MockKeychainHandler.swift
@@ -6,4 +6,6 @@ public struct MockKeychainHandler: KeychainHandling {
     public func clear() throws {}
     public func store(password pwd: Data) throws {}
     public func getPassword() throws -> Data? { Data() }
+    public func get(key: KeychainSFTP) throws -> String? { nil }
+    public func store(key: KeychainSFTP, value: String) throws {}
 }
diff --git a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
index 0a7d988ef270cbcfabbe6d1e929809ba3c24e9c9..ccb417df5624d7bd0036e34356c996c923a8a6d3 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
@@ -8,6 +8,7 @@ import Integration
 import BackupFeature
 import DependencyInjection
 
+import SFTPFeature
 import iCloudFeature
 import DropboxFeature
 import GoogleDriveFeature
@@ -38,13 +39,16 @@ extension RestorationStep: Equatable {
 }
 
 final class RestoreViewModel {
+    @Dependency private var sftpService: SFTPService
     @Dependency private var iCloudService: iCloudInterface
     @Dependency private var dropboxService: DropboxInterface
     @Dependency private var googleService: GoogleDriveInterface
 
     @KeyObject(.username, defaultValue: nil) var username: String?
 
-    var step: AnyPublisher<RestorationStep, Never> { stepRelay.eraseToAnyPublisher() }
+    var step: AnyPublisher<RestorationStep, Never> {
+        stepRelay.eraseToAnyPublisher()
+    }
 
     // TO REFACTOR:
     //
@@ -86,7 +90,11 @@ final class RestoreViewModel {
     }
 
     private func downloadBackupForSFTP(_ backup: Backup) {
-        // TODO
+        do {
+            try sftpService.download(backup.id)
+        } catch {
+            print(error.localizedDescription)
+        }
     }
 
     private func downloadBackupForDropbox(_ backup: Backup) {
diff --git a/Sources/SFTPFeature/SFTPService.swift b/Sources/SFTPFeature/SFTPService.swift
index 30b92573a75e1cc4fc956e3f68f8433aa59f9e13..3bb8c0620c70c0d3a84c6e627e64be9e7f484556 100644
--- a/Sources/SFTPFeature/SFTPService.swift
+++ b/Sources/SFTPFeature/SFTPService.swift
@@ -1,5 +1,8 @@
+import Shout
 import Models
+import Keychain
 import Foundation
+import DependencyInjection
 
 public typealias SFTPAuthParams = (String, String, String)
 public typealias SFTPFetchResult = (Result<RestoreSettings?, Error>) -> Void
@@ -8,42 +11,88 @@ public typealias SFTPFetchParams = (SFTPAuthParams, SFTPFetchResult)
 public struct SFTPService {
     public var isAuthorized: () -> Bool
     public var fetch: (SFTPFetchParams) -> Void
-    public var justAuthenticate: (SFTPAuthParams) -> Void
+    public var download: (String) throws -> Void
+    public var justAuthenticate: (SFTPAuthParams) throws -> Void
 }
 
 public extension SFTPService {
     static var mock = SFTPService(
         isAuthorized: {
-            false
+            true
         },
         fetch: { (authParams, completion) in
-            print("^^^ RestoreSFTP Host: \(authParams.0)")
-            print("^^^ RestoreSFTP Username: \(authParams.1)")
-            print("^^^ RestoreSFTP Password: \(authParams.2)")
-
-            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                completion(.success(.init(
-                    backup: .init(id: "ASDF", date: Date.distantPast, size: 100_000_000),
-                    cloudService: .sftp
-                )))
-            }
+            completion(.success(nil))
+        },
+        download: { path in
+
         },
         justAuthenticate: { host, username, password in
-            // TODO: Store these params on the keychain
         })
 
     static var live = SFTPService(
         isAuthorized: {
-            /// If it has host/username/password on keychain
-            /// means its authorized, not that is working
-            ///
-            true
+            if let keychain = try? DependencyInjection.Container.shared.resolve() as KeychainHandling,
+               let pwd = try? keychain.get(key: .pwd),
+               let host = try? keychain.get(key: .host),
+               let username = try? keychain.get(key: .username) {
+                return true
+            } else {
+                return false
+            }
         },
         fetch: { (authParams, completion) in
-            // TODO: Store host/username/password on keychain
+            let host = authParams.0
+            let username = authParams.1
+            let password = authParams.2
+
+            do {
+                let ssh = try SSH(host: host, port: 22)
+                try ssh.authenticate(username: username, password: password)
+                let sftp = try ssh.openSftp()
+
+                let keychain = try DependencyInjection.Container.shared.resolve() as KeychainHandling
+                try keychain.store(key: .host, value: host)
+                try keychain.store(key: .pwd, value: password)
+                try keychain.store(key: .username, value: username)
+
+                if let files = try? sftp.listFiles(in: "backup"),
+                   let backup = files.filter({ file in file.0 == "backup.xxm" }).first {
+                    completion(.success(.init(
+                        backup: .init(
+                            id: "backup/backup.xxm",
+                            date: backup.value.lastModified,
+                            size: Float(backup.value.size)
+                        ),
+                        cloudService: .sftp
+                    )))
+
+                    return
+                }
+
+                completion(.success(nil))
+            } catch {
+                completion(.failure(error))
+            }
+        },
+        download: { path in
+            let keychain = try DependencyInjection.Container.shared.resolve() as KeychainHandling
+            let host = try keychain.get(key: .host)
+            let password = try keychain.get(key: .pwd)
+            let username = try keychain.get(key: .username)
+
+            let ssh = try SSH(host: host!, port: 22)
+            try ssh.authenticate(username: username!, password: password!)
+            let sftp = try ssh.openSftp()
+
+            let temp = NSTemporaryDirectory()
+            try sftp.download(remotePath: path, localURL: URL(string: temp)!)
+            print(FileManager.default.fileExists(atPath: temp))
         },
         justAuthenticate: { host, username, password in
-            // TODO: Store host/username/password on keychain
+            let keychain = try DependencyInjection.Container.shared.resolve() as KeychainHandling
+            try keychain.store(key: .host, value: host)
+            try keychain.store(key: .pwd, value: password)
+            try keychain.store(key: .username, value: username)
         }
     )
 }
diff --git a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
index eeb145af40bba398a5526019333b5de39606557e..102be628eff74bf62db32030a74c7eed314ba3f3 100644
--- a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -27,6 +27,15 @@
         "version" : "1.4.0"
       }
     },
+    {
+      "identity" : "bluesocket",
+      "kind" : "remoteSourceControl",
+      "location" : "https://github.com/IBM-Swift/BlueSocket.git",
+      "state" : {
+        "revision" : "c9894fd117457f1d006575fbfb2fdfd6f79eac03",
+        "version" : "1.0.200"
+      }
+    },
     {
       "identity" : "boringssl-swiftpm",
       "kind" : "remoteSourceControl",
@@ -207,6 +216,15 @@
         "version" : "1.22.2"
       }
     },
+    {
+      "identity" : "libssh2prebuild",
+      "kind" : "remoteSourceControl",
+      "location" : "https://github.com/DimaRU/Libssh2Prebuild.git",
+      "state" : {
+        "branch" : "1.10.0+OpenSSL_1_1_1o",
+        "revision" : "a91bcf205a6cbc84144f840c44145656abbd266a"
+      }
+    },
     {
       "identity" : "nanopb",
       "kind" : "remoteSourceControl",
@@ -261,6 +279,14 @@
         "version" : "1.2.0"
       }
     },
+    {
+      "identity" : "shout",
+      "kind" : "remoteSourceControl",
+      "location" : "https://github.com/darrarski/Shout.git",
+      "state" : {
+        "revision" : "df5a662293f0ac15eeb4f2fd3ffd0c07b73d0de0"
+      }
+    },
     {
       "identity" : "snapkit",
       "kind" : "remoteSourceControl",