NCEndToEndInitialize.swift 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. //
  2. // NCEndToEndInitialize.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 03/04/17.
  6. // Copyright © 2017 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import Foundation
  24. @objc protocol NCEndToEndInitializeDelegate {
  25. func endToEndInitializeSuccess()
  26. }
  27. class NCEndToEndInitialize : NSObject {
  28. @objc weak var delegate: NCEndToEndInitializeDelegate?
  29. let appDelegate = UIApplication.shared.delegate as! AppDelegate
  30. override init() {
  31. }
  32. // --------------------------------------------------------------------------------------------
  33. // MARK: Initialize
  34. // --------------------------------------------------------------------------------------------
  35. @objc func initEndToEndEncryption() {
  36. // Clear all keys
  37. CCUtility.clearAllKeysEnd(toEnd: appDelegate.activeAccount)
  38. self.getPublicKey()
  39. }
  40. func getPublicKey() {
  41. NCNetworkingEndToEnd.sharedManager()?.getPublicKey(withAccount: appDelegate.activeAccount, completion: { (account, publicKey, message, errorCode) in
  42. if (errorCode == 0 && account == self.appDelegate.activeAccount) {
  43. CCUtility.setEndToEndPublicKey(account, publicKey: publicKey)
  44. // Request PrivateKey chiper to Server
  45. self.getPrivateKeyCipher()
  46. } else if errorCode != 0 {
  47. switch errorCode {
  48. case 400:
  49. self.appDelegate.messageNotification("E2E get publicKey", description: "bad request: unpredictable internal error", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  50. case 404:
  51. guard let csr = NCEndToEndEncryption.sharedManager().createCSR(self.appDelegate.activeUserID, directory: CCUtility.getDirectoryUserData()) else {
  52. self.appDelegate.messageNotification("E2E Csr", description: "Error to create Csr", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  53. return
  54. }
  55. NCNetworkingEndToEnd.sharedManager()?.signPublicKey(withAccount: account, publicKey: csr, completion: { (account, publicKey, message, errorCode) in
  56. if (errorCode == 0 && account == self.appDelegate.activeAccount) {
  57. CCUtility.setEndToEndPublicKey(account, publicKey: publicKey)
  58. // Request PrivateKey chiper to Server
  59. self.getPrivateKeyCipher()
  60. } else if errorCode != 0 {
  61. switch errorCode {
  62. case 400:
  63. self.appDelegate.messageNotification("E2E sign publicKey", description: "bad request: unpredictable internal error", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  64. case 409:
  65. self.appDelegate.messageNotification("E2E sign publicKey", description: "conflict: a public key for the user already exists", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  66. default:
  67. self.appDelegate.messageNotification("E2E sign publicKey", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  68. }
  69. }
  70. })
  71. case 409:
  72. self.appDelegate.messageNotification("E2E get publicKey", description: "forbidden: the user can't access the public keys", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  73. default:
  74. self.appDelegate.messageNotification("E2E get publicKey", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  75. }
  76. }
  77. })
  78. }
  79. func getPrivateKeyCipher() {
  80. // Request PrivateKey chiper to Server
  81. NCNetworkingEndToEnd.sharedManager()?.getPrivateKeyCipher(withAccount: appDelegate.activeAccount, completion: { (account, privateKeyChiper, message, errorCode) in
  82. if (errorCode == 0 && account == self.appDelegate.activeAccount) {
  83. // request Passphrase
  84. var passphraseTextField: UITextField?
  85. let alertController = UIAlertController(title: NSLocalizedString("_e2e_passphrase_request_title_", comment: ""), message: NSLocalizedString("_e2e_passphrase_request_message_", comment: ""), preferredStyle: .alert)
  86. //TEST
  87. /*
  88. if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
  89. let fileURL = dir.appendingPathComponent("privatekey.txt")
  90. //writing
  91. do {
  92. try metadataNet.key.write(to: fileURL, atomically: false, encoding: .utf8)
  93. }
  94. catch {/* error handling here */}
  95. }
  96. */
  97. //
  98. let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
  99. let passphrase = passphraseTextField?.text
  100. let publicKey = CCUtility.getEndToEndPublicKey(self.appDelegate.activeAccount)
  101. guard let privateKey = (NCEndToEndEncryption.sharedManager().decryptPrivateKey(privateKeyChiper, passphrase: passphrase, publicKey: publicKey)) else {
  102. self.appDelegate.messageNotification("E2E decrypt privateKey", description: "Serious internal error to decrypt Private Key", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: Int(k_CCErrorInternalError))
  103. return
  104. }
  105. // privateKey
  106. print(privateKey)
  107. // Save to keychain
  108. CCUtility.setEndToEndPrivateKey(self.appDelegate.activeAccount, privateKey: privateKey)
  109. CCUtility.setEndToEndPassphrase(self.appDelegate.activeAccount, passphrase:passphrase)
  110. // request publicKey Server()
  111. NCNetworkingEndToEnd.sharedManager()?.getServerPublicKey(withAccount: account, completion: { (account, publicKey, message, errorCode) in
  112. if (errorCode == 0 && account == self.appDelegate.activeAccount) {
  113. CCUtility.setEndToEndPublicKeyServer(account, publicKey: publicKey)
  114. // Clear Table
  115. NCManageDatabase.sharedInstance.clearTable(tableDirectory.self, account: account)
  116. NCManageDatabase.sharedInstance.clearTable(tableE2eEncryption.self, account: account)
  117. self.delegate?.endToEndInitializeSuccess()
  118. } else if errorCode != 0 {
  119. switch (errorCode) {
  120. case 400:
  121. self.appDelegate.messageNotification("E2E Server publicKey", description: "bad request: unpredictable internal error", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  122. case 404:
  123. self.appDelegate.messageNotification("E2E Server publicKey", description: "Server publickey doesn't exists", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  124. case 409:
  125. self.appDelegate.messageNotification("E2E Server publicKey", description: "forbidden: the user can't access the Server publickey", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  126. default:
  127. self.appDelegate.messageNotification("E2E Server publicKey", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  128. }
  129. }
  130. })
  131. })
  132. let cancel = UIAlertAction(title: "Cancel", style: .cancel) { (action) -> Void in
  133. }
  134. alertController.addAction(ok)
  135. alertController.addAction(cancel)
  136. alertController.addTextField { (textField) -> Void in
  137. passphraseTextField = textField
  138. passphraseTextField?.placeholder = "Enter passphrase (12 words)"
  139. }
  140. self.appDelegate.activeMain.present(alertController, animated: true)
  141. } else if errorCode != 0 {
  142. switch errorCode {
  143. case 400:
  144. self.appDelegate.messageNotification("E2E get privateKey", description: "bad request: unpredictable internal error", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  145. case 404:
  146. // message
  147. let e2ePassphrase = NYMnemonic.generateString(128, language: "english")
  148. let message = "\n" + NSLocalizedString("_e2e_settings_view_passphrase_", comment: "") + "\n\n" + e2ePassphrase!
  149. let alertController = UIAlertController(title: NSLocalizedString("_e2e_settings_title_", comment: ""), message: NSLocalizedString(message, comment: ""), preferredStyle: .alert)
  150. let OKAction = UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default) { action in
  151. var privateKeyString: NSString?
  152. guard let privateKeyChiper = NCEndToEndEncryption.sharedManager().encryptPrivateKey(self.appDelegate.activeUserID, directory: CCUtility.getDirectoryUserData(), passphrase: e2ePassphrase, privateKey: &privateKeyString) else {
  153. self.appDelegate.messageNotification("E2E privateKey", description: "Serious internal error to create PrivateKey chiper", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  154. return
  155. }
  156. NCNetworkingEndToEnd.sharedManager()?.storePrivateKeyCipher(withAccount: account, privateKeyString: privateKeyString! as String, privateKeyChiper: privateKeyChiper, completion: { (account, privateKeyString, privateKey, message, errorCode) in
  157. if (errorCode == 0 && account == self.appDelegate.activeAccount) {
  158. CCUtility.setEndToEndPrivateKey(account, privateKey: privateKeyString! as String)
  159. CCUtility.setEndToEndPassphrase(account, passphrase: e2ePassphrase)
  160. // request publicKey Server()
  161. NCNetworkingEndToEnd.sharedManager()?.getServerPublicKey(withAccount: account, completion: { (account, publicKey, message, errorCode) in
  162. if (errorCode == 0 && account == self.appDelegate.activeAccount) {
  163. CCUtility.setEndToEndPublicKeyServer(account, publicKey: publicKey)
  164. // Clear Table
  165. NCManageDatabase.sharedInstance.clearTable(tableDirectory.self, account: account)
  166. NCManageDatabase.sharedInstance.clearTable(tableE2eEncryption.self, account: account)
  167. self.delegate?.endToEndInitializeSuccess()
  168. } else if errorCode != 0 {
  169. switch (errorCode) {
  170. case 400:
  171. self.appDelegate.messageNotification("E2E Server publicKey", description: "bad request: unpredictable internal error", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  172. case 404:
  173. self.appDelegate.messageNotification("E2E Server publicKey", description: "Server publickey doesn't exists", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  174. case 409:
  175. self.appDelegate.messageNotification("E2E Server publicKey", description: "forbidden: the user can't access the Server publickey", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  176. default:
  177. self.appDelegate.messageNotification("E2E Server publicKey", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  178. }
  179. }
  180. })
  181. } else if errorCode != 0 {
  182. switch errorCode {
  183. case 400:
  184. self.appDelegate.messageNotification("E2E store privateKey", description: "bad request: unpredictable internal error", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  185. case 409:
  186. self.appDelegate.messageNotification("E2E store privateKey", description: "conflict: a private key for the user already exists", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  187. default:
  188. self.appDelegate.messageNotification("E2E store privateKey", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  189. }
  190. }
  191. })
  192. }
  193. alertController.addAction(OKAction)
  194. self.appDelegate.activeMain.present(alertController, animated: true)
  195. case 409:
  196. self.appDelegate.messageNotification("E2E get privateKey", description: "forbidden: the user can't access the private key", visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  197. default:
  198. self.appDelegate.messageNotification("E2E get privateKey", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
  199. }
  200. }
  201. })
  202. }
  203. }