private bool ProcessMessageLinkedDeviceChange() { var linkedDeviceResponse = new GetLinkedDevice().GetResponse(GetApiClient()); var keyHash = HashUtil.Sha256(linkedDeviceResponse.PublicKeyPem); var cryptoKey = _model.CryptoKeys.Query().FirstOrDefault(r => r.PublicKeyPemHash == keyHash); if (cryptoKey == null) { var newCryptoKeyId = _model.CryptoKeys.Create(new CryptoKey { PublicKeyPem = linkedDeviceResponse.PublicKeyPem, PublicKeyPemHash = keyHash }); cryptoKey = _model.CryptoKeys.Query().First(r => r.Id == newCryptoKeyId); } var accountSettings = _model.ServerAccountSettings.Query().First(); _model.ServerAccountSettings.Update(accountSettings.Id, new ServerAccountSetting { LinkedDeviceCryptoKeyId = cryptoKey.Id }); return(true); }
private bool ProcessMessageLinkedDeviceChange() { var linkedDeviceResponse = new GetLinkedDevice().GetResponse(GetApiClient()); var keyHash = HashUtil.Sha256(linkedDeviceResponse.PublicKeyPem); var cryptoKey = _model.CryptoKeys.Query().FirstOrDefault(r => r.PublicKeyPemHash == keyHash); if (cryptoKey == null) { var newCryptoKeyId = _model.CryptoKeys.Create(new CryptoKey { PublicKeyPem = linkedDeviceResponse.PublicKeyPem, PublicKeyPemHash = keyHash }); cryptoKey = _model.CryptoKeys.Query().First(r => r.Id == newCryptoKeyId); } var accountSettings = _model.ServerAccountSettings.Query().First(); _model.ServerAccountSettings.Update(accountSettings.Id, new ServerAccountSetting { LinkedDeviceCryptoKeyId = cryptoKey.Id }); return true; }
public bool LoginToServer(ServerAccount newServerAccount, string recoveryPasswordPlaintext) { // Duplicate check var existingServers = Model.ServerAccounts.Find(new ServerAccount { ServerHost = newServerAccount.ServerHost, ServerPort = newServerAccount.ServerPort, EmailAddress = newServerAccount.EmailAddress }); if (existingServers.Any()) { MessageBox.Show(@"You are already logged in to this server. "); return false; } var newKeyPair = AsymmetricCryptoUtil.GenerateKeyPair(); var recoveryPasswordHash = HashUtil.GenerateServerRecoveryPasswordHash( newServerAccount.EmailAddress, recoveryPasswordPlaintext); var apiClientUnauthenticated = new ServerAPI.ApiClient(newServerAccount.HttpsEnabled, newServerAccount.ServerHost, newServerAccount.ServerPort, newServerAccount.ServerApiVersion); var loginRequest = new ServerAPI.Requests.Unauthenticated.LoginWithDatabaseRecoveryKey { EmailAddress = newServerAccount.EmailAddress, RecoveryPasswordClientHash = recoveryPasswordHash, DeviceLabel = "My Desktop App", DeviceType = "desktop", DeviceSubtype = "windows", PublicKeyPem = newKeyPair.PublicPem }; ServerAPI.Requests.Unauthenticated.LoginWithDatabaseRecoveryKey.ResponseParams loginResponse; try { loginResponse = loginRequest.GetResponse(apiClientUnauthenticated); } catch (UnauthorizedException) { MessageBox.Show(@"Incorrect email address or recovery passphrase."); return false; } catch (RequestException) { MessageBox.Show(@"There was an error attempting to log in to the server."); return false; } var apiClient = new ServerAPI.ApiClient( newServerAccount.HttpsEnabled, newServerAccount.ServerHost, newServerAccount.ServerPort, newServerAccount.ServerApiVersion, loginResponse.ApiKey, newKeyPair.PrivatePem); var serverInfo = apiClient.GetServerInfo(new ServerAPI.GetServerInfoRequest()); newServerAccount.ServerIdentifier = serverInfo.ServerIdentifier; newServerAccount.ServerLabel = serverInfo.ServerLabel; newServerAccount.UserIdentifier = loginResponse.UserIdentifier; newServerAccount.DeviceIdentifier = loginResponse.DeviceIdentifier; newServerAccount.ApiKey = loginResponse.ApiKey; newServerAccount.BackupEncryptionPassword = HashUtil.GenerateDatabaseBackupPasswordHash(newServerAccount.EmailAddress, recoveryPasswordPlaintext); var newCryptoKeyId = Model.CryptoKeys.Create(new CryptoKey { OwnKey = true, Trust = true, PrivateKeyPem = newKeyPair.PrivatePem, PublicKeyPem = newKeyPair.PublicPem }); newServerAccount.CryptoKeyId = newCryptoKeyId; ServerAPI.GetUserResponse userInfo; try { userInfo = apiClient.GetUser(new ServerAPI.GetUserRequest()); if (userInfo.SecondDeviceSetupCompleted) { // Retrieve the linked device public key var linkedDeviceResponse = new GetLinkedDevice().GetResponse(apiClient); var linkedDeviceCryptoKeyId = Model.CryptoKeys.Create(new CryptoKey { PublicKeyPem = linkedDeviceResponse.PublicKeyPem, PublicKeyPemHash = HashUtil.Sha256(linkedDeviceResponse.PublicKeyPem) }); newServerAccount.LinkedDeviceCryptoKeyId = linkedDeviceCryptoKeyId; } } catch (RequestException) { MessageBox.Show(@"There was an error attempting to retrieve linked device details."); return false; } var newServerAccountId = Model.ServerAccounts.Create(newServerAccount); if (!userInfo.SecondDeviceSetupCompleted) { Model.ServerAccounts.Update(newServerAccountId, new ServerAccount {LinkedDeviceSetup = true}); if (userInfo.Links.Count == 0) NewDatabase("My Database", newServerAccountId); } if (!_syncServers.ContainsKey(newServerAccountId)) { _syncServers.Add(newServerAccountId, new Sync(this, newServerAccountId)); _syncServers[newServerAccountId].Start(); } UpdateHomePage(); return true; }
public bool LinkSecondDevice(int serverAccountId, bool isRecovery = false) { var serverAccount = Model.ServerAccounts.Get(serverAccountId); var apiClient = GetApiClient(serverAccountId); var cryptoKey = Model.CryptoKeys.Get(serverAccount.CryptoKeyId); using (var form = new SetupOtpDeviceLink(this, apiClient, serverAccount, cryptoKey)) { form.ShowDialog(); if (!form.Success) { //MessageBox.Show(@"Link to second device was not established."); return false; } } // TODO: Verify the linked device key properly. GetLinkedDevice.ResponseParams linkedDeviceResponse; try { linkedDeviceResponse = new GetLinkedDevice().GetResponse(apiClient); } catch (RequestException e) { if (Program.AppEnvDebug) throw new Exception("Error getting linked device info", e); MessageBox.Show(@"There was an error verifying phone's device key."); return false; } var linkedDeviceCryptoKeyId = Model.CryptoKeys.Create(new CryptoKey { //Trust = true, PublicKeyPem = linkedDeviceResponse.PublicKeyPem, PublicKeyPemHash = HashUtil.Sha256(linkedDeviceResponse.PublicKeyPem) }); Model.ServerAccounts.Update(serverAccountId, new ServerAccount { LinkedDeviceSetup = true, LinkedDeviceCryptoKeyId = linkedDeviceCryptoKeyId }); ServerAPI.GetUserResponse userInfoResponse; try { userInfoResponse = apiClient.GetUser(new ServerAPI.GetUserRequest()); } catch (RequestException e) { if (Program.AppEnvDebug) throw new Exception("Unexpected error getting user info", e); return true; } if (userInfoResponse.Links.Count == 0) NewDatabase("My Database", serverAccountId); VerifyDeviceKeys(serverAccountId); UpdateHomePage(); return true; }