diff --git a/enzevalos_iphone/CryptoObject.swift b/enzevalos_iphone/CryptoObject.swift index ddeb212fd0115b39798f29f0bb10947bddd997dc..86825b50cd7f4d3b4b76fb01c34ef282d08c9805 100644 --- a/enzevalos_iphone/CryptoObject.swift +++ b/enzevalos_iphone/CryptoObject.swift @@ -33,6 +33,7 @@ public class CryptoObject{ let encryptionState: EncryptionState let signKey: String? let encType: CryptoScheme + let passcode: String? var decryptedText: String?{ if let data = decryptedData{ @@ -50,6 +51,7 @@ public class CryptoObject{ self.encryptionState = encState self.signKey = signKey self.encType = encType + self.passcode = nil } diff --git a/enzevalos_iphone/Cryptography.swift b/enzevalos_iphone/Cryptography.swift index 8429f66554259ecab5b794bc753cb398484efaa2..e7fc0c1577a20513f36a5a4375307abe7cbc085e 100644 --- a/enzevalos_iphone/Cryptography.swift +++ b/enzevalos_iphone/Cryptography.swift @@ -15,10 +15,12 @@ public protocol Encryption{ func importKeys(key: String, isSecretKey: Bool, autocrypt: Bool) -> [String] func importKeys(data: Data, secret: Bool) -> [String] func importKeysFromFile(file: String) -> [String] + func exportKey(id: String, isSecretkey: Bool, autocrypt: Bool) -> String? + func exportKeyData(id: String, isSecretkey: Bool, autocrypt: Bool) -> Data? // operations on keys func encrypt(plaintext: String, ids: [String], myId: String) -> CryptoObject func decrypt(data: Data, decryptionId: String?, verifyIds: [String]) -> CryptoObject - + } diff --git a/enzevalos_iphone/ExportViewController.swift b/enzevalos_iphone/ExportViewController.swift index 4c4f904298f904ec3200aa70155c6e996c5177d4..3cc4f8a809afc83f09082a022c96aa1ce91cb6db 100644 --- a/enzevalos_iphone/ExportViewController.swift +++ b/enzevalos_iphone/ExportViewController.swift @@ -16,27 +16,22 @@ class ExportViewController: UITableViewController { @IBAction func buttonTouched(_ sender: Any) { if !alreadySent { //TODO: create passcode for AES, export key, send mail + let handler = DataHandler.handler let ids = handler.findSecretKeys() if ids.count > 0{ - // let id = ids[0] - // let pgp = SwiftPGP() - //passcode = loadPassword(id) + let id = ids[0] + let pgp = SwiftPGP() //AppDelegate.mailhandler.sendSecretKey(id) - let objPGP = ObjectivePGP() - if let data = "hello Bob".data(using: .utf8){ - print("Create Key message") - passcode = "1234" - let m = try! objPGP.symmetricEncrypt(data, signWith: nil, encryptionKey: passcode, passphrase: passcode, armored: true) - let mString = String.init(data: m, encoding: .utf8) - print(mString ?? "no encrypted message") - let p = try! objPGP.symmetricDecrypt(m, key: passcode, verifyWith: nil, signed: nil, valid: nil, integrityProtected: nil) - let pString = String.init(data: p, encoding: .utf8) - print(pString ?? "no decrypted message") + if let keyId = id.keyID{ + if let message = pgp.exportKeyData(id: keyId, isSecretkey: true, autocrypt: true){ + passcode = pgp.loadExportPasscode(id: keyId)! + print("My passcode: \(passcode)") + let mailHandler = AppDelegate.getAppDelegate().mailHandler + mailHandler.sendSecretKey(keyData: message, passcode: passcode, callback: mailSend) + } } - - } else{ // TODO: Error NO SECRET KEY! @@ -112,4 +107,14 @@ class ExportViewController: UITableViewController { tableView.estimatedRowHeight = 140 navigationItem.rightBarButtonItem?.title = NSLocalizedString("Done", comment: "") } + + func mailSend(_ error: Error?) { + if (error != nil) { + NSLog("Error sending email: \(String(describing: error))") + AppDelegate.getAppDelegate().showMessage("An error occured", completion: nil) + } else { + NSLog("Send successful!") + } + } + } diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift index f12cc59298af6b41c8b17539fe6344680b13fb05..3be032028345512d054311e9f9b2c5f4d93259de 100644 --- a/enzevalos_iphone/MailHandler.swift +++ b/enzevalos_iphone/MailHandler.swift @@ -230,8 +230,39 @@ class MailHandler { return ids } - func sendSecretKey(keyID: String){ - + func sendSecretKey(keyData: Data, passcode: String, callback: @escaping (Error?) -> Void){ + let useraddr = (UserManager.loadUserValue(Attribute.userAddr) as! String) + let session = createSMTPSession() + let builder = MCOMessageBuilder() + let userID :MCOAddress = MCOAddress(displayName: useraddr, mailbox: useraddr) + + createHeader(builder, toEntrys: [useraddr], ccEntrys: [], bccEntrys: [], subject: "Autocrypt Setup Message 2") + builder.header.setExtraHeaderValue("v1", forName: "Autocrypt-Setup-Message") + + + /* + if let key = MCOAttachment.init(rfc822Message: keyData){ + print("ID: \(key.contentID)") + print("Type: \(key.mimeType)") + // Use and test later: + // see https://autocrypt.readthedocs.io/en/latest/level1.html#autocrypt-setup-message + // key.mimeType = "application/autocrypt-key-backup" + key.mimeType = "application/pgp-encrypted" + builder.addAttachment(key) + } + let plain = MCOAttachment.init(text: "Klartext!") + builder.addAttachment(plain) + + */ + builder.addAttachment(MCOAttachment.init(text: NSLocalizedString("This message contains a secret for reading secure mails on other devices. \n 1) Input the passcode from your smartphone to unlock the message on your other device. \n 2) Import the secret into your pgp program on the device. \n\n For more information visit: www.enzevalos.de/other", comment: "Message when sending the secret key"))) + + let key = MCOAttachment.init(rfc822Message: keyData) + builder.addAttachment(key) + + + let sendOperation = session.sendOperation(with: builder.data() , from: userID, recipients: [userID]) + sendOperation?.start(callback) + createSendCopy(sendData: builder.openPGPEncryptedMessageData(withEncryptedData: keyData)) } @@ -267,8 +298,7 @@ class MailHandler { let cryptoObject = pgp.encrypt(plaintext: "\n" + message, ids: keyIDs, myId:sk.keyID!) if let encData = cryptoObject.chiphertext{ sendData = encData - builder.textBody = "Dies ist verschlüsselt!" - sendOperation = session.sendOperation(with: builder.openPGPEncryptedMessageData(withEncryptedData: sendData), from: userID, recipients: encPGP) + sendOperation = session.sendOperation(with: builder.openPGPEncryptedMessageData(withEncryptedData: sendData), from: userID, recipients: encPGP) //TODO handle different callbacks sendOperation.start(callback) @@ -360,8 +390,8 @@ class MailHandler { imapsession.port = UInt32(UserManager.loadUserValue(Attribute.imapPort) as! Int) imapsession.username = UserManager.loadUserValue(Attribute.userAddr) as! String imapsession.password = UserManager.loadUserValue(Attribute.userPW) as! String - imapsession.authType = UserManager.loadImapAuthType()//MCOAuthType(rawValue: UserManager.loadUserValue(Attribute.imapAuthType) as! Int) //MCOAuthType.SASLPlain - imapsession.connectionType = MCOConnectionType(rawValue: UserManager.loadUserValue(Attribute.imapConnectionType) as! Int)//MCOConnectionType.TLS + imapsession.authType = UserManager.loadImapAuthType() + imapsession.connectionType = MCOConnectionType(rawValue: UserManager.loadUserValue(Attribute.imapConnectionType) as! Int) let y = imapsession.folderStatusOperation("INBOX") y?.start{(error, status) -> Void in @@ -418,7 +448,7 @@ class MailHandler { session.port = UInt32(UserManager.loadUserValue(Attribute.smtpPort) as! Int) session.username = UserManager.loadUserValue(Attribute.userAddr) as! String session.password = UserManager.loadUserValue(Attribute.userPW) as! String - session.authType = UserManager.loadSmtpAuthType()//MCOAuthType(rawValue: UserManager.loadUserValue(Attribute.smtpAuthType) as! Int) + session.authType = UserManager.loadSmtpAuthType() session.connectionType = MCOConnectionType(rawValue: UserManager.loadUserValue(Attribute.smtpConnectionType) as! Int) return session } diff --git a/enzevalos_iphone/SwiftPGP.swift b/enzevalos_iphone/SwiftPGP.swift index 77abf2170d7470161680971945e7e92da2f8693e..7cd46980e0dddf011913e97948d20e4a58626d2d 100644 --- a/enzevalos_iphone/SwiftPGP.swift +++ b/enzevalos_iphone/SwiftPGP.swift @@ -14,12 +14,17 @@ class SwiftPGP: Encryption{ let cryptoScheme = CryptoScheme.PGP + let PasscodeSize = 36 + private func generatePW(size: Int)-> String{ var pw = "" - for _ in 0..<size{ + for i in 0..<size{ let p = Int(arc4random_uniform(10)) pw.append(String(p)) + if i % 4 == 3 && i < size - 4{ + pw.append("-") + } } return pw } @@ -37,6 +42,12 @@ class SwiftPGP: Encryption{ } } + private var exportPwKeyChain: Keychain{ + get{ + return Keychain(service: "Enzevalos/PGP/ExportPassword") + } + } + private func storeKey(key: PGPKey) -> String{ let id = key.keyID.longKeyString let data = try! key.export() @@ -70,7 +81,18 @@ class SwiftPGP: Encryption{ return nil } - func loadPassword(id: String) -> String?{ + func loadExportPasscode(id: String) -> String?{ + do{ + if let pw = try exportPwKeyChain.getString(id){ + return pw + } + } catch{ + return nil + } + return nil + } + + private func loadPassword(id: String) -> String?{ do{ if let pw = try pwKeyChain.getString(id){ return pw @@ -83,7 +105,7 @@ class SwiftPGP: Encryption{ func generateKey(adr: String) -> String{ let gen = PGPKeyGenerator() - let pw = generatePW(size: 36) + let pw = generatePW(size: PasscodeSize) let key = gen.generate(for: adr, passphrase: pw) pwKeyChain[key.keyID.longKeyString] = pw return storeKey(key: key) @@ -99,7 +121,7 @@ class SwiftPGP: Encryption{ } else{ if let data = key.data(using: .utf8){ - keys = pgp.importKeys(from: data) //.base64EncodedData() + keys = pgp.importKeys(from: data) } else{ @@ -138,9 +160,40 @@ class SwiftPGP: Encryption{ } func exportKey(id: String, isSecretkey isSecretKey: Bool, autocrypt: Bool) -> String?{ + if let key = exportKeyData(id: id, isSecretkey: isSecretKey, autocrypt: autocrypt){ + if !isSecretKey && autocrypt{ + return key.base64EncodedString() + } + else{ + return String.init(data: key, encoding: .utf8) + } + } + return nil + } + + func exportKeyData(id: String, isSecretkey: Bool, autocrypt: Bool) -> Data?{ let pgp = ObjectivePGP() if var key = loadKey(id: id){ - if key.isSecret && !isSecretKey{ + if isSecretkey && key.isSecret{ + if let keyData = pgp.export(key, armored: true){ + if autocrypt{ + // Create Autocrypt Setup-message + // See: https://autocrypt.readthedocs.io/en/latest/level1.html#autocrypt-setup-message + var passcode = loadPassword(id: id) + if passcode == nil{ + passcode = generatePW(size: PasscodeSize) + } + exportPwKeyChain[key.keyID.longKeyString] = passcode + let cipher = try! pgp.symmetricEncrypt(keyData, signWith: nil, encryptionKey: passcode, passphrase: passcode, armored: true) + print(String.init(data: cipher, encoding: .utf8) ?? "NO KEY") + + return cipher + } + return keyData + } + } + + if key.isSecret && !isSecretkey{ let pk = try! key.export(PGPPartialKeyType.public, error: ()) let keys = pgp.keys(from: pk) if (keys.count > 0){ @@ -152,17 +205,18 @@ class SwiftPGP: Encryption{ } if autocrypt{ if let data = pgp.export(key, armored: false){ - return data.base64EncodedString() + return data } } else{ if let data = pgp.export(key, armored: true){ - return data.base64EncodedString() + return data } } } return nil } + func encrypt(plaintext: String, ids: [String], myId: String) -> CryptoObject{ let pgp = ObjectivePGP()