// ref: https://github.com/mirthas/totp-net/blob/master/TOTP/Totp.cs public static string Totp(string key) { var otpParams = new OtpAuth(key); var b32Key = Base32.FromBase32(otpParams.Secret); if (b32Key == null || b32Key.Length == 0) { return(null); } var now = Helpers.EpocUtcNow() / 1000; var sec = now / otpParams.Period; var secBytes = BitConverter.GetBytes(sec); if (BitConverter.IsLittleEndian) { Array.Reverse(secBytes, 0, secBytes.Length); } var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(otpParams.Algorithm); var hasher = algorithm.CreateHash(b32Key); hasher.Append(secBytes); var hash = hasher.GetValueAndReset(); var offset = (hash[hash.Length - 1] & 0xf); var binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8) | (hash[offset + 3] & 0xff); var otp = binary % (int)Math.Pow(10, otpParams.Digits); return(otp.ToString().PadLeft(otpParams.Digits, '0')); }
// ref: https://github.com/mirthas/totp-net/blob/master/TOTP/Totp.cs public static string Totp(string key) { var otpParams = new OtpAuth(key); var b32Key = Base32.FromBase32(otpParams.Secret); if (b32Key == null || b32Key.Length == 0) { return(null); } var now = Helpers.EpocUtcNow() / 1000; var sec = now / otpParams.Period; var secBytes = BitConverter.GetBytes(sec); if (BitConverter.IsLittleEndian) { Array.Reverse(secBytes, 0, secBytes.Length); } var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(otpParams.Algorithm); var hasher = algorithm.CreateHash(b32Key); hasher.Append(secBytes); var hash = hasher.GetValueAndReset(); var offset = (hash[hash.Length - 1] & 0xf); var binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8) | (hash[offset + 3] & 0xff); string otp = string.Empty; if (otpParams.Steam) { var fullCode = binary & 0x7fffffff; for (var i = 0; i < otpParams.Digits; i++) { otp += SteamChars[fullCode % SteamChars.Length]; fullCode = (int)Math.Truncate(fullCode / (double)SteamChars.Length); } } else { var rawOtp = binary % (int)Math.Pow(10, otpParams.Digits); otp = rawOtp.ToString().PadLeft(otpParams.Digits, '0'); } return(otp); }
private void BuildTable(Cipher cipher) { // URIs if (UrisSection != null && Table.Root.Contains(UrisSection)) { Table.Root.Remove(UrisSection); } if (Model.ShowLoginUris) { UrisSection = new TableSection(Helpers.GetEmptyTableSectionTitle()); foreach (var uri in Model.LoginUris) { UrisSection.Add(new UriViewCell(this, uri)); } Table.Root.Add(UrisSection); } // Notes if (Table.Root.Contains(NotesSection)) { Table.Root.Remove(NotesSection); } if (Model.ShowNotes) { Table.Root.Add(NotesSection); } // Fields if (Table.Root.Contains(FieldsSection)) { Table.Root.Remove(FieldsSection); } if (Model.ShowFields) { FieldsSection = new TableSection(AppResources.CustomFields); foreach (var field in Model.Fields) { FieldViewCell fieldCell; switch (field.Type) { case FieldType.Text: fieldCell = new FieldViewCell(this, field, null); break; case FieldType.Hidden: fieldCell = new FieldViewCell(this, field, null, null); break; case FieldType.Boolean: fieldCell = new FieldViewCell(this, field); break; default: continue; } FieldsSection.Add(fieldCell); } Table.Root.Add(FieldsSection); } // Attachments CleanupAttachmentCells(); if (Table.Root.Contains(AttachmentsSection)) { Table.Root.Remove(AttachmentsSection); } if (Model.ShowAttachments && (Helpers.CanAccessPremium() || cipher.OrganizationId != null)) { AttachmentsSection = new TableSection(AppResources.Attachments); AttachmentCells = new List <AttachmentViewCell>(); foreach (var attachment in Model.Attachments.OrderBy(s => s.Name)) { var attachmentCell = new AttachmentViewCell(attachment, async() => { await OpenAttachmentAsync(cipher, attachment); }); AttachmentCells.Add(attachmentCell); AttachmentsSection.Add(attachmentCell); attachmentCell.InitEvents(); } Table.Root.Add(AttachmentsSection); } // Other if (Table.Root.Contains(OtherSection)) { Table.Root.Remove(OtherSection); } Table.Root.Add(OtherSection); // Various types switch (cipher.Type) { case CipherType.Login: if (OtherSection.Contains(LoginPasswordRevisionDateCell)) { OtherSection.Remove(LoginPasswordRevisionDateCell); } if (Model.ShowPasswordRevisionDate) { OtherSection.Add(LoginPasswordRevisionDateCell); } AddSectionCell(LoginUsernameCell, Model.ShowLoginUsername); AddSectionCell(LoginPasswordCell, Model.ShowLoginPassword); if (ItemInformationSection.Contains(LoginTotpCodeCell)) { ItemInformationSection.Remove(LoginTotpCodeCell); } if (cipher.Login?.Totp != null && (Helpers.CanAccessPremium() || cipher.OrganizationUseTotp)) { var totpKey = cipher.Login?.Totp.Decrypt(cipher.OrganizationId); if (!string.IsNullOrWhiteSpace(totpKey)) { var otpParams = new OtpAuth(totpKey); Model.LoginTotpCode = Crypto.Totp(totpKey); if (!string.IsNullOrWhiteSpace(Model.LoginTotpCode)) { TotpTick(totpKey, otpParams.Period); _timerStarted = DateTime.Now; Device.StartTimer(new TimeSpan(0, 0, 1), () => { if (_timerStarted == null || (DateTime.Now - _timerStarted) > _timerMaxLength) { return(false); } TotpTick(totpKey, otpParams.Period); return(true); }); ItemInformationSection.Add(LoginTotpCodeCell); } } } break; case CipherType.Card: AddSectionCell(CardNameCell, Model.ShowCardName); AddSectionCell(CardNumberCell, Model.ShowCardNumber); AddSectionCell(CardBrandCell, Model.ShowCardBrand); AddSectionCell(CardExpCell, Model.ShowCardExp); AddSectionCell(CardCodeCell, Model.ShowCardCode); break; case CipherType.Identity: AddSectionCell(IdNameCell, Model.ShowIdName); AddSectionCell(IdUsernameCell, Model.ShowIdUsername); AddSectionCell(IdCompanyCell, Model.ShowIdCompany); AddSectionCell(IdSsnCell, Model.ShowIdSsn); AddSectionCell(IdPassportNumberCell, Model.ShowIdPassportNumber); AddSectionCell(IdLicenseNumberCell, Model.ShowIdLicenseNumber); AddSectionCell(IdEmailCell, Model.ShowIdEmail); AddSectionCell(IdPhoneCell, Model.ShowIdPhone); AddSectionCell(IdAddressCell, Model.ShowIdAddress); break; default: break; } }