Exemplo n.º 1
0
        public void Base56EncodeDecodeTest()
        {
            using (WebClient wc = new WebClient())
            {
                String   base56FullVectors = wc.DownloadString("https://raw.githubusercontent.com/sqrldev/sqrl-test-vectors/master/vectors/base56-full-format-vectors.txt");
                String[] lines             = base56FullVectors.Split("\n");
                bool     first             = true;

                foreach (var line in lines)
                {
                    if (first || string.IsNullOrEmpty(line))
                    {
                        first = false;
                        continue;
                    }
                    string[] data = line.Replace("\"", "").Split(',');

                    string s         = SQRL.GenerateTextualIdentityBase56(Sodium.Utilities.Base64ToBinary(data[0], string.Empty, Sodium.Utilities.Base64Variant.UrlSafeNoPadding));
                    byte[] alpha     = SQRL.Base56DecodeIdentity(s);
                    string inputData = Sodium.Utilities.BinaryToBase64(alpha, Sodium.Utilities.Base64Variant.UrlSafeNoPadding);

                    Assert.Equal(inputData.CleanUpString(), data[0].CleanUpString());
                }
            }
        }
Exemplo n.º 2
0
        public void GenerateIndexedSecretTest()
        {
            using (WebClient wc = new WebClient())
            {
                String   insVectors = wc.DownloadString("https://raw.githubusercontent.com/sqrldev/sqrl-test-vectors/master/vectors/ins-vectors.txt");
                String[] lines      = insVectors.Split("\n");
                bool     first      = true;

                foreach (var line in lines)
                {
                    if (first || string.IsNullOrEmpty(line))
                    {
                        first = false;
                        continue;
                    }
                    string[] data = line.CleanUpString().Replace("\"", "").Split(',');

                    var ins = SQRL.CreateIndexedSecret(
                        new Uri($"sqrl://{data[1]}"),
                        string.Empty,
                        Sodium.Utilities.Base64ToBinary(data[0], string.Empty, Sodium.Utilities.Base64Variant.UrlSafeNoPadding),
                        Encoding.UTF8.GetBytes(data[2]),
                        true);

                    Assert.Equal(Sodium.Utilities.BinaryToBase64(ins, Sodium.Utilities.Base64Variant.UrlSafeNoPadding), data[3]);
                }
            }
        }
Exemplo n.º 3
0
        public void FromBase64URLWithoutPadding_2_equals_padding_needed()
        {
            var input  = "YQ";
            var result = SQRL.FromBase64URL(input);

            Assert.AreEqual("a", result);
        }
Exemplo n.º 4
0
        /// <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);
        }
Exemplo n.º 5
0
        public IActionResult Index()
        {
            var vm = new IndexVM
            {
                SQRLLoginLink = $"sqrl://{Request.Host}/{SQRL.LoginLink(RequestIP)}"
            };

            return(View(vm));
        }
        /// <summary>
        /// Verifies whether the user has copied down and entered the correct rescue code,
        /// and, upon successful verification, imports the identity into the database and
        /// navigates to the "Export Identity" screen.
        /// </summary>
        public async void VerifyRescueCode()
        {
            var progressBlock1 = new Progress <KeyValuePair <int, string> >();
            var progressBlock2 = new Progress <KeyValuePair <int, string> >();
            var progressDialog = new ProgressDialogViewModel(new List <Progress <KeyValuePair <int, string> > >()
            {
                progressBlock1, progressBlock2
            }, this);

            progressDialog.ShowDialog();


            var block1Task = SQRL.DecryptBlock1(this.Identity, this.Password, progressBlock1);
            var block2Task = SQRL.DecryptBlock2(this.Identity, SQRL.CleanUpRescueCode(this.RescueCode), progressBlock2);
            await Task.WhenAll(block1Task, block2Task);


            progressDialog.Close();

            string msg = "";

            if (!block1Task.Result.DecryptionSucceeded)
            {
                msg = _loc.GetLocalizationValue("InvalidPasswordMessage") + Environment.NewLine;
            }
            if (!block2Task.Result.DecryptionSucceeded)
            {
                msg = _loc.GetLocalizationValue("InvalidRescueCodeMessage") + Environment.NewLine;
            }

            if (!string.IsNullOrEmpty(msg))
            {
                _ = await new MessageBoxViewModel(_loc.GetLocalizationValue("ErrorTitleGeneric"), $"{msg}",
                                                  MessageBoxSize.Medium, MessageBoxButtons.OK, MessageBoxIcons.ERROR)
                    .ShowDialog(this);
            }
            else
            {
                try
                {
                    _identityManager.ImportIdentity(this.Identity, true);
                }
                catch (InvalidOperationException e)
                {
                    await new MessageBoxViewModel(_loc.GetLocalizationValue("ErrorTitleGeneric"),
                                                  e.Message, MessageBoxSize.Medium,
                                                  MessageBoxButtons.OK, MessageBoxIcons.ERROR)
                    .ShowDialog(this);
                }
                finally
                {
                    ((MainWindowViewModel)_mainWindow.DataContext).Content =
                        new ExportIdentityViewModel();
                }
            }
        }
Exemplo n.º 7
0
        /// <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();
                    }
        }
        public async void CopyToClipboard()
        {
            string identity = SQRL.GenerateTextualIdentityBase56(this.Identity.ToByteArray());
            await Application.Current.Clipboard.SetTextAsync(identity);


            await new Views.MessageBox(_loc.GetLocalizationValue("IdentityExportedMessageBoxTitle"),
                                       _loc.GetLocalizationValue("IdentityCopiedToClipboardMessageBoxText"),
                                       MessageBoxSize.Medium, MessageBoxButtons.OK, MessageBoxIcons.OK)
            .ShowDialog <MessagBoxDialogResult>(_mainWindow);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Copies the textual version of the current identity to the clipboard.
        /// </summary>
        public async void CopyToClipboard()
        {
            var textualIdentityBytes = this.Identity.ToByteArray(includeHeader: true, _blocksToExport);

            string identity = SQRL.GenerateTextualIdentityBase56(textualIdentityBytes);
            await Application.Current.Clipboard.SetTextAsync(identity);

            await new MessageBoxViewModel(_loc.GetLocalizationValue("IdentityExportedMessageBoxTitle"),
                                          _loc.GetLocalizationValue("IdentityCopiedToClipboardMessageBoxText"),
                                          MessageBoxSize.Medium, MessageBoxButtons.OK, MessageBoxIcons.OK)
            .ShowDialog(this);
        }
Exemplo n.º 10
0
        /// <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();
                        }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Handles CPS response for all requests
        /// </summary>
        /// <param name="header">Sets the title and heading line on the SQRL Abort HTML Generated page</param>
        /// <param name="message">Sets the body of the SQRL Abort HTML Generated page</param>
        /// <param name="backUrlText">Sets the text on the Back Now link on the SQRL Abort HTML Generated page</param>
        /// <param name="succesUrl">Success URL passed in if the response is a successful Auth Ident</param>
        public static void HandlePendingCPS(string header = "", string message = "", string backUrlText = "", Uri succesUrl = null)
        {
            /* There are some points in the application where all else fails and we still wantt o try and gracefully exit CPS
             * in these instances we may not have access to the localization so we are hard coding these here as backup
             * they only get called this way in extreme cases.
             */
            if (string.IsNullOrEmpty(header))
            {
                header = "Authentication Aborted";
            }
            if (string.IsNullOrEmpty(message))
            {
                message = "SQRL's CPS authentication has been aborted. You will be automatically sent back to the previous page in a few seconds. If this does not work, please press your browser's BACK button or click the link below.";
            }
            if (string.IsNullOrEmpty(backUrlText))
            {
                backUrlText = "Go Back Now";
            }

            // Note we want to handle CPS if it already exists, but we don't want to start up the CPS Server for no reason.
            var sqrlIntance = SQRL.GetInstance(false);


            if (sqrlIntance.cps != null && sqrlIntance.cps.PendingResponse)
            {
                if (succesUrl == null)
                {
                    sqrlIntance.cps.CPSAbortHeader   = header;
                    sqrlIntance.cps.CPSAbortMessage  = message;
                    sqrlIntance.cps.CPSAbortLinkText = backUrlText;

                    if (sqrlIntance.cps.Can != null)
                    {
                        sqrlIntance.cps.cpsBC.Add(sqrlIntance.cps.Can);
                    }
                    else
                    {
                        sqrlIntance.cps.cpsBC.Add(sqrlIntance.cps.AbortURL);
                    }
                }
                else
                {
                    sqrlIntance.cps.cpsBC.Add(succesUrl);
                }
                while (sqrlIntance.cps.PendingResponse)
                {
                    ;
                }
            }
        }
Exemplo n.º 12
0
        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));
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Decrypts the Identity Master Key (IMK) for for the given <paramref name="identityUniqueId"/>
        /// using the provided <paramref name="quickPass"/> and returns it. If <c>null</c> is passed for
        /// <paramref name="identityUniqueId"/>, the decrypted IML for the current identity will be returned.
        /// </summary>
        /// <param name="quickPass">The QuickPass (first x characters from the identity's master password
        /// which was used to encrypt the IMK when setting the QuickPass entry for the identity.</param>
        /// <param name="identityUniqueId">The hex representation of the identity's unique id (block 0),
        /// or <c>null</c> if you want to decrypt the current identity's IMK.</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>
        /// <returns>The decrypted block 1 keys (IMK, ILK) for the given <paramref name="identityUniqueId"/>, or
        /// <c>null</c> if no such QuickPass entry exists.</returns>
        public async Task <QuickPassDecryptedKeys> GetQuickPassDecryptedImk(string quickPass, string identityUniqueId        = null,
                                                                            IProgress <KeyValuePair <int, string> > progress = null, string progressText = null)
        {
            QuickPassItem qpi = null;

            if (identityUniqueId == null)
            {
                if (_identityManager.CurrentIdentity == null)
                {
                    return(null);
                }
                identityUniqueId = _identityManager.CurrentIdentity?.Block0?.UniqueIdentifier?.ToHex();
            }


            if (identityUniqueId == null)
            {
                Log.Error("Could not resolve current identity in {MethodName}, throwing Exception!",
                          nameof(GetQuickPassDecryptedImk));

                throw new InvalidOperationException("Cannot return QuickPass-decrypted IMK without an identity!");
            }

            lock (_dataSyncObj)
            {
                if (!_quickPassItems.ContainsKey(identityUniqueId))
                {
                    Log.Warning("No identity found for id {IdentityUniqueId} in {MethodName}",
                                identityUniqueId, nameof(GetQuickPassDecryptedImk));

                    return(null);
                }

                qpi = _quickPassItems[identityUniqueId];
            }

            byte[] key = await SQRL.EnScryptCT(quickPass, qpi.ScryptRandomSalt, (int)Math.Pow(2, 9),
                                               qpi.ScryptIterationCount, progress, progressText);

            byte[] decryptedImk = StreamEncryption.Decrypt(qpi.EncryptedImk, qpi.Nonce, key);
            byte[] decryptedIlk = StreamEncryption.Decrypt(qpi.EncryptedIlk, qpi.Nonce, key);

            Log.Information("QuickPass retrieved for identity {IdentityUniqueId}",
                            identityUniqueId);

            return(new QuickPassDecryptedKeys(decryptedImk, decryptedIlk));
        }
Exemplo n.º 14
0
        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));
            }
        }
Exemplo n.º 15
0
        public void VerifyDetached()
        {
            //client=dmVyPTENCmNtZD1pZGVudA0KaWRrPXhZdjhvRzY2RE1HWEs4VENXQjU0QkFPcTk5LWFDcEZiMEw2NGE5b3JBcWsNCm9wdD1jcHN-c3VrDQo&server=dmVyPTENCm51dD1HdWZJYkQzVVhlMVpGYkpxdVNOQ2ZBDQp0aWY9NQ0KcXJ5PS9zcXJsP251dD1HdWZJYkQzVVhlMVpGYkpxdVNOQ2ZBDQpzdWs9dVUwUG1rRnpDVFMyUjkxOWpfQ3VKb0EtR0h2T0lvN3JqZ0Q3QUhVTVptNA0K&ids=xvbYlKjPU_bVkSacpXakcJhJX6ZaiPa8cX9wGtVbeEHROddvmQ5ec-xDuMmuPg4-p7Os-PDTO8ZJC12oW-48CQ

            var ids    = "xvbYlKjPU_bVkSacpXakcJhJX6ZaiPa8cX9wGtVbeEHROddvmQ5ec-xDuMmuPg4-p7Os-PDTO8ZJC12oW-48CQ";
            var client = "dmVyPTENCmNtZD1pZGVudA0KaWRrPXhZdjhvRzY2RE1HWEs4VENXQjU0QkFPcTk5LWFDcEZiMEw2NGE5b3JBcWsNCm9wdD1jcHN-c3VrDQo";
            var server = "dmVyPTENCm51dD1HdWZJYkQzVVhlMVpGYkpxdVNOQ2ZBDQp0aWY9NQ0KcXJ5PS9zcXJsP251dD1HdWZJYkQzVVhlMVpGYkpxdVNOQ2ZBDQpzdWs9dVUwUG1rRnpDVFMyUjkxOWpfQ3VKb0EtR0h2T0lvN3JqZ0Q3QUhVTVptNA0K";

            var idk = "xYv8oG66DMGXK8TCWB54BAOq99-aCpFb0L64a9orAqk";
            var msg = client + server;

            var msgBytes = Encoding.UTF8.GetBytes(msg);
            var sigBytes = SQRL.FromBase64URL(ids);
            var keyBytes = SQRL.FromBase64URL(idk);

            var result = Sodium.PublicKeyAuth.VerifyDetached(sigBytes, msgBytes, keyBytes);

            Assert.IsTrue(result);
        }
Exemplo n.º 16
0
        public void EnHashTest()
        {
            using (WebClient wc = new WebClient())
            {
                String   enHashVectors = wc.DownloadString("https://raw.githubusercontent.com/sqrldev/sqrl-test-vectors/master/vectors/enhash-vectors.txt");
                String[] lines         = enHashVectors.Split("\n");
                bool     first         = true;

                foreach (var line in lines)
                {
                    if (first || string.IsNullOrEmpty(line))
                    {
                        first = false;
                        continue;
                    }
                    string[] data   = line.Replace("\"", "").Split(',');
                    byte[]   ary    = SQRL.EnHash(Sodium.Utilities.Base64ToBinary(data[0], "", Sodium.Utilities.Base64Variant.UrlSafeNoPadding));
                    string   hex    = data[1];
                    string   result = Sodium.Utilities.BinaryToBase64(ary, Sodium.Utilities.Base64Variant.UrlSafeNoPadding);
                    Assert.Equal(hex.CleanUpString(), result.CleanUpString());
                }
            }
        }
Exemplo n.º 17
0
        public void GenerateSiteKeysTest()
        {
            using (WebClient wc = new WebClient())
            {
                String   identityVectors = wc.DownloadString("https://raw.githubusercontent.com/sqrldev/sqrl-test-vectors/master/vectors/identity-vectors.txt");
                String[] lines           = identityVectors.Split("\n");
                bool     first           = true;

                foreach (var line in lines)
                {
                    if (first || string.IsNullOrEmpty(line))
                    {
                        first = false;
                        continue;
                    }
                    string[] data = line.CleanUpString().Replace("\"", "").Split(',');

                    var keys = SQRL.CreateSiteKey(new Uri($"sqrl://{data[3]}"), data[4], Sodium.Utilities.Base64ToBinary(data[2], string.Empty, Sodium.Utilities.Base64Variant.UrlSafeNoPadding), true);

                    Assert.Equal(Sodium.Utilities.BinaryToBase64(keys.PublicKey, Sodium.Utilities.Base64Variant.UrlSafeNoPadding), data[5]);
                }
            }
        }
Exemplo n.º 18
0
        public async void EnScryptTest()
        {
            using (WebClient wc = new WebClient())
            {
                String   enScryptVectors = wc.DownloadString("https://raw.githubusercontent.com/sqrldev/sqrl-test-vectors/master/vectors/enscrypt-vectors.txt");
                String[] lines           = enScryptVectors.Split(Environment.NewLine);
                bool     first           = true;

                foreach (var line in lines)
                {
                    if (first || string.IsNullOrEmpty(line))
                    {
                        first = false;
                        continue;
                    }
                    string[] data = line.Replace("\"", "").Split(',');
                    byte[]   ary  = await SQRL.EnScryptCT(data[0], Encoding.UTF8.GetBytes(data[1]), (int)Math.Pow(2, 9), int.Parse(data[2]));

                    string hex    = data[4];
                    string result = Sodium.Utilities.BinaryToHex(ary);
                    Assert.Equal(hex.CleanUpString(), result.CleanUpString());
                }
            }
        }
Exemplo n.º 19
0
 /// <summary>
 /// Creates a new <c>App</c> instance.
 /// </summary>
 public App() : base()
 {
     this.Localization = new LocalizationExtension();
     SQRL.StartCPSServer();
     SQRL.CPS.CPSRequestReceived += CPSRequestReceived;
 }
Exemplo n.º 20
0
        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!");
            }
        }