| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | using InABox.Clients;using InABox.Core;using InABox.Wpf;using Microsoft.Exchange.WebServices.Data;using Syncfusion.UI.Xaml.Controls.Barcode;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Web;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Shapes;namespace PRSDesktop.Panels.Users{    /// <summary>    /// Interaction logic for QR2FAWindow.xaml    /// </summary>    public partial class QR2FAWindow : ThemableWindow    {        private User User;        public QR2FAWindow(User user)        {            User = user;            user.AuthenticatorToken ??= User.GenerateAuthenticationToken();            InitializeComponent();            Barcode.QuietZone.All = 0;            SetBarcodeText(user.UserID, user.AuthenticatorToken);            Reset.IsEnabled = Security.CanEdit<User>();        }        public void SetBarcodeText(string userID, byte[] key)        {            var secret = Base32Encoding.ToString(key).Trim('=');            var info = new Client<CompanyInformation>().Load().FirstOrDefault();            if (info == null)                info = new CompanyInformation();            SetupKey.Text = secret;            Barcode.Text = $"otpauth://totp/PRS-{Uri.EscapeDataString(userID)}?secret={secret}&issuer=PRS%20-%20{Uri.EscapeDataString(info.CompanyName)}";        }        private void OK_Click(object sender, RoutedEventArgs e)        {            DialogResult = true;            Close();        }        private void Reset_Click(object sender, RoutedEventArgs e)        {            if(MessageBox.Show("Doing this will invalidate the authentication of this user, preventing them from being able to log in until they have rescanned this code. Do you wish to proceed?", "Continue?", MessageBoxButton.YesNo) == MessageBoxResult.Yes)            {                User.AuthenticatorToken = User.GenerateAuthenticationToken();                SetBarcodeText(User.UserID, User.AuthenticatorToken);            }        }    }    // Code taken from https://stackoverflow.com/questions/641361/base32-decoding    public class Base32Encoding    {        public static byte[] ToBytes(string input)        {            if (string.IsNullOrEmpty(input))            {                throw new ArgumentNullException("input");            }            input = input.TrimEnd('='); //remove padding characters            int byteCount = input.Length * 5 / 8; //this must be TRUNCATED            byte[] returnArray = new byte[byteCount];            byte curByte = 0, bitsRemaining = 8;            int mask = 0, arrayIndex = 0;            foreach (char c in input)            {                int cValue = CharToValue(c);                if (bitsRemaining > 5)                {                    mask = cValue << (bitsRemaining - 5);                    curByte = (byte)(curByte | mask);                    bitsRemaining -= 5;                }                else                {                    mask = cValue >> (5 - bitsRemaining);                    curByte = (byte)(curByte | mask);                    returnArray[arrayIndex++] = curByte;                    curByte = (byte)(cValue << (3 + bitsRemaining));                    bitsRemaining += 3;                }            }            //if we didn't end with a full byte            if (arrayIndex != byteCount)            {                returnArray[arrayIndex] = curByte;            }            return returnArray;        }        public static string ToString(byte[] input)        {            if (input == null || input.Length == 0)            {                throw new ArgumentNullException("input");            }            int charCount = (int)Math.Ceiling(input.Length / 5d) * 8;            char[] returnArray = new char[charCount];            byte nextChar = 0, bitsRemaining = 5;            int arrayIndex = 0;            foreach (byte b in input)            {                nextChar = (byte)(nextChar | (b >> (8 - bitsRemaining)));                returnArray[arrayIndex++] = ValueToChar(nextChar);                if (bitsRemaining < 4)                {                    nextChar = (byte)((b >> (3 - bitsRemaining)) & 31);                    returnArray[arrayIndex++] = ValueToChar(nextChar);                    bitsRemaining += 5;                }                bitsRemaining -= 3;                nextChar = (byte)((b << bitsRemaining) & 31);            }            //if we didn't end with a full char            if (arrayIndex != charCount)            {                returnArray[arrayIndex++] = ValueToChar(nextChar);                while (arrayIndex != charCount) returnArray[arrayIndex++] = '='; //padding            }            return new string(returnArray);        }        private static int CharToValue(char c)        {            int value = (int)c;            //65-90 == uppercase letters            if (value < 91 && value > 64)            {                return value - 65;            }            //50-55 == numbers 2-7            if (value < 56 && value > 49)            {                return value - 24;            }            //97-122 == lowercase letters            if (value < 123 && value > 96)            {                return value - 97;            }            throw new ArgumentException("Character is not a Base32 character.", "c");        }        private static char ValueToChar(byte b)        {            if (b < 26)            {                return (char)(b + 65);            }            if (b < 32)            {                return (char)(b + 24);            }            throw new ArgumentException("Byte is not a value Base32 value.", "b");        }    }}
 |