private static double ComputePathCost(List<QePatternInstance> l,
			char[] vPassword, EntropyEncoder ecPattern, MultiEntropyEncoder mcData)
		{
			ecPattern.Reset();
			for(int i = 0; i < l.Count; ++i)
				ecPattern.Write(l[i].PatternID);
			double dblPatternCost = ecPattern.GetOutputSize();

			mcData.Reset();
			double dblDataCost = 0.0;
			foreach(QePatternInstance pi in l)
			{
				QeCharType tChar = pi.SingleCharType;
				if(tChar != null)
				{
					char ch = vPassword[pi.Position];
					if(!mcData.Write(tChar.TypeID, ch))
						dblDataCost += pi.Cost;
				}
				else dblDataCost += pi.Cost;
			}
			dblDataCost += mcData.GetOutputSize();

			return (dblPatternCost + dblDataCost);
		}
		/// <summary>
		/// Estimate the quality of a password.
		/// </summary>
		/// <param name="vPasswordChars">Password to check.</param>
		/// <returns>Estimated bit-strength of the password.</returns>
		public static uint EstimatePasswordBits(char[] vPasswordChars)
		{
			if(vPasswordChars == null) { Debug.Assert(false); return 0; }
			if(vPasswordChars.Length == 0) return 0;

			EnsureInitialized();

			int n = vPasswordChars.Length;
			List<QePatternInstance>[] vPatterns = new List<QePatternInstance>[n];
			for(int i = 0; i < n; ++i)
			{
				vPatterns[i] = new List<QePatternInstance>();

				QePatternInstance piChar = new QePatternInstance(i, 1,
					GetCharType(vPasswordChars[i]));
				vPatterns[i].Add(piChar);
			}

			FindRepetitions(vPasswordChars, vPatterns);
			FindNumbers(vPasswordChars, vPatterns);
			FindDiffSeqs(vPasswordChars, vPatterns);
			FindPopularPasswords(vPasswordChars, vPatterns);

			// Encoders must not be static, because the entropy estimation
			// may run concurrently in multiple threads and the encoders are
			// not read-only
			EntropyEncoder ecPattern = new EntropyEncoder(PatternID.All, 0, 1, 0);
			MultiEntropyEncoder mcData = new MultiEntropyEncoder();
			for(int i = 0; i < (m_lCharTypes.Count - 1); ++i)
			{
				// Let m be the alphabet size. In order to ensure that two same
				// characters cost at least as much as a single character, for
				// the probability p and weight w of the character it must hold:
				//     -log(1/m) >= -2*log(p)
				// <=> log(1/m) <= log(p^2) <=> 1/m <= p^2 <=> p >= sqrt(1/m);
				//     sqrt(1/m) = (1+w)/(m+w)
				// <=> m+w = (1+w)*sqrt(m) <=> m+w = sqrt(m) + w*sqrt(m)
				// <=> w*(1-sqrt(m)) = sqrt(m) - m <=> w = (sqrt(m)-m)/(1-sqrt(m))
				// <=> w = (sqrt(m)-m)*(1+sqrt(m))/(1-m)
				// <=> w = (sqrt(m)-m+m-m*sqrt(m))/(1-m) <=> w = sqrt(m)
				ulong uw = (ulong)Math.Sqrt((double)m_lCharTypes[i].CharCount);

				mcData.AddEncoder(m_lCharTypes[i].TypeID, new EntropyEncoder(
					m_lCharTypes[i].Alphabet, 1, uw, 1));
			}

			double dblMinCost = (double)int.MaxValue;
			int tStart = Environment.TickCount;

			Stack<QePathState> sRec = new Stack<QePathState>();
			sRec.Push(new QePathState(0, new List<QePatternInstance>()));
			while(sRec.Count > 0)
			{
				int tDiff = Environment.TickCount - tStart;
				if(tDiff > 500) break;

				QePathState s = sRec.Pop();

				if(s.Position >= n)
				{
					Debug.Assert(s.Position == n);

					double dblCost = ComputePathCost(s.Path, vPasswordChars,
						ecPattern, mcData);
					if(dblCost < dblMinCost) dblMinCost = dblCost;
				}
				else
				{
					List<QePatternInstance> lSubs = vPatterns[s.Position];
					for(int i = lSubs.Count - 1; i >= 0; --i)
					{
						QePatternInstance pi = lSubs[i];
						Debug.Assert(pi.Position == s.Position);
						Debug.Assert(pi.Length >= 1);

						List<QePatternInstance> lNewPath =
							new List<QePatternInstance>(s.Path.Count + 1);
						lNewPath.AddRange(s.Path);
						lNewPath.Add(pi);
						Debug.Assert(lNewPath.Capacity == (s.Path.Count + 1));

						QePathState sNew = new QePathState(s.Position +
							pi.Length, lNewPath);
						sRec.Push(sNew);
					}
				}
			}

			return (uint)Math.Ceiling(dblMinCost);
		}
Beispiel #3
0
        /// <summary>
        /// Estimate the quality of a password.
        /// </summary>
        /// <param name="vPasswordChars">Password to check.</param>
        /// <returns>Estimated bit-strength of the password.</returns>
        public static uint EstimatePasswordBits(char[] vPasswordChars)
        {
            if (vPasswordChars == null)
            {
                Debug.Assert(false); return(0);
            }
            if (vPasswordChars.Length == 0)
            {
                return(0);
            }

            EnsureInitialized();

            int n = vPasswordChars.Length;

            List <QePatternInstance>[] vPatterns = new List <QePatternInstance> [n];
            for (int i = 0; i < n; ++i)
            {
                vPatterns[i] = new List <QePatternInstance>();

                QePatternInstance piChar = new QePatternInstance(i, 1,
                                                                 GetCharType(vPasswordChars[i]));
                vPatterns[i].Add(piChar);
            }

            FindRepetitions(vPasswordChars, vPatterns);
            FindNumbers(vPasswordChars, vPatterns);
            FindDiffSeqs(vPasswordChars, vPatterns);
            FindPopularPasswords(vPasswordChars, vPatterns);

            // Encoders must not be static, because the entropy estimation
            // may run concurrently in multiple threads and the encoders are
            // not read-only
            EntropyEncoder      ecPattern = new EntropyEncoder(PatternID.All, 0, 1, 0);
            MultiEntropyEncoder mcData    = new MultiEntropyEncoder();

            for (int i = 0; i < (m_lCharTypes.Count - 1); ++i)
            {
                // Let m be the alphabet size. In order to ensure that two same
                // characters cost at least as much as a single character, for
                // the probability p and weight w of the character it must hold:
                //     -log(1/m) >= -2*log(p)
                // <=> log(1/m) <= log(p^2) <=> 1/m <= p^2 <=> p >= sqrt(1/m);
                //     sqrt(1/m) = (1+w)/(m+w)
                // <=> m+w = (1+w)*sqrt(m) <=> m+w = sqrt(m) + w*sqrt(m)
                // <=> w*(1-sqrt(m)) = sqrt(m) - m <=> w = (sqrt(m)-m)/(1-sqrt(m))
                // <=> w = (sqrt(m)-m)*(1+sqrt(m))/(1-m)
                // <=> w = (sqrt(m)-m+m-m*sqrt(m))/(1-m) <=> w = sqrt(m)
                ulong uw = (ulong)Math.Sqrt((double)m_lCharTypes[i].CharCount);

                mcData.AddEncoder(m_lCharTypes[i].TypeID, new EntropyEncoder(
                                      m_lCharTypes[i].Alphabet, 1, uw, 1));
            }

            double dblMinCost = (double)int.MaxValue;
            int    tStart     = Environment.TickCount;

            Stack <QePathState> sRec = new Stack <QePathState>();

            sRec.Push(new QePathState(0, new List <QePatternInstance>()));
            while (sRec.Count > 0)
            {
                int tDiff = Environment.TickCount - tStart;
                if (tDiff > 500)
                {
                    break;
                }

                QePathState s = sRec.Pop();

                if (s.Position >= n)
                {
                    Debug.Assert(s.Position == n);

                    double dblCost = ComputePathCost(s.Path, vPasswordChars,
                                                     ecPattern, mcData);
                    if (dblCost < dblMinCost)
                    {
                        dblMinCost = dblCost;
                    }
                }
                else
                {
                    List <QePatternInstance> lSubs = vPatterns[s.Position];
                    for (int i = lSubs.Count - 1; i >= 0; --i)
                    {
                        QePatternInstance pi = lSubs[i];
                        Debug.Assert(pi.Position == s.Position);
                        Debug.Assert(pi.Length >= 1);

                        List <QePatternInstance> lNewPath =
                            new List <QePatternInstance>(s.Path.Count + 1);
                        lNewPath.AddRange(s.Path);
                        lNewPath.Add(pi);
                        Debug.Assert(lNewPath.Capacity == (s.Path.Count + 1));

                        QePathState sNew = new QePathState(s.Position +
                                                           pi.Length, lNewPath);
                        sRec.Push(sNew);
                    }
                }
            }

            return((uint)Math.Ceiling(dblMinCost));
        }
Beispiel #4
0
        private static double ComputePathCost(List <QePatternInstance> l,
                                              char[] vPassword, EntropyEncoder ecPattern, MultiEntropyEncoder mcData)
        {
            ecPattern.Reset();
            for (int i = 0; i < l.Count; ++i)
            {
                ecPattern.Write(l[i].PatternID);
            }
            double dblPatternCost = ecPattern.GetOutputSize();

            mcData.Reset();
            double dblDataCost = 0.0;

            foreach (QePatternInstance pi in l)
            {
                QeCharType tChar = pi.SingleCharType;
                if (tChar != null)
                {
                    char ch = vPassword[pi.Position];
                    if (!mcData.Write(tChar.TypeID, ch))
                    {
                        dblDataCost += pi.Cost;
                    }
                }
                else
                {
                    dblDataCost += pi.Cost;
                }
            }
            dblDataCost += mcData.GetOutputSize();

            return(dblPatternCost + dblDataCost);
        }
        private static double ComputePathCost(List <QePatternInstance> patternInstanceCollection,
                                              char[] password, EntropyEncoder ecPattern, MultiEntropyEncoder mcData)
        {
            ecPattern.Reset();
            for (var i = 0; i < patternInstanceCollection.Count; ++i)
            {
                ecPattern.Write(patternInstanceCollection[i].ThePatternId);
            }

            var dblPatternCost = ecPattern.GetOutputSize();

            mcData.Reset();
            var dblDataCost = 0.0;

            foreach (var parameterInstance in patternInstanceCollection)
            {
                QeCharType characterType = parameterInstance.SingleCharType;
                if (characterType != null)
                {
                    var character = password[parameterInstance.Position];
                    if (!mcData.Write(characterType.TypeId, character))
                    {
                        dblDataCost += parameterInstance.Cost;
                    }
                }
                else
                {
                    dblDataCost += parameterInstance.Cost;
                }
            }
            dblDataCost += mcData.GetOutputSize();

            return(dblPatternCost + dblDataCost);
        }