internal static bool PrepareCharSet(PwCharSet pwCharSet, PwProfile pwProfile)
        {
            uint cc = pwCharSet.Size;

            for (uint i = 0; i < cc; ++i)
            {
                char ch = pwCharSet[i];
                if ((ch == char.MinValue) || (ch == '\t') || (ch == '\r') ||
                    (ch == '\n') || char.IsSurrogate(ch))
                {
                    return(false);
                }
            }

            if (pwProfile.ExcludeLookAlike)
            {
                pwCharSet.Remove(PwCharSet.LookAlike);
            }

            if (!string.IsNullOrEmpty(pwProfile.ExcludeCharacters))
            {
                pwCharSet.Remove(pwProfile.ExcludeCharacters);
            }

            return(true);
        }
        internal static void PrepareCharSet(PwCharSet pwCharSet, PwProfile pwProfile)
        {
            pwCharSet.Remove(PwCharSet.Invalid);

            if (pwProfile.ExcludeLookAlike)
            {
                pwCharSet.Remove(PwCharSet.LookAlike);
            }

            if (pwProfile.ExcludeCharacters.Length > 0)
            {
                pwCharSet.Remove(pwProfile.ExcludeCharacters);
            }
        }
        public static PwgError Generate(out ProtectedString psOut,
                                        PwProfile pwProfile, byte[] pbUserEntropy,
                                        CustomPwGeneratorPool pwAlgorithmPool)
        {
            Debug.Assert(pwProfile != null);
            if (pwProfile == null)
            {
                throw new ArgumentNullException("pwProfile");
            }

            PwgError           e   = PwgError.Unknown;
            CryptoRandomStream crs = null;

            byte[] pbKey = null;
            try
            {
                crs = CreateRandomStream(pbUserEntropy, out pbKey);

                if (pwProfile.GeneratorType == PasswordGeneratorType.CharSet)
                {
                    e = CharSetBasedGenerator.Generate(out psOut, pwProfile, crs);
                }
                else if (pwProfile.GeneratorType == PasswordGeneratorType.Pattern)
                {
                    e = PatternBasedGenerator.Generate(out psOut, pwProfile, crs);
                }
                else if (pwProfile.GeneratorType == PasswordGeneratorType.Custom)
                {
                    e = GenerateCustom(out psOut, pwProfile, crs, pwAlgorithmPool);
                }
                else
                {
                    Debug.Assert(false); psOut = ProtectedString.Empty;
                }
            }
            finally
            {
                if (crs != null)
                {
                    crs.Dispose();
                }
                if (pbKey != null)
                {
                    MemUtil.ZeroByteArray(pbKey);
                }
            }

            return(e);
        }
        internal static PwgError Generate(out ProtectedString psOut,
                                          PwProfile pwProfile, CryptoRandomStream crsRandomSource)
        {
            psOut = ProtectedString.Empty;
            if (pwProfile.Length == 0)
            {
                return(PwgError.Success);
            }

            PwCharSet pcs = new PwCharSet(pwProfile.CharSet.ToString());

            if (!PwGenerator.PrepareCharSet(pcs, pwProfile))
            {
                return(PwgError.InvalidCharSet);
            }

            char[] v = new char[pwProfile.Length];
            try
            {
                for (int i = 0; i < v.Length; ++i)
                {
                    char ch = PwGenerator.GenerateCharacter(pcs, crsRandomSource);
                    if (ch == char.MinValue)
                    {
                        return(PwgError.TooFewCharacters);
                    }

                    v[i] = ch;
                    if (pwProfile.NoRepeatingCharacters)
                    {
                        pcs.Remove(ch);
                    }
                }

                byte[] pbUtf8 = StrUtil.Utf8.GetBytes(v);
                psOut = new ProtectedString(true, pbUtf8);
                MemUtil.ZeroByteArray(pbUtf8);
            }
            finally { MemUtil.ZeroArray <char>(v); }

            return(PwgError.Success);
        }
        internal static char GenerateCharacter(PwProfile pwProfile,
                                               PwCharSet pwCharSet, CryptoRandomStream crsRandomSource)
        {
            if (pwCharSet.Size == 0)
            {
                return(char.MinValue);
            }

            ulong uIndex = crsRandomSource.GetRandomUInt64();

            uIndex %= (ulong)pwCharSet.Size;

            char ch = pwCharSet[(uint)uIndex];

            if (pwProfile.NoRepeatingCharacters)
            {
                pwCharSet.Remove(ch);
            }

            return(ch);
        }
        private static PwgError GenerateCustom(out ProtectedString psOut,
                                               PwProfile pwProfile, CryptoRandomStream crs,
                                               CustomPwGeneratorPool pwAlgorithmPool)
        {
            psOut = ProtectedString.Empty;

            Debug.Assert(pwProfile.GeneratorType == PasswordGeneratorType.Custom);
            if (pwAlgorithmPool == null)
            {
                return(PwgError.UnknownAlgorithm);
            }

            string strID = pwProfile.CustomAlgorithmUuid;

            if (string.IsNullOrEmpty(strID))
            {
                Debug.Assert(false); return(PwgError.UnknownAlgorithm);
            }

            byte[]            pbUuid = Convert.FromBase64String(strID);
            PwUuid            uuid   = new PwUuid(pbUuid);
            CustomPwGenerator pwg    = pwAlgorithmPool.Find(uuid);

            if (pwg == null)
            {
                Debug.Assert(false); return(PwgError.UnknownAlgorithm);
            }

            ProtectedString pwd = pwg.Generate(pwProfile.CloneDeep(), crs);

            if (pwd == null)
            {
                return(PwgError.Unknown);
            }

            psOut = pwd;
            return(PwgError.Success);
        }
        internal static PwgError Generate(out ProtectedString psOut,
                                          PwProfile pwProfile, CryptoRandomStream crsRandomSource)
        {
            psOut = ProtectedString.Empty;
            if (pwProfile.Length == 0)
            {
                return(PwgError.Success);
            }

            PwCharSet pcs = new PwCharSet(pwProfile.CharSet.ToString());

            char[] vGenerated = new char[pwProfile.Length];

            PwGenerator.PrepareCharSet(pcs, pwProfile);

            for (int nIndex = 0; nIndex < (int)pwProfile.Length; ++nIndex)
            {
                char ch = PwGenerator.GenerateCharacter(pwProfile, pcs,
                                                        crsRandomSource);

                if (ch == char.MinValue)
                {
                    MemUtil.ZeroArray <char>(vGenerated);
                    return(PwgError.TooFewCharacters);
                }

                vGenerated[nIndex] = ch;
            }

            byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vGenerated);
            psOut = new ProtectedString(true, pbUtf8);
            MemUtil.ZeroByteArray(pbUtf8);
            MemUtil.ZeroArray <char>(vGenerated);

            return(PwgError.Success);
        }
 /// <summary>
 /// Password generation function.
 /// </summary>
 /// <param name="prf">Password generation options chosen
 /// by the user. This may be <c>null</c>, if the default
 /// options should be used.</param>
 /// <param name="crsRandomSource">Source that the algorithm
 /// can use to generate random numbers.</param>
 /// <returns>Generated password or <c>null</c> in case
 /// of failure. If returning <c>null</c>, the caller assumes
 /// that an error message has already been shown to the user.</returns>
 public abstract ProtectedString Generate(PwProfile prf,
                                          CryptoRandomStream crsRandomSource);
Exemple #9
0
        internal static PwgError Generate(out ProtectedString psOut,
                                          PwProfile pwProfile, CryptoRandomStream crsRandomSource)
        {
            psOut = ProtectedString.Empty;
            LinkedList <char> vGenerated = new LinkedList <char>();
            PwCharSet         pcsCurrent = new PwCharSet();
            PwCharSet         pcsCustom  = new PwCharSet();
            PwCharSet         pcsUsed    = new PwCharSet();
            bool bInCharSetDef           = false;

            string strPattern = ExpandPattern(pwProfile.Pattern);

            if (strPattern.Length == 0)
            {
                return(PwgError.Success);
            }

            CharStream csStream = new CharStream(strPattern);
            char       ch       = csStream.ReadChar();

            while (ch != char.MinValue)
            {
                pcsCurrent.Clear();

                bool bGenerateChar = false;

                if (ch == '\\')
                {
                    ch = csStream.ReadChar();
                    if (ch == char.MinValue)                    // Backslash at the end
                    {
                        vGenerated.AddLast('\\');
                        break;
                    }

                    if (bInCharSetDef)
                    {
                        pcsCustom.Add(ch);
                    }
                    else
                    {
                        vGenerated.AddLast(ch);
                        pcsUsed.Add(ch);
                    }
                }
                else if (ch == '^')
                {
                    ch = csStream.ReadChar();
                    if (ch == char.MinValue)                    // ^ at the end
                    {
                        vGenerated.AddLast('^');
                        break;
                    }

                    if (bInCharSetDef)
                    {
                        pcsCustom.Remove(ch);
                    }
                }
                else if (ch == '[')
                {
                    pcsCustom.Clear();
                    bInCharSetDef = true;
                }
                else if (ch == ']')
                {
                    pcsCurrent.Add(pcsCustom.ToString());

                    bInCharSetDef = false;
                    bGenerateChar = true;
                }
                else if (bInCharSetDef)
                {
                    if (pcsCustom.AddCharSet(ch) == false)
                    {
                        pcsCustom.Add(ch);
                    }
                }
                else if (pcsCurrent.AddCharSet(ch) == false)
                {
                    vGenerated.AddLast(ch);
                    pcsUsed.Add(ch);
                }
                else
                {
                    bGenerateChar = true;
                }

                if (bGenerateChar)
                {
                    PwGenerator.PrepareCharSet(pcsCurrent, pwProfile);

                    if (pwProfile.NoRepeatingCharacters)
                    {
                        pcsCurrent.Remove(pcsUsed.ToString());
                    }

                    char chGen = PwGenerator.GenerateCharacter(pwProfile,
                                                               pcsCurrent, crsRandomSource);

                    if (chGen == char.MinValue)
                    {
                        return(PwgError.TooFewCharacters);
                    }

                    vGenerated.AddLast(chGen);
                    pcsUsed.Add(chGen);
                }

                ch = csStream.ReadChar();
            }

            if (vGenerated.Count == 0)
            {
                return(PwgError.Success);
            }

            char[] vArray = new char[vGenerated.Count];
            vGenerated.CopyTo(vArray, 0);

            if (pwProfile.PatternPermutePassword)
            {
                PwGenerator.ShufflePassword(vArray, crsRandomSource);
            }

            byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vArray);
            psOut = new ProtectedString(true, pbUtf8);
            MemUtil.ZeroByteArray(pbUtf8);
            MemUtil.ZeroArray <char>(vArray);
            vGenerated.Clear();

            return(PwgError.Success);
        }
        internal static PwgError Generate(out ProtectedString psOut,
                                          PwProfile pwProfile, CryptoRandomStream crsRandomSource)
        {
            psOut = ProtectedString.Empty;

            string strPattern = pwProfile.Pattern;

            if (string.IsNullOrEmpty(strPattern))
            {
                return(PwgError.Success);
            }

            CharStream        cs          = new CharStream(strPattern);
            LinkedList <char> llGenerated = new LinkedList <char>();
            PwCharSet         pcs         = new PwCharSet();

            while (true)
            {
                char ch = cs.ReadChar();
                if (ch == char.MinValue)
                {
                    break;
                }

                pcs.Clear();

                if (ch == '\\')
                {
                    ch = cs.ReadChar();
                    if (ch == char.MinValue)
                    {
                        return(PwgError.InvalidPattern);
                    }

                    pcs.Add(ch);                     // Allow "{...}" support and char check
                }
                else if (ch == '[')
                {
                    if (!ReadCustomCharSet(cs, pcs))
                    {
                        return(PwgError.InvalidPattern);
                    }
                }
                else
                {
                    if (!pcs.AddCharSet(ch))
                    {
                        return(PwgError.InvalidPattern);
                    }
                }

                int nCount = 1;
                if (cs.PeekChar() == '{')
                {
                    nCount = ReadCount(cs);
                    if (nCount < 0)
                    {
                        return(PwgError.InvalidPattern);
                    }
                }

                for (int i = 0; i < nCount; ++i)
                {
                    if (!PwGenerator.PrepareCharSet(pcs, pwProfile))
                    {
                        return(PwgError.InvalidCharSet);
                    }
                    if (pwProfile.NoRepeatingCharacters)
                    {
                        foreach (char chUsed in llGenerated)
                        {
                            pcs.Remove(chUsed);
                        }
                    }

                    char chGen = PwGenerator.GenerateCharacter(pcs,
                                                               crsRandomSource);
                    if (chGen == char.MinValue)
                    {
                        return(PwgError.TooFewCharacters);
                    }

                    llGenerated.AddLast(chGen);
                }
            }

            if (llGenerated.Count == 0)
            {
                return(PwgError.Success);
            }

            char[] v = new char[llGenerated.Count];
            llGenerated.CopyTo(v, 0);

            if (pwProfile.PatternPermutePassword)
            {
                PwGenerator.Shuffle(v, crsRandomSource);
            }

            byte[] pbUtf8 = StrUtil.Utf8.GetBytes(v);
            psOut = new ProtectedString(true, pbUtf8);
            MemUtil.ZeroByteArray(pbUtf8);

            MemUtil.ZeroArray <char>(v);
            return(PwgError.Success);
        }