/// <summary> /// Imports a SQRL identity and stores it in the database. /// </summary> /// <param name="identity">The <c>SQRLIdentity</c> to be imported.</param> /// <param name="setAsCurrentIdentity">If set to <c>true</c>, the imported identity will be /// set as the currently active identity after adding it to the database.</param> public void ImportIdentity(SQRLIdentity identity, bool setAsCurrentIdentity = true) { if (identity.Block0 == null) { throw new InvalidOperationException("The identity does not contain a type 0 block!"); } if (HasIdentity(identity.Block0.UniqueIdentifier.ToHex())) { throw new InvalidOperationException("The identity already exists in the database!"); } Identity newIdRec = new Identity(); newIdRec.Name = identity.IdentityName; newIdRec.UniqueId = identity.Block0.UniqueIdentifier.ToHex(); newIdRec.GenesisId = identity.Block0.GenesisIdentifier.ToHex(); // Serialize the identity for storing it in the database. // We could use identity.ToByteArray() here, but then we would // lose extra information not covered by the S4 format, such // as identity name, file path etc. newIdRec.DataBytes = SerializeIdentity(identity); _db.Identities.Add(newIdRec); _db.SaveChanges(); if (setAsCurrentIdentity) { SetCurrentIdentity(newIdRec.UniqueId); } // Finally, fire the IdentityCountChanged event IdentityCountChanged?.Invoke(this, new IdentityCountChangedEventArgs(this.IdentityCount)); }
public void FromToByteArrayTest() { List <Tuple <byte[], bool> > idVectors = new List <Tuple <byte[], bool> >() { // "Ordinary" identity containing block 1 + 2 Tuple.Create(Sodium.Utilities.HexToBinary("7371726C646174617D0001002D003DF8C1D0D35425CBABE1ECEA13100FCDA8CE1EE9CC6C88A0F512D5F60991000000F30104050F00B10BC086752714EF4AC4330015268AF7716F8AA231C7F912D217189D37BEC4F82CBFF30D7ADC9ECF361E9236BC5E66FCBB6B75E6B7B23D5543F3DC78B50071C77A6CED382249904789E1F6341A91E9DC490002002FBE0BA95BD8FF50053728A565DD3EEF0995000000E64C5A1EDDB214D6B2886AC3FDA1E831C3DDFDD6405035F69E1AFAD21464C75E98CCD59C5A8BE47E39F2A39F2D10D3BA"), false), // Rekeyed 4 times, thus containing a large block 3 Tuple.Create(Sodium.Utilities.HexToBinary("7371726C646174617D0001002D002943D5681A77E7EE06F6878C830D41F1B39BBBF63A9FA58B2022D4DE0990000000F30104050F00066DBAF9D304A4011E980AE2F43C489AD1F8AAC7EB5397F875C06B231D56AFEC1A398E1A5703FB622DEB645A2E77FF456976A312F07F555C5D3407DB23DD47A777CAB5683564FCB677BA63D93E3AF2F249000200415464EDD9EF881606D85D01EBDF0D21098F00000096FA59AD8B58DE81A4ED00C2516CE80BD65CC1389C0A7A89F85F775DBB455E0AF1CF5757F11B17924DC1EB6863D82C20960003000400B19A77C75B9945BEB48BFCC6494244BC5C025EB9F4501017FF04E41C02B7B65ECA95D164C4465AAC3140292598592E56D9A88FCF787B5189BDFD81E238641CE46B0C97E47D5EBDC4DD16D5748874C8A5BFA82515F50F1577E15A157CDD059695A61BF0538217680019E5D9AF34A1F70054A057BFFC6F505E1859FFDCA2EB418F0F1B3903C78B219BDB5D28620BB1BFEB"), false), // .sqrc-File (containing only block 2) Tuple.Create(Sodium.Utilities.HexToBinary("7371726C64617461490002002DD4DEA2238AFF0A553C76AADE9488A309960000006CC320A5DF90DEF5E3F8DCF460B6A5490E7C4CABB93926B0B79D850582C88DE1E698A4F03CC93926CA0015D673DB1686"), false), // Custom block (contains a block of imaginary type 55, which should be retained) Tuple.Create(Sodium.Utilities.HexToBinary("7371726C646174617D0001002D005B6648EBCC4E296A4CBF479E43C67DDBBBCCEBF73E1D5939D18758D3091F000000F30104050F002C6258339401919F4BA3C1B904174BCA18ED3DC25560637D684A2A7C19761709AED12E480CCED7B0D8B21FC13B773578ABA9EC6838B1ED4D110787EFEB9740EFF40536CC5F598A5714EBBF6E2946F0934900020002D86D2A4CEDC1C91951E5410A5DE3CC09200000000752657E822696708F7DCC96D0AD911C0184BD8A06DE16C7509CED8762B53EBAEEA49CB089449204317437BECC5956DB1500370074657374696E67206974206F7574212129"), false), // Base64url-encoded identity (indicated by uppercase "SQRLDATA" header) Tuple.Create(Sodium.Utilities.HexToBinary("5351524C44415441665141424143304150666A42304E4E554A63757234657A71457841507A616A4F48756E4D6249696739524C5639676D5241414141387745454251384173517641686E556E464F394B78444D414653614B3933467669714978785F6B53306863596E54652D78506773765F4D4E657479657A7A59656B6A6138586D623875327431357265795056564438397834745142787833707337546769535A4248696548324E4271523664784A414149414C37344C715676595F3141464E79696C5A64302D37776D5641414141356B786148743279464E6179694772445F61486F4D6350645F645A41554458326E6872363068526B783136597A4E5763576F766B666A6E796F353874454E4F36"), true) }; foreach (var idVector in idVectors) { SQRLIdentity id = SQRLIdentity.FromByteArray(idVector.Item1); byte[] result = id.ToByteArray(); if (!idVector.Item2) // No base 64, straight comparison possible { Assert.Equal(idVector.Item1, result); } else // Take base64url encoding of source vector into account! { Assert.Equal(Encoding.UTF8.GetString(idVector.Item1.Skip(8).ToArray()), Sodium.Utilities.BinaryToBase64(result.Skip(8).ToArray(), Sodium.Utilities.Base64Variant.UrlSafeNoPadding)); } } }
/// <summary> /// Creates a QuickPass from the given <paramref name="password"/> and /// <paramref name="imk"/> using the QuickPass settings stored in /// <paramref name="identity"/>, stores it in memory and establishes a /// timer that will clear the QuickPass after the timeout set forth in /// <paramref name="identity"/>'s QuickPass settings. /// </summary> /// <param name="password">The full identity master password.</param> /// <param name="imk">The identity's unencrypted Identity Master Key (IMK).</param> /// <param name="ilk">The identity's unencrypted Identity Lock Key (ILK).</param> /// <param name="identity">The identity that the QuickPass should be set for.</param> /// <param name="progress">An object implementing the IProgress interface for tracking the operation's progress (optional).</param> /// <param name="progressText">A string representing a text descrition for the progress indicator (optional).</param> public async void SetQuickPass(string password, byte[] imk, byte[] ilk, SQRLIdentity identity, IProgress <KeyValuePair <int, string> > progress = null, string progressText = null) { if (string.IsNullOrEmpty(password)) { Log.Warning("Can't use QuickPass on an empty password, aborting SetQuickPass()!"); return; } QuickPassItem qpi = new QuickPassItem() { EstablishedDate = DateTime.Now, QuickPassLength = identity.Block1.HintLength, IdentityUniqueId = identity.Block0.UniqueIdentifier.ToHex(), ScryptRandomSalt = SodiumCore.GetRandomBytes(16), Nonce = SodiumCore.GetRandomBytes(24), QuickPassTimeoutSecs = identity.Block1.PwdTimeoutMins * 60, ClearQuickPassOnIdle = identity.Block1.OptionFlags.ClearQuickPassOnIdle, ClearQuickPassOnSleep = identity.Block1.OptionFlags.ClearQuickPassOnSleep, ClearQuickPassOnSwitchingUser = identity.Block1.OptionFlags.ClearQuickPassOnSwitchingUser, Timer = new Timer() }; qpi.Timer.Enabled = false; qpi.Timer.AutoReset = false; // Dont restart timer after calling elapsed qpi.Timer.Interval = QP_GENERAL_TIMEOUT_SEC; qpi.Timer.Elapsed += QuickPassTimerElapsed; string quickPass = password.Substring(0, qpi.QuickPassLength); var enScryptResult = await SQRL.EnScryptTime( quickPass, qpi.ScryptRandomSalt, (int)Math.Pow(2, 9), QP_KEYDERIV_SEC, progress, progressText); qpi.ScryptIterationCount = enScryptResult.IterationCount; qpi.EncryptedImk = StreamEncryption.Encrypt(imk, qpi.Nonce, enScryptResult.Key); qpi.EncryptedIlk = StreamEncryption.Encrypt(ilk, qpi.Nonce, enScryptResult.Key); // If we already have a QuickPass entry for this identity, remove it first if (HasQuickPass(qpi.IdentityUniqueId)) { ClearQuickPass(qpi.IdentityUniqueId, QuickPassClearReason.Unspecified); } // Now, add the QuickPass item to our list and start the timer lock (_dataSyncObj) { _quickPassItems.Add(qpi.IdentityUniqueId, qpi); qpi.Timer.Start(); } Log.Information("QuickPass set for identity {IdentityUniqueId}", qpi.IdentityUniqueId); }
/// <summary> /// Creates a PDF document displaying the given identity as QR code and text and /// providing some guidance for the user. /// </summary> /// <param name="fileName">The full file name (including the path) for the document.</param> /// <param name="identity">The identity for which to create the document.</param> /// <param name="blockTypes">Spciefies a list of block types to include.</param> public static void CreateIdentityDocument(string fileName, SQRLIdentity identity, List <ushort> blockTypes) { if (string.IsNullOrEmpty(fileName) || identity == null || blockTypes == null || blockTypes.Count < 1) { throw new ArgumentException(string.Format("{0}, {1} and {2} must be specified and valid!", nameof(fileName), nameof(identity), nameof(blockTypes))); } _pageNr = 0; string title = "\"" + identity.IdentityName + "\" " + _loc.GetLocalizationValue("FileDialogFilterName"); string identityEncryptionMessage = blockTypes.Contains(1) ? _loc.GetLocalizationValue("IdentityDocEncMsgPassword") : _loc.GetLocalizationValue("IdentityDocEncMsgRC"); string textualIdentityMessage = _loc.GetLocalizationValue("IdentityDocumentTextualIdentityMessage"); string guidanceMessage = _loc.GetLocalizationValue("IdentityDocumentGuidanceMessage"); var identityBytes = identity.ToByteArray(includeHeader: true, blockTypes); string textualIdentity = SQRL.GenerateTextualIdentityBase56(identityBytes); var metadata = new SKDocumentPdfMetadata { Author = _assemblyName, Creation = DateTime.Now, Creator = _assemblyName, Keywords = "SQRL,Identity", Modified = DateTime.Now, Producer = "SkiaSharp", Subject = "SQRL Identity Document", Title = "SQRL Identity Document", EncodingQuality = 300, RasterDpi = 300 }; using (SKBitmap qrCode = CreateQRCode(identityBytes)) using (var stream = new SKFileWStream(fileName)) using (_document = SKDocument.CreatePdf(stream, metadata)) { StartNextPage(); float qrCodeWidth = (qrCode.Width <= QRCODE_MAX_SIZE) ? qrCode.Width : QRCODE_MAX_SIZE; float qrCodeHeight = (qrCode.Height <= QRCODE_MAX_SIZE) ? qrCode.Height : QRCODE_MAX_SIZE; DrawTextBlock(title, _fontBold, 23, SKColors.Black, 10f); DrawTextBlock(identityEncryptionMessage, _fontRegular, 12, SKColors.DarkGray, -5f, SKTextAlign.Left, 1.3f); DrawBitmap(qrCode, SKTextAlign.Center, qrCodeWidth, qrCodeHeight, 15f); DrawTextBlock(textualIdentityMessage, _fontRegular, 12, SKColors.DarkGray, 10f, SKTextAlign.Left, 1.3f); DrawTextBlock(textualIdentity, _fontMonoBold, 12, SKColors.Black, 15f, SKTextAlign.Center, 1.3f);; DrawTextBlock(guidanceMessage, _fontRegular, 12, SKColors.DarkGray, 0f, SKTextAlign.Left, 1.3f); EndPage(); _document.Close(); } }
/// <summary> /// The constructor is private because <c>IdentityManager</c> /// implements the singleton pattern. To get an instance, use /// <c>IdentityManager.Instance</c> instead. /// </summary> private IdentityManager() { _db = new SQRLDBContext(); _currentIdentityDB = GetIdentityInternal(GetUserData().LastLoadedIdentity); if (_currentIdentityDB != null) { _currentIdentity = DeserializeIdentity(_currentIdentityDB.DataBytes); } _log.Information("IdentityManager initialized."); }
/// <summary> /// Serializes a <c>SQRLIdentity</c> object to a byte array. /// </summary> /// <param name="identity">The identity to be serialized.</param> private byte[] SerializeIdentity(SQRLIdentity identity) { byte[] identityBtes; IFormatter formatter = new BinaryFormatter(); using (MemoryStream stream = new MemoryStream()) { formatter.Serialize(stream, identity); identityBtes = stream.ToArray(); } return(identityBtes); }
/// <summary> /// Writes changes made to the given <paramref name="identity"/> back to the database. /// </summary> /// <param name="identity">The changed identity which should be updated in the database.</param> public void UpdateIdentity(SQRLIdentity identity) { Identity id = GetIdentityInternal(identity.Block0?.UniqueIdentifier.ToHex()); if (id == null) { throw new ArgumentException("This identity does not exist!", nameof(identity)); } id.DataBytes = SerializeIdentity(identity); _db.SaveChanges(); }
/// <summary> /// Creates a PDF document displaying the given identity as QR code and text and /// providing some guidance for the user. /// </summary> /// <param name="fileName">The full file name (including the path) for the document.</param> /// <param name="identity">The identity for which to create the document.</param> /// <param name="blockTypes">Spciefies a list of block types to include.</param> public static void CreateIdentityDocument(string fileName, SQRLIdentity identity, List <ushort> blockTypes) { if (string.IsNullOrEmpty(fileName) || identity == null) { throw new ArgumentException(string.Format("{0} and {1} must be specified and valid!", nameof(fileName), nameof(identity))); } float yPos = MARGIN_TOP; string title = "\"" + identity.IdentityName + "\" " + _loc.GetLocalizationValue("FileDialogFilterName"); string qrCodeMessage = _loc.GetLocalizationValue("IdentityDocumentQRCodeMessage"); string textualIdentityMessage = _loc.GetLocalizationValue("IdentityDocumentTextualIdentityMessage"); string guidanceMessage = _loc.GetLocalizationValue("IdentityDocumentGuidanceMessage"); var identityBytes = identity.ToByteArray(includeHeader: true, blockTypes); string textualIdentity = SQRL.GenerateTextualIdentityBase56(identityBytes); var metadata = new SKDocumentPdfMetadata { Author = _assemblyName, Creation = DateTime.Now, Creator = _assemblyName, Keywords = "SQRL,Identity", Modified = DateTime.Now, Producer = "SkiaSharp", Subject = "SQRL Identity Document", Title = "SQRL Identity Document", EncodingQuality = 300, RasterDpi = 300 }; using (SKBitmap qrCode = CreateQRCode(identityBytes)) using (var stream = new SKFileWStream(fileName)) using (var document = SKDocument.CreatePdf(stream, metadata)) using (var canvas = document.BeginPage(PAGE_WIDTH, PAGE_HEIGHT)) { float qrCodeWidth = (qrCode.Width <= QRCODE_MAX_SIZE) ? qrCode.Width : QRCODE_MAX_SIZE; float qrCodeHeight = (qrCode.Height <= QRCODE_MAX_SIZE) ? qrCode.Height : QRCODE_MAX_SIZE; float qrCodeXPos = PAGE_WIDTH / 2 - qrCodeWidth / 2; yPos += 10 + DrawTextBlock(canvas, title, yPos, _fontBold, 23, SKColors.Black); yPos += -15 + DrawTextBlock(canvas, qrCodeMessage, yPos, _fontRegular, 12, SKColors.DarkGray, SKTextAlign.Left, 1.3f); canvas.DrawBitmap(qrCode, new SKRect(qrCodeXPos, yPos, qrCodeXPos + qrCodeWidth, yPos + qrCodeHeight)); yPos += qrCodeHeight + 15; yPos += 10 + DrawTextBlock(canvas, textualIdentityMessage, yPos, _fontRegular, 12, SKColors.DarkGray, SKTextAlign.Left, 1.3f); yPos += 15 + DrawTextBlock(canvas, textualIdentity, yPos, _fontMonoBold, 12, SKColors.Black, SKTextAlign.Center, 1.3f); yPos += 00 + DrawTextBlock(canvas, guidanceMessage, yPos, _fontRegular, 12, SKColors.DarkGray, SKTextAlign.Left, 1.3f); DrawFooter(canvas); document.EndPage(); document.Close(); } }
/// <summary> /// Called from various methods to load DB and initialize defaults. /// </summary> public void Initialize() { _db = SQRLDBContext.Instance; _currentIdentityDB = GetIdentityInternal(_appSettings.LastLoadedIdentity); if (_currentIdentityDB != null) { _currentIdentity = DeserializeIdentity(_currentIdentityDB.DataBytes); } else { _currentIdentity = null; } }
public async void IUKRescueCodeEncryptDecryptTest() { for (int i = 0; i < 10; i++) { SQRLIdentity identity = new SQRLIdentity(); byte[] iuk = SQRL.CreateIUK(); string rescueCode = SQRL.CreateRescueCode(); identity = await SQRL.GenerateIdentityBlock2(iuk, rescueCode, identity); var decryptResult = await SQRL.DecryptBlock2(identity, rescueCode); Assert.Equal(Sodium.Utilities.BinaryToHex(iuk), Sodium.Utilities.BinaryToHex(decryptResult.Iuk)); } }
public async void LMKILKPasswordEncryptDecryptTest() { for (int i = 0; i < 50; i++) { SQRLIdentity identity = new SQRLIdentity(); byte[] iuk = SQRL.CreateIUK(); string password = Sodium.Utilities.BinaryToHex(Sodium.SodiumCore.GetRandomBytes(32), Sodium.Utilities.HexFormat.None, Sodium.Utilities.HexCase.Lower); identity = await SQRL.GenerateIdentityBlock1(iuk, password, identity); byte[] imk = SQRL.CreateIMK(iuk); byte[] ilk = SQRL.CreateILK(iuk); var decryptedData = await SQRL.DecryptBlock1(identity, password); Assert.Equal(Sodium.Utilities.BinaryToHex(imk), Sodium.Utilities.BinaryToHex(decryptedData.Imk)); Assert.Equal(Sodium.Utilities.BinaryToHex(ilk), Sodium.Utilities.BinaryToHex(decryptedData.Ilk)); } }
/// <summary> /// Tries setting the identity with the given <paramref name="uniqueId"/> as /// the currently active identity. If the currently selected identity should /// be unspecified, just pass <c>null</c> for the <paramref name="uniqueId"/>. /// </summary> /// <param name="uniqueId">The unique id of the identity to be set active.</param> public void SetCurrentIdentity(string uniqueId) { if (_currentIdentityDB?.UniqueId == uniqueId) { return; } Identity id = null; if (uniqueId != null) { // Fetch the identity from the database id = GetIdentityInternal(uniqueId); if (id == null) { throw new ArgumentException("No matching identity found!", nameof(uniqueId)); } // Set it as currently active identity _currentIdentityDB = id; _currentIdentity = DeserializeIdentity(_currentIdentityDB.DataBytes); // Save the last active identity unique id in the database GetUserData().LastLoadedIdentity = id.UniqueId; _db.SaveChanges(); } else { _currentIdentityDB = null; _currentIdentity = null; } // And finally fire the IdentityChanged event IdentityChanged?.Invoke(this, new IdentityChangedEventArgs( _currentIdentity, (id != null) ? id.Name : "", (id != null) ? id.UniqueId : "")); }
static async Task Main(string[] args) { SQRL sqrl = SQRL.GetInstance(true); Console.WriteLine("Importing Identity"); var progress = new Progress <KeyValuePair <int, string> >(percent => { Console.WriteLine($"{percent.Value}: {percent.Key}%"); }); SQRLIdentity newId = SQRLIdentity.FromFile(Path.Combine(@"C:\Users\jose\Downloads\SQRL-Test-Identity-Resources\", @"Spec-Vectors-Identity.sqrl")); //SQRLIdentity newId = SQRLIdentity.FromFile(Path.Combine(Directory.GetCurrentDirectory(), @"980591756918003626376697.sqrl")); SQRLOpts optsFlags = (sqrl.cps != null && sqrl.cps.Running ? SQRLOpts.SUK | SQRLOpts.CPS : SQRLOpts.SUK); SQRLOptions opts = new SQRLOptions(optsFlags); bool run = true; var block1Keys = await SQRL.DecryptBlock1(newId, "Zingo-Bingo-Slingo-Dingo", progress); if (block1Keys.DecryptionSucceeded) { try { do { Console.WriteLine("Enter SQRL URL:"); string url = Console.ReadLine(); Uri requestURI = new Uri(url); string AltID = ""; var siteKvp = SQRL.CreateSiteKey(requestURI, AltID, block1Keys.Imk); Dictionary <byte[], PriorSiteKeysResult> priorSiteKeys = null; if (newId.Block3 != null && newId.Block3.Edition > 0) { byte[] decryptedBlock3 = SQRL.DecryptBlock3(block1Keys.Imk, newId, out bool allGood); List <byte[]> oldIUKs = new List <byte[]>(); if (allGood) { int skip = 0; int ct = 0; while (skip < decryptedBlock3.Length) { oldIUKs.Add(decryptedBlock3.Skip(skip).Take(32).ToArray()); skip += 32; ; if (++ct >= 3) { break; } } SQRL.ZeroFillByteArray(ref decryptedBlock3); priorSiteKeys = SQRL.CreatePriorSiteKeys(oldIUKs, requestURI, AltID); oldIUKs.Clear(); } } //SQRL.ZeroFillByteArray(ref decryptedData.Item2); //decryptedData.Item2.ZeroFill(); var serverRespose = SQRL.GenerateQueryCommand(requestURI, siteKvp, opts, null, 0, priorSiteKeys); if (!serverRespose.CommandFailed) { if (!serverRespose.CurrentIDMatch && !serverRespose.PreviousIDMatch) { StringBuilder additionalData = null; if (!string.IsNullOrEmpty(serverRespose.SIN)) { additionalData = new StringBuilder(); byte[] ids = SQRL.CreateIndexedSecret(requestURI, AltID, block1Keys.Imk, Encoding.UTF8.GetBytes(serverRespose.SIN)); additionalData.AppendLineWindows($"ins={Sodium.Utilities.BinaryToBase64(ids, Utilities.Base64Variant.UrlSafeNoPadding)}"); } Console.WriteLine("The site doesn't recognize this ID, would you like to proceed and create one? (Y/N)"); if (Console.ReadLine().StartsWith("Y", StringComparison.OrdinalIgnoreCase)) { serverRespose = SQRL.GenerateNewIdentCommand(serverRespose.NewNutURL, siteKvp, serverRespose.FullServerRequest, block1Keys.Ilk, opts, additionalData); } } else if (serverRespose.PreviousIDMatch) { byte[] ursKey = null; ursKey = SQRL.GetURSKey(serverRespose.PriorMatchedKey.Key, Sodium.Utilities.Base64ToBinary( serverRespose.SUK, string.Empty, Sodium.Utilities.Base64Variant.UrlSafeNoPadding)); StringBuilder additionalData = null; if (!string.IsNullOrEmpty(serverRespose.SIN)) { additionalData = new StringBuilder(); byte[] ids = SQRL.CreateIndexedSecret(requestURI, AltID, block1Keys.Imk, Encoding.UTF8.GetBytes(serverRespose.SIN)); additionalData.AppendLineWindows($"ins={Sodium.Utilities.BinaryToBase64(ids, Utilities.Base64Variant.UrlSafeNoPadding)}"); byte[] pids = SQRL.CreateIndexedSecret(serverRespose.PriorMatchedKey.Value.SiteSeed, Encoding.UTF8.GetBytes(serverRespose.SIN)); additionalData.AppendLineWindows($"pins={Sodium.Utilities.BinaryToBase64(pids, Utilities.Base64Variant.UrlSafeNoPadding)}"); } serverRespose = SQRL.GenerateIdentCommandWithReplace( serverRespose.NewNutURL, siteKvp, serverRespose.FullServerRequest, block1Keys.Ilk, ursKey, serverRespose.PriorMatchedKey.Value.KeyPair, opts, additionalData); } else if (serverRespose.CurrentIDMatch) { int askResponse = 0; if (serverRespose.HasAsk) { Console.WriteLine(serverRespose.AskMessage); Console.WriteLine($"Enter 1 for {serverRespose.GetAskButtons[0]} or 2 for {serverRespose.GetAskButtons[1]}"); int resp; do { string response = Console.ReadLine(); int.TryParse(response, out resp); if (resp == 0) { Console.WriteLine("Invalid Entry, please enter 1 or 2 as shown above"); } } while (resp == 0); askResponse = resp; } StringBuilder addClientData = null; if (askResponse > 0) { addClientData = new StringBuilder(); addClientData.AppendLineWindows($"btn={askResponse}"); } if (serverRespose.SQRLDisabled) { Console.WriteLine("SQRL Is Disabled, to Continue you must enable it. Do you want to? (Y/N)"); if (Console.ReadLine().StartsWith("Y", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("Enter your Rescue Code (No Sapces or Dashes)"); string rescueCode = Console.ReadLine().Trim(); progress = new Progress <KeyValuePair <int, string> >(percent => { Console.WriteLine($"Decrypting with Rescue Code: {percent.Key}%"); }); var iukData = await SQRL.DecryptBlock2(newId, rescueCode, progress); if (iukData.DecryptionSucceeded) { byte[] ursKey = null; ursKey = SQRL.GetURSKey(iukData.Iuk, Sodium.Utilities.Base64ToBinary(serverRespose.SUK, string.Empty, Sodium.Utilities.Base64Variant.UrlSafeNoPadding)); iukData.Iuk.ZeroFill(); serverRespose = SQRL.GenerateEnableCommand(serverRespose.NewNutURL, siteKvp, serverRespose.FullServerRequest, ursKey, addClientData, opts); } else { throw new Exception("Failed to Decrypt Block 2, Invalid Rescue Code"); } } } Console.WriteLine("Which Command Would you like to Issue?:"); Console.WriteLine("*********************************************"); Console.WriteLine("0- Ident (Default/Enter) "); Console.WriteLine("1- Disable "); Console.WriteLine("2- Remove "); Console.WriteLine("3- Cancel "); Console.WriteLine("4- Re-Key "); Console.WriteLine("10- Quit "); Console.WriteLine("*********************************************"); var value = Console.ReadLine(); int.TryParse(value, out int selection); switch (selection) { case 0: { serverRespose = SQRL.GenerateSQRLCommand(SQRLCommands.ident, serverRespose.NewNutURL, siteKvp, serverRespose.FullServerRequest, addClientData, opts); if (sqrl.cps != null && sqrl.cps.PendingResponse) { sqrl.cps.cpsBC.Add(new Uri(serverRespose.SuccessUrl)); } } break; case 1: { Console.WriteLine("This will disable all use of this SQRL Identity on the server, are you sure you want to proceed?: (Y/N)"); if (Console.ReadLine().StartsWith("Y", StringComparison.OrdinalIgnoreCase)) { serverRespose = SQRL.GenerateSQRLCommand(SQRLCommands.disable, serverRespose.NewNutURL, siteKvp, serverRespose.FullServerRequest, addClientData, opts); if (sqrl.cps != null && sqrl.cps.PendingResponse) { sqrl.cps.cpsBC.Add(sqrl.cps.Can); } } } break; case 2: { Console.WriteLine("Enter your Rescue Code (No Sapces or Dashes)"); string rescueCode = Console.ReadLine().Trim(); progress = new Progress <KeyValuePair <int, string> >(percent => { Console.WriteLine($"Decrypting with Rescue Code: {percent.Key}%"); }); var iukData = await SQRL.DecryptBlock2(newId, rescueCode); if (iukData.DecryptionSucceeded) { byte[] ursKey = SQRL.GetURSKey(iukData.Iuk, Sodium.Utilities.Base64ToBinary(serverRespose.SUK, string.Empty, Sodium.Utilities.Base64Variant.UrlSafeNoPadding)); iukData.Iuk.ZeroFill(); serverRespose = SQRL.GenerateSQRLCommand(SQRLCommands.remove, serverRespose.NewNutURL, siteKvp, serverRespose.FullServerRequest, addClientData, opts, null, ursKey); if (sqrl.cps != null && sqrl.cps.PendingResponse) { sqrl.cps.cpsBC.Add(sqrl.cps.Can); } } else { throw new Exception("Failed to Decrypt Block 2, Invalid Rescue Code"); } } break; case 3: { if (sqrl.cps != null && sqrl.cps.PendingResponse) { sqrl.cps.cpsBC.Add(sqrl.cps.Can); } } break; default: { Console.WriteLine("bye"); run = false; } break; } } } } while (run); } catch (Exception ex) { Console.WriteLine($"Error: {ex.ToString()}"); } } else { Console.WriteLine("Failed to Decrypt Block 1, bad password!"); } }
public IdentityChangedEventArgs(SQRLIdentity identity, string identityName, string identityUniqueId) { this.Identity = identity; this.IdentityName = identityName; this.IdentityUniqueId = identityUniqueId; }
/// <summary> /// Creates a new <c>NewIdentityVerifyViewModel</c> intance and performs /// some initialization tasks. /// </summary> /// <param name="identity">The newly created identity to be verified.</param> /// <param name="password">The identity's master password set by the user.</param> public NewIdentityVerifyViewModel(SQRLIdentity identity, string password) { Init(); this.Identity = identity; this.Password = password; }