public object SetKeys(string publicKey, string privateKeyEnc) { SecurityContext.DemandPermissions(new UserSecurityProvider(SecurityContext.CurrentAccount.ID), Core.Users.Constants.Action_EditUser); if (!PrivacyRoomSettings.Enabled) { throw new System.Security.SecurityException(); } var keyPair = EncryptionKeyPair.GetKeyPair(); if (keyPair != null) { if (!string.IsNullOrEmpty(keyPair.PublicKey)) { return(new { isset = true }); } LogManager.GetLogger("ASC.Api.Documents").InfoFormat("User {0} updates address", SecurityContext.CurrentAccount.ID); } EncryptionKeyPair.SetKeyPair(publicKey, privateKeyEnc); return(new { isset = true }); }
public IEnumerable <EncryptionKeyPair> GetPublicKeysWithAccess(string fileId) { if (!PrivacyRoomSettings.Enabled) { throw new System.Security.SecurityException(); } var fileKeyPair = EncryptionKeyPair.GetKeyPair(fileId); return(fileKeyPair); }
public void Decrypting_UsingPublicKey_Exc() { Setup.Initialize(out var testFolders); Setup.SetEncryptedFiles(testFolders); string targetFilePath = Directory.GetFiles(testFolders["encrypted"])[0]; var key = EncryptionKeyPair.ImportPEMFile($@"{Setup.AbsolutePath}\pub.key.pem"); Assert.NotNull(key); Assert.Throws <InvalidOperationException>(() => Program.DecryptOption(targetFilePath, Setup.PublicKey, testFolders["decrypted"], false)); }
/// <summary> /// Generate Aes encryption key. /// </summary> /// <returns></returns> public static EncryptionKeyPair GenerateKeyPair() { var ret = new EncryptionKeyPair(); using var aes = System.Security.Cryptography.Aes.Create(); aes.GenerateKey(); ret.PublicKey = aes.Key; aes.GenerateIV(); ret.PrivateKey = aes.IV; return(ret); }
public static void Initialize(out Dictionary <string, string> testFolders) { Guid[] guids = { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() }; string folderName = Guid.NewGuid().ToString(); testFolders = new Dictionary <string, string> { { "original", Path.Combine(OriginalPath, folderName) }, { "encrypted", Path.Combine(EncryptedPath, folderName) }, { "decrypted", Path.Combine(DecryptedPath, folderName) }, }; string[] files = { Path.Combine(testFolders["original"], guids[0].ToString() + ".txt"), Path.Combine(testFolders["original"], guids[1].ToString() + ".txt"), Path.Combine(testFolders["original"], guids[2].ToString() + ".txt"), }; string pubKey = @$ "{AbsolutePath}\pub.key.pem"; string privKey = @$ "{AbsolutePath}\priv.key.pem"; Directory.CreateDirectory(testFolders["original"]); Directory.CreateDirectory(testFolders["encrypted"]); Directory.CreateDirectory(testFolders["decrypted"]); for (int i = 0; i < files.Length; i++) { using (var sw = File.CreateText(files[i])) { sw.WriteLine(Guid.NewGuid()); sw.WriteLine(Guid.NewGuid()); sw.WriteLine(Guid.NewGuid()); } } if (!File.Exists(pubKey) && !File.Exists(privKey)) { var key = EncryptionKeyPair.New(2048); key.ExportAsPEMFile(AbsolutePath, includePrivate: false); key.ExportAsPEMFile(AbsolutePath, includePrivate: true); } PrivateKey = EncryptionKeyPair.ImportPEMFile(@$ "{AbsolutePath}\priv.key.pem"); PublicKey = EncryptionKeyPair.ImportPEMFile(@$ "{AbsolutePath}\pub.key.pem"); }
public EncryptionKeyPair GenerateEncryptionKeyPair() { using (var cryptoProvider = new RNGCryptoServiceProvider()) { var key = Guid.NewGuid().ToString("N"); byte[] secretKeyByteArray = new byte[32]; //256 bit cryptoProvider.GetBytes(secretKeyByteArray); var secret = Convert.ToBase64String(secretKeyByteArray); var result = new EncryptionKeyPair { PublicKey = key, PrivateKey = secret }; return(result); } }
private void PageLoad() { var editPossible = !RequestEmbedded; var isExtenral = false; File file; var fileUri = string.Empty; try { if (string.IsNullOrEmpty(RequestFileUrl)) { var app = ThirdPartySelector.GetAppByFileId(RequestFileId); if (app == null) { file = DocumentServiceHelper.GetParams(RequestFileId, RequestVersion, RequestShareLinkKey, editPossible, !RequestView, true, out _configuration); if (_valideShareLink) { _configuration.Document.SharedLinkKey += RequestShareLinkKey; _configuration.Document.Info.Favorite = null; if (CoreContext.Configuration.Personal && !SecurityContext.IsAuthenticated) { var user = CoreContext.UserManager.GetUsers(file.CreateBy); var culture = CultureInfo.GetCultureInfo(user.CultureName); Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture; } } } else { isExtenral = true; bool editable; _thirdPartyApp = true; file = app.GetFile(RequestFileId, out editable); file = DocumentServiceHelper.GetParams(file, true, editPossible ? FileShare.ReadWrite : FileShare.Read, false, editable, editable, editable, true, out _configuration); _configuration.Document.Url = app.GetFileStreamUrl(file); _configuration.EditorConfig.Customization.GobackUrl = string.Empty; _configuration.Document.Info.Favorite = null; } } else { isExtenral = true; fileUri = RequestFileUrl; var fileTitle = Request[FilesLinkUtility.FileTitle]; if (string.IsNullOrEmpty(fileTitle)) { fileTitle = Path.GetFileName(HttpUtility.UrlDecode(fileUri)) ?? ""; } file = new File { ID = RequestFileUrl, Title = Global.ReplaceInvalidCharsAndTruncate(fileTitle) }; file = DocumentServiceHelper.GetParams(file, true, FileShare.Read, false, false, false, false, false, out _configuration); _configuration.Document.Permissions.Edit = editPossible && !CoreContext.Configuration.Standalone; _configuration.Document.Permissions.Rename = false; _configuration.Document.Permissions.Review = false; _configuration.Document.Permissions.FillForms = false; _configuration.Document.Permissions.ChangeHistory = false; _configuration.Document.Permissions.ModifyFilter = false; _editByUrl = true; _configuration.Document.Url = fileUri; _configuration.Document.Info.Favorite = null; } ErrorMessage = _configuration.ErrorMessage; } catch (Exception ex) { Global.Logger.Warn("DocEditor", ex); ErrorMessage = ex.Message; return; } var userAgent = Request.UserAgent.ToString().ToLower(); HttpCookie deeplinkCookie = Request.Cookies.Get("deeplink"); var deepLink = ConfigurationManagerExtension.AppSettings["deeplink.documents.url"]; if (!_valideShareLink && deepLink != null && MobileDetector.IsMobile && ((!userAgent.Contains("version/") && userAgent.Contains("android")) || !userAgent.Contains("android")) && //check webkit ((Request[DeepLinking.WithoutDeeplinkRedirect] == null && deeplinkCookie == null) || Request[DeepLinking.WithoutDeeplinkRedirect] == null && deeplinkCookie != null && deeplinkCookie.Value == "app")) { var currentUser = CoreContext.UserManager.GetUsers(SecurityContext.CurrentAccount.ID); DeepLinkData deepLinkData = new DeepLinkData { Email = currentUser.Email, Portal = CoreContext.TenantManager.GetCurrentTenant().TenantDomain, File = new DeepLinkDataFile { Id = file.ID.ToString(), Title = file.Title, Extension = file.ConvertedExtension }, Folder = new DeepLinkDataFolder { Id = file.FolderID.ToString(), ParentId = file.RootFolderId.ToString(), RootFolderType = (int)file.RootFolderType }, OriginalUrl = Request.GetUrlRewriter().ToString() }; var jsonDeeplinkData = JsonConvert.SerializeObject(deepLinkData); string base64DeeplinkData = Convert.ToBase64String(Encoding.UTF8.GetBytes(jsonDeeplinkData)); Response.Redirect("~/DeepLink.aspx?data=" + HttpUtility.UrlEncode(base64DeeplinkData)); } if (_configuration.EditorConfig.ModeWrite && FileConverter.MustConvert(file)) { try { file = FileConverter.ExecSync(file, RequestShareLinkKey); } catch (Exception ex) { _configuration = null; Global.Logger.Error("DocEditor", ex); ErrorMessage = ex.Message; return; } var comment = "#message/" + HttpUtility.UrlEncode(string.Format(FilesCommonResource.ConvertForEdit, file.Title)); Response.Redirect(FilesLinkUtility.GetFileWebEditorUrl(file.ID) + comment); return; } var fileSecurity = Global.GetFilesSecurity(); if (_configuration.EditorConfig.ModeWrite && FileUtility.CanWebRestrictedEditing(file.Title) && fileSecurity.CanFillForms(file) && !fileSecurity.CanEdit(file)) { if (!file.IsFillFormDraft) { FileMarker.RemoveMarkAsNew(file); Folder folderIfNew; try { file = EntryManager.GetFillFormDraft(file, out folderIfNew); } catch (Exception ex) { _configuration = null; Global.Logger.Error("DocEditor", ex); ErrorMessage = ex.Message; return; } var comment = folderIfNew == null ? string.Empty : "#message/" + HttpUtility.UrlEncode(string.Format(FilesCommonResource.MessageFillFormDraftCreated, folderIfNew.Title)); Response.Redirect(FilesLinkUtility.GetFileWebEditorUrl(file.ID) + comment); return; } else if (!EntryManager.CheckFillFormDraft(file)) { var comment = "#message/" + HttpUtility.UrlEncode(FilesCommonResource.MessageFillFormDraftDiscard); Response.Redirect(FilesLinkUtility.GetFileWebEditorUrl(file.ID) + comment); return; } } Title = file.Title + GetPageTitlePostfix(); if (_configuration.EditorConfig.Customization.Goback == null || string.IsNullOrEmpty(_configuration.EditorConfig.Customization.Goback.Url)) { _configuration.EditorConfig.Customization.GobackUrl = Request[FilesLinkUtility.FolderUrl] ?? ""; } _configuration.EditorConfig.Customization.IsRetina = TenantLogoManager.IsRetina(Request); if (RequestEmbedded) { _configuration.Type = Services.DocumentService.Configuration.EditorType.Embedded; _configuration.EditorConfig.Embedded.ShareLinkParam = string.IsNullOrEmpty(RequestShareLinkKey) ? string.Empty : "&" + FilesLinkUtility.DocShareKey + "=" + RequestShareLinkKey; } else { _configuration.Type = IsMobile ? Services.DocumentService.Configuration.EditorType.Mobile : Services.DocumentService.Configuration.EditorType.Desktop; if (FileSharing.CanSetAccess(file) && !(file.Encrypted && (!Request.DesktopApp() || CoreContext.Configuration.Personal))) { _configuration.EditorConfig.SharingSettingsUrl = CommonLinkUtility.GetFullAbsolutePath( Share.Location + "?" + FilesLinkUtility.FileId + "=" + HttpUtility.UrlEncode(file.ID.ToString()) + (Request.DesktopApp() ? "&desktop=true" : string.Empty)); } if (file.RootFolderType == FolderType.Privacy) { if (!PrivacyRoomSettings.Enabled) { _configuration = null; ErrorMessage = FilesCommonResource.ErrorMassage_FileNotFound; return; } else { if (Request.DesktopApp()) { var keyPair = EncryptionKeyPair.GetKeyPair(); if (keyPair != null) { _configuration.EditorConfig.EncryptionKeys = new Services.DocumentService.Configuration.EditorConfiguration.EncryptionKeysConfig { PrivateKeyEnc = keyPair.PrivateKeyEnc, PublicKey = keyPair.PublicKey, }; } } } } } if (!isExtenral) { _docKeyForTrack = DocumentServiceHelper.GetDocKey(file.ID, -1, DateTime.MinValue); FileMarker.RemoveMarkAsNew(file); if (!file.Encrypted && !file.ProviderEntry) { EntryManager.MarkAsRecent(file); } if (RequestView) { FilesMessageService.Send(file, MessageInitiator.DocsService, MessageAction.FileReaded, file.Title); } else { FilesMessageService.Send(file, MessageInitiator.DocsService, MessageAction.FileOpenedForChange, file.Title); } } if (SecurityContext.IsAuthenticated) { var saveAsUrl = SaveAs.GetUrl; using (var folderDao = Global.DaoFactory.GetFolderDao()) { var folder = folderDao.GetFolder(file.FolderID); if (folder != null && Global.GetFilesSecurity().CanCreate(folder)) { saveAsUrl = SaveAs.GetUrlToFolder(file.FolderID); } } _configuration.EditorConfig.SaveAsUrl = CommonLinkUtility.GetFullAbsolutePath(saveAsUrl); } if (_configuration.EditorConfig.ModeWrite) { _tabId = FileTracker.Add(file.ID); Global.SocketManager.FilesChangeEditors(file.ID); if (SecurityContext.IsAuthenticated) { _configuration.EditorConfig.FileChoiceUrl = CommonLinkUtility.GetFullAbsolutePath(FileChoice.GetUrlForEditor); } } else { _linkToEdit = _editByUrl ? CommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorExternalUrl(fileUri, file.Title)) : CommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorUrl(file.ID)); if (Request.DesktopApp()) { _linkToEdit += "&desktop=true"; } if (FileConverter.MustConvert(_configuration.Document.Info.File)) { _editByUrl = true; } } var actionAnchor = Request[FilesLinkUtility.Anchor]; if (!string.IsNullOrEmpty(actionAnchor)) { _configuration.EditorConfig.ActionLinkString = actionAnchor; } }
/// <summary> /// Using AES algorithm to decrypt input text. /// </summary> /// <param name="cipherText"></param> /// <param name="keyPair"></param> /// <returns></returns> public static string Decrypt(string cipherText, EncryptionKeyPair keyPair) { return(Decrypt(cipherText, keyPair.PublicKey, keyPair.PrivateKey)); }
/// <summary> /// Using AES algorithm to encrypt input text with output URL friendly encrypted text. /// </summary> /// <param name="clearText"></param> /// <param name="keyPair"></param> /// <returns></returns> public static string UrlEncrypt(string clearText, EncryptionKeyPair keyPair) { return(UrlEncrypt(clearText, keyPair.PublicKey, keyPair.PrivateKey)); }
private void PageLoad() { var editPossible = !RequestEmbedded; var isExtenral = false; File file; var fileUri = string.Empty; try { if (string.IsNullOrEmpty(RequestFileUrl)) { var app = ThirdPartySelector.GetAppByFileId(RequestFileId); if (app == null) { file = DocumentServiceHelper.GetParams(RequestFileId, RequestVersion, RequestShareLinkKey, editPossible, !RequestView, true, out _configuration); if (_valideShareLink) { _configuration.Document.SharedLinkKey += RequestShareLinkKey; if (CoreContext.Configuration.Personal && !SecurityContext.IsAuthenticated) { var user = CoreContext.UserManager.GetUsers(file.CreateBy); var culture = CultureInfo.GetCultureInfo(user.CultureName); Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture; } } } else { isExtenral = true; bool editable; _thirdPartyApp = true; file = app.GetFile(RequestFileId, out editable); file = DocumentServiceHelper.GetParams(file, true, editPossible ? FileShare.ReadWrite : FileShare.Read, false, editable, editable, editable, true, out _configuration); _configuration.Document.Url = app.GetFileStreamUrl(file); _configuration.EditorConfig.Customization.GobackUrl = string.Empty; } } else { isExtenral = true; fileUri = RequestFileUrl; var fileTitle = Request[FilesLinkUtility.FileTitle]; if (string.IsNullOrEmpty(fileTitle)) { fileTitle = Path.GetFileName(HttpUtility.UrlDecode(fileUri)) ?? ""; } file = new File { ID = RequestFileUrl, Title = Global.ReplaceInvalidCharsAndTruncate(fileTitle) }; file = DocumentServiceHelper.GetParams(file, true, FileShare.Read, false, false, false, false, false, out _configuration); _configuration.Document.Permissions.Edit = editPossible && !CoreContext.Configuration.Standalone; _configuration.Document.Permissions.Rename = false; _configuration.Document.Permissions.Review = false; _configuration.Document.Permissions.FillForms = false; _configuration.Document.Permissions.ChangeHistory = false; _configuration.Document.Permissions.ModifyFilter = false; _editByUrl = true; _configuration.Document.Url = fileUri; } ErrorMessage = _configuration.ErrorMessage; } catch (Exception ex) { Global.Logger.Warn("DocEditor", ex); ErrorMessage = ex.Message; return; } if (_configuration.EditorConfig.ModeWrite && FileConverter.MustConvert(file)) { try { file = FileConverter.ExecSync(file, RequestShareLinkKey); } catch (Exception ex) { _configuration = null; Global.Logger.Error("DocEditor", ex); ErrorMessage = ex.Message; return; } var comment = "#message/" + HttpUtility.UrlEncode(string.Format(FilesCommonResource.ConvertForEdit, file.Title)); Response.Redirect(FilesLinkUtility.GetFileWebEditorUrl(file.ID) + comment); return; } Title = file.Title + GetPageTitlePostfix(); if (_configuration.EditorConfig.Customization.Goback == null || string.IsNullOrEmpty(_configuration.EditorConfig.Customization.Goback.Url)) { _configuration.EditorConfig.Customization.GobackUrl = Request[FilesLinkUtility.FolderUrl] ?? ""; } _configuration.EditorConfig.Customization.IsRetina = TenantLogoManager.IsRetina(Request); if (RequestEmbedded) { _configuration.Type = Services.DocumentService.Configuration.EditorType.Embedded; _configuration.EditorConfig.Embedded.ShareLinkParam = string.IsNullOrEmpty(RequestShareLinkKey) ? string.Empty : "&" + FilesLinkUtility.DocShareKey + "=" + RequestShareLinkKey; } else { _configuration.Type = IsMobile ? Services.DocumentService.Configuration.EditorType.Mobile : Services.DocumentService.Configuration.EditorType.Desktop; if (FileSharing.CanSetAccess(file) && !(file.Encrypted && (!Request.DesktopApp() || CoreContext.Configuration.Personal))) { _configuration.EditorConfig.SharingSettingsUrl = CommonLinkUtility.GetFullAbsolutePath( Share.Location + "?" + FilesLinkUtility.FileId + "=" + HttpUtility.UrlEncode(file.ID.ToString()) + (Request.DesktopApp() ? "&desktop=true" : string.Empty)); } if (file.RootFolderType == FolderType.Privacy) { if (!PrivacyRoomSettings.Enabled) { _configuration = null; ErrorMessage = FilesCommonResource.ErrorMassage_FileNotFound; return; } else { if (Request.DesktopApp()) { var keyPair = EncryptionKeyPair.GetKeyPair(); if (keyPair != null) { _configuration.EditorConfig.EncryptionKeys = new Services.DocumentService.Configuration.EditorConfiguration.EncryptionKeysConfig { PrivateKeyEnc = keyPair.PrivateKeyEnc, PublicKey = keyPair.PublicKey, }; } } } } } if (!isExtenral) { _docKeyForTrack = DocumentServiceHelper.GetDocKey(file.ID, -1, DateTime.MinValue); FileMarker.RemoveMarkAsNew(file); if (!file.Encrypted && !file.ProviderEntry) { EntryManager.MarkAsRecent(file); } } if (SecurityContext.IsAuthenticated) { _configuration.EditorConfig.SaveAsUrl = CommonLinkUtility.GetFullAbsolutePath(SaveAs.GetUrl); } if (_configuration.EditorConfig.ModeWrite) { _tabId = FileTracker.Add(file.ID); Global.SocketManager.FilesChangeEditors(file.ID); if (SecurityContext.IsAuthenticated) { _configuration.EditorConfig.FileChoiceUrl = CommonLinkUtility.GetFullAbsolutePath(FileChoice.GetUrlForEditor); } } else { _linkToEdit = _editByUrl ? CommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorExternalUrl(fileUri, file.Title)) : CommonLinkUtility.GetFullAbsolutePath(FilesLinkUtility.GetFileWebEditorUrl(file.ID)); if (Request.DesktopApp()) { _linkToEdit += "&desktop=true"; } if (FileConverter.MustConvert(_configuration.Document.Info.File)) { _editByUrl = true; } } var actionAnchor = Request[FilesLinkUtility.Anchor]; if (!string.IsNullOrEmpty(actionAnchor)) { _configuration.EditorConfig.ActionLinkString = actionAnchor; } }
public static void Main(string[] args) { bool verbose = false; bool help = false; bool examples = false; bool encrypt = false; bool decrypt = false; bool sign = false; bool verifySignature = false; bool version = false; bool action = false; bool unmerge = false; bool merge = false; bool newKey = false; bool passwordProtected = false; int keySize = 2048; string passwd = string.Empty; var argsValue = new Dictionary <string, string>(); var opts = new OptionSet { // action { "d|decrypt", "decrypts the encrypted data, requires private key \n[ACTION]", v => { decrypt = v != null; action = true; } }, // action { "e|encrypt", "encrypts the data, if used with -s merge signature to encrypted file \n[ACTION]", v => { encrypt = v != null; action = true; } }, // action { "h|help", "show this message and exit \n[ACTION]", v => { help = v != null; action = true; } }, { "k|key=", "key to use", v => argsValue.Add("key", v) }, { "m|merge", "merge signature with another file, use --signaturefile, warns if no key was specified\n[ACTION]", v => { merge = true; action = true; } }, // action { "n|newkey", "generates a new RSA Key, default size is 2048bits, exports as .pem files by default \n[ACTION]", v => { newKey = true; action = true; } }, { "o|output=", "path to output encrypted files", v => argsValue.Add("output", v) }, { "p|password", "when generating/using a new key use this flag to set password. when using this flag must always be a private key.", v => passwordProtected = true }, // action { "s|sign", "signs data, requires private key \n[ACTION]", v => { sign = v != null; action = true; } }, { "t|target=", "file or directory to be encrypted, decrypted or to verify its signature if directory encrypts all file from that directory", v => argsValue.Add("target", v) }, { "u|unmerge", "unmerge signature from file, requires public key used in signature, use --hashalg to identify wich hashing algorithm was used and verify signature (if none was specified uses default: SHA256)\n[ACTION]", v => { unmerge = true; action = true; } }, // action { "v|verifysignature", "verify if signed data is trustworthy \n[ACTION], use --target for signed data and --signaturefile for signature file", v => { verifySignature = v != null; action = true; } }, { "x|examples", "show specific examples \n[ACTION]", v => { examples = v != null; action = true; } }, { "hashalg=", "type of hashing algorithm, examples: SHA1, SHA256. default value is SHA256", v => _hashAlg = v }, { "keyfilename=", "when generating a new key use this to choose file name, default is \"key\"", v => argsValue.Add("keyfilename", v) }, { "keysize=", "when generating key use this to choose its size, minimum size is 384 and maximum is 16384, key size must be in increments of 8 bits.", (int v) => keySize = v }, { "signaturefile=", "signature file generated based on encrypted file", v => argsValue.Add("signaturefile", v) }, { "verbose", "increase debug message verbosity", v => verbose = v != null }, // action { "version", "shows version \n[ACTION]", v => { version = v != null; action = true; } }, }; try { List <string> extra = opts.Parse(args); string keyPath = argsValue.ContainsKey("key") ? argsValue["key"] : null; // show help when no args, not defined opts // missing action option, show help // when key is null and is not newkey/merge if (help || args == null || extra?.Count > 0 || !action || (string.IsNullOrWhiteSpace(keyPath) && !newKey && !merge)) { ShowHelp(opts); return; } if (examples) { ShowExamples(opts); return; } if (version) { var assembly = Assembly.GetEntryAssembly().GetName(); Console.WriteLine($"v{assembly.Version}"); return; } Console.WriteLine($"[*] Starting {_exeName}..."); var output = argsValue.ContainsKey("output") ? argsValue["output"] : Environment.CurrentDirectory; _hashAlg = string.IsNullOrWhiteSpace(_hashAlg) ? "SHA256" : _hashAlg.ToUpper(); EncryptionKeyPair key = default; if (passwordProtected) { Console.Write("[*] Encrypted Key Password: "); while (true) { var cKey = Console.ReadKey(true); if (cKey.Key != ConsoleKey.Backspace && cKey.Key != ConsoleKey.Enter && cKey.Key != ConsoleKey.Escape && cKey.KeyChar != '\0') { passwd += cKey.KeyChar; } else if (cKey.Key == ConsoleKey.Backspace && passwd.Length > 0) { passwd = passwd[0..^ 1];