Welcome to mirror list, hosted at ThFree Co, Russian Federation.

NCEndToEndInitialize.swift « Settings « iOSClient - github.com/nextcloud/ios.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bfa97cb25a8fee78d30917b540a122d7e343f716 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
//
//  NCEndToEndInitialize.swift
//  Nextcloud
//
//  Created by Marino Faggiana on 03/04/17.
//  Copyright © 2017 Marino Faggiana. All rights reserved.
//
//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

import UIKit
import NextcloudKit

@objc protocol NCEndToEndInitializeDelegate {

    func endToEndInitializeSuccess()
}

class NCEndToEndInitialize: NSObject {

    @objc weak var delegate: NCEndToEndInitializeDelegate?

    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    var extractedPublicKey: String?

    override init() {
    }

    // --------------------------------------------------------------------------------------------
    // MARK: Initialize
    // --------------------------------------------------------------------------------------------

    @objc func initEndToEndEncryption() {

        // Clear all keys
        CCUtility.clearAllKeysEnd(toEnd: appDelegate.account)

        self.getPublicKey()
    }

    func getPublicKey() {

        NextcloudKit.shared.getE2EECertificate { account, certificate, data, error in

            if error == .success && account == self.appDelegate.account {

                CCUtility.setEndToEndCertificate(account, certificate: certificate)

                self.extractedPublicKey = NCEndToEndEncryption.sharedManager().extractPublicKey(fromCertificate: certificate)

                // Request PrivateKey chiper to Server
                self.getPrivateKeyCipher()

            } else if error != .success {

                switch error.errorCode {

                case NCGlobal.shared.errorBadRequest:
                    let error = NKError(errorCode: error.errorCode, errorDescription: "bad request: unpredictable internal error")
                    NCContentPresenter.shared.messageNotification("E2E get publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                case NCGlobal.shared.errorResourceNotFound:
                    guard let csr = NCEndToEndEncryption.sharedManager().createCSR(self.appDelegate.userId, directory: CCUtility.getDirectoryUserData()) else {
                        let error = NKError(errorCode: error.errorCode, errorDescription: "Error to create Csr")
                        NCContentPresenter.shared.messageNotification("E2E Csr", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                        return
                    }

                    NextcloudKit.shared.signE2EECertificate(certificate: csr) { account, certificate, data, error in

                        if error == .success && account == self.appDelegate.account {

                            // TEST publicKey
                            let extractedPublicKey = NCEndToEndEncryption.sharedManager().extractPublicKey(fromCertificate: certificate)
                            if extractedPublicKey != NCEndToEndEncryption.sharedManager().generatedPublicKey {
                                let error = NKError(errorCode: error.errorCode, errorDescription: "error: the public key is incorrect")
                                NCContentPresenter.shared.messageNotification("E2E sign publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                            } else {

                                CCUtility.setEndToEndCertificate(account, certificate: certificate)

                                // Request PrivateKey chiper to Server
                                self.getPrivateKeyCipher()
                            }

                        } else if error != .success {

                            switch error.errorCode {

                            case NCGlobal.shared.errorBadRequest:
                                let error = NKError(errorCode: error.errorCode, errorDescription: "bad request: unpredictable internal error")
                                NCContentPresenter.shared.messageNotification("E2E sign publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                            case NCGlobal.shared.errorConflict:
                                let error = NKError(errorCode: error.errorCode, errorDescription: "conflict: a public key for the user already exists")
                                NCContentPresenter.shared.messageNotification("E2E sign publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                            default:
                                NCContentPresenter.shared.messageNotification("E2E sign publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
                            }
                        }
                    }

                case NCGlobal.shared.errorConflict:
                    let error = NKError(errorCode: error.errorCode, errorDescription: "forbidden: the user can't access the public keys")
                    NCContentPresenter.shared.messageNotification("E2E get publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                default:
                    NCContentPresenter.shared.messageNotification("E2E get publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
                }
            }
        }
    }

    func getPrivateKeyCipher() {

        // Request PrivateKey chiper to Server
        NextcloudKit.shared.getE2EEPrivateKey { account, privateKeyChiper, data, error in

            if error == .success && account == self.appDelegate.account {

                // request Passphrase

                var passphraseTextField: UITextField?

                let alertController = UIAlertController(title: NSLocalizedString("_e2e_passphrase_request_title_", comment: ""), message: NSLocalizedString("_e2e_passphrase_request_message_", comment: ""), preferredStyle: .alert)

                let ok = UIAlertAction(title: "OK", style: .default, handler: { _ -> Void in

                    let passphrase = passphraseTextField?.text

                    let publicKey = CCUtility.getEndToEndCertificate(self.appDelegate.account)

                    guard let privateKey = (NCEndToEndEncryption.sharedManager().decryptPrivateKey(privateKeyChiper, passphrase: passphrase, publicKey: publicKey)) else {
                        let error = NKError(errorCode: NCGlobal.shared.errorInternalError, errorDescription: "Serious internal error to decrypt Private Key")
                        NCContentPresenter.shared.messageNotification("E2E decrypt privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                        return
                    }

                    // privateKey
                    print(privateKey)

                    // Save to keychain
                    CCUtility.setEndToEndPrivateKey(self.appDelegate.account, privateKey: privateKey)
                    CCUtility.setEndToEndPassphrase(self.appDelegate.account, passphrase: passphrase)

                    // request server publicKey
                    NextcloudKit.shared.getE2EEPublicKey { account, publicKey, data, error in

                        if error == .success && account == self.appDelegate.account {

                            CCUtility.setEndToEndPublicKey(account, publicKey: publicKey)

                            // Clear Table
                            NCManageDatabase.shared.clearTable(tableDirectory.self, account: account)
                            NCManageDatabase.shared.clearTable(tableE2eEncryption.self, account: account)

                            self.delegate?.endToEndInitializeSuccess()

                        } else if error != .success {

                            switch error.errorCode {

                            case NCGlobal.shared.errorBadRequest:
                                let error = NKError(errorCode: error.errorCode, errorDescription: "bad request: unpredictable internal error")
                                NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                            case NCGlobal.shared.errorResourceNotFound:
                                let error = NKError(errorCode: error.errorCode, errorDescription: "Server publickey doesn't exists")
                                NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                            case NCGlobal.shared.errorConflict:
                                let error = NKError(errorCode: error.errorCode, errorDescription: "forbidden: the user can't access the Server publickey")
                                NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                            default:
                                NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
                            }
                        }
                    }
                })

                let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ -> Void in
                }

                alertController.addAction(ok)
                alertController.addAction(cancel)
                alertController.addTextField { textField -> Void in
                    passphraseTextField = textField
                    passphraseTextField?.placeholder = NSLocalizedString("_enter_passphrase_", comment: "")
                }

                self.appDelegate.window?.rootViewController?.present(alertController, animated: true)

            } else if error != .success {

                switch error.errorCode {

                case NCGlobal.shared.errorBadRequest:
                    let error = NKError(errorCode: error.errorCode, errorDescription: "bad request: unpredictable internal error")
                    NCContentPresenter.shared.messageNotification("E2E get privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                case NCGlobal.shared.errorResourceNotFound:
                    // message
                    guard let e2ePassphrase = NYMnemonic.generateString(128, language: "english") else { return }
                    let message = "\n" + NSLocalizedString("_e2e_settings_view_passphrase_", comment: "") + "\n\n" + e2ePassphrase

                    let alertController = UIAlertController(title: NSLocalizedString("_e2e_settings_title_", comment: ""), message: NSLocalizedString(message, comment: ""), preferredStyle: .alert)

                    let OKAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default) { _ in
                        self.createNewE2EE(e2ePassphrase: e2ePassphrase, error: error, copyPassphrase: false)
                    }

                    let copyAction = UIAlertAction(title: NSLocalizedString("_ok_copy_passphrase_", comment: ""), style: .default) { _ in
                        self.createNewE2EE(e2ePassphrase: e2ePassphrase, error: error, copyPassphrase: true)
                    }

                    alertController.addAction(OKAction)
                    alertController.addAction(copyAction)

                    self.appDelegate.window?.rootViewController?.present(alertController, animated: true)

                case NCGlobal.shared.errorConflict:
                    let error = NKError(errorCode: error.errorCode, errorDescription: "forbidden: the user can't access the private key")
                    NCContentPresenter.shared.messageNotification("E2E get privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                default:
                    NCContentPresenter.shared.messageNotification("E2E get privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
                }
            }
        }
    }

    func createNewE2EE(e2ePassphrase: String, error: NKError, copyPassphrase: Bool) {

        var privateKeyString: NSString?

        guard let privateKeyChiper = NCEndToEndEncryption.sharedManager().encryptPrivateKey(self.appDelegate.userId, directory: CCUtility.getDirectoryUserData(), passphrase: e2ePassphrase, privateKey: &privateKeyString) else {
            let error = NKError(errorCode: error.errorCode, errorDescription: "Serious internal error to create PrivateKey chiper")
            NCContentPresenter.shared.messageNotification("E2E privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
            return
        }

        // privateKeyChiper
        print(privateKeyChiper)

        NextcloudKit.shared.storeE2EEPrivateKey(privateKey: privateKeyChiper) { account, privateKey, data, error in

            if error == .success && account == self.appDelegate.account {

                CCUtility.setEndToEndPrivateKey(account, privateKey: privateKeyString! as String)
                CCUtility.setEndToEndPassphrase(account, passphrase: e2ePassphrase)

                // request server publicKey
                NextcloudKit.shared.getE2EEPublicKey { account, publicKey, data, error in

                    if error == .success && account == self.appDelegate.account {

                        CCUtility.setEndToEndPublicKey(account, publicKey: publicKey)

                        // Clear Table
                        NCManageDatabase.shared.clearTable(tableDirectory.self, account: account)
                        NCManageDatabase.shared.clearTable(tableE2eEncryption.self, account: account)

                        if copyPassphrase {
                            UIPasteboard.general.string = e2ePassphrase
                        }

                        self.delegate?.endToEndInitializeSuccess()

                    } else if error != .success {

                        switch error.errorCode {

                        case NCGlobal.shared.errorBadRequest:
                            let error = NKError(errorCode: error.errorCode, errorDescription: "bad request: unpredictable internal error")
                            NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                        case NCGlobal.shared.errorResourceNotFound:
                            let error = NKError(errorCode: error.errorCode, errorDescription: "Server publickey doesn't exists")
                            NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                        case NCGlobal.shared.errorConflict:
                            let error = NKError(errorCode: error.errorCode, errorDescription: "forbidden: the user can't access the Server publickey")
                            NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                        default:
                            NCContentPresenter.shared.messageNotification("E2E Server publicKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
                        }
                    }
                }

            } else if error != .success {

                switch error.errorCode {

                case NCGlobal.shared.errorBadRequest:
                    let error = NKError(errorCode: error.errorCode, errorDescription: "bad request: unpredictable internal error")
                    NCContentPresenter.shared.messageNotification("E2E store privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                case NCGlobal.shared.errorConflict:
                    let error = NKError(errorCode: error.errorCode, errorDescription: "conflict: a private key for the user already exists")
                    NCContentPresenter.shared.messageNotification("E2E store privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)

                default:
                    NCContentPresenter.shared.messageNotification("E2E store privateKey", error: error, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, priority: .max)
                }
            }
        }
    }

}