Exemplo n.º 1
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);
        }