并行暴力算法

发布于 2024-10-08 15:13:08 字数 3834 浏览 0 评论 0原文

所以我正在查看 http://codahale.com/how-to- safe-store-a-password/# 并开始好奇在一台功能强大的台式计算机上暴力破解不同散列的速度有多快,并试图对其进行测试,

但我见过的大多数算法都是单线程的,并且它让我震惊的是,使用 c# 4.0 Parallel.net/Plinq 扩展和并发结构(如 ConcurrentBag 和 IProducerConsumer)将是一个非常有趣的挑战。

所以我的任务如下,使用并行化构建 n 长度和字符集 [x] 的密码的最有效/性能的暴力检查器,即生成给定字符集和长度的所有可能的字符串,直到找到匹配。假设至少有两个核心和合理数量的内存,

我要自己尝试一下,让最好的男人/女人获胜:)

编辑

第一次尝试,没有比较性能和有限的范围和已知的密码length

    char[] chars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };

    public long NrCombinations(int nrChars, int stringLength)
    {
        Func<long, int, long> power = null;
        power = (i, p) => p == 1 ? i : i * power(i, p - 1);

        return power(nrChars, stringLength);
    }


    public static bool StringArrayEquals(char[] a, char[] b)
    {
        if (a.Length != b.Length)
            return false;
        for (int i = 0; i < a.Length; i++)
        {
            if (!a[i].Equals(b[i]))
                return false;
        }
        return true;
    }

    public char[]  GenerateString(int i, int stringLength)
    {
        char[] current = new char[stringLength];
        for (int i = 0; i < stringLength; i++)
        {
            double remainder = i % this.chars.Length;   
            i = i / this.chars.Length;         
            current[i] = this.chars[(int) remainder];
        }
        return current;
    }

    public bool IsMatch(int i, char[] password)
    {
        return StringArrayEquals(GenerateString(i, password.Length), password);
    }

    private int GetMatching(string passwordString)
    {
        char[] password = passwordString.ToArray();
        int nrCombinations = (int)NrCombinations(this.chars.Length, password.Length);

        return ParallelEnumerable.Range(0, nrCombinations).WithDegreeOfParallelism(10).FirstOrDefault(i => IsMatch(i, password));

    }

下一次尝试

使用 ParallelEnumerable 并不聪明,因为它的大小仅限于 int,您很快就需要至少 long,尽管我怀疑这会让您在使用大型密码字符集时保持很长时间。我猜你要么必须使用 BigInt,要么在那之后开始以某种方式分解它。

    public long NrCombinations(int nrChars, int stringLength)
    {
        Func<long, int, long> power = null;
        power = (i, p) => p == 1 ? i : i * power(i, p - 1);

        return power(nrChars, stringLength);
    }


    public string GenerateString(long number, int sentenceLength)
    {
        char[] current = new char[sentenceLength];
        for (int i = 0; i < sentenceLength; i++)
        {
            double remainder = number % this.chars.Length;   
            number = number / this.chars.Length;         
            current[i] = this.chars[(int) remainder];
        }
        return new string(current);
    }

    public bool IsMatch(string hash, long  i, int passwordLength)
    {
        string generated = GenerateString(i, passwordLength);
        string hashed = GetMasterHash(generated, this.site);
        return string.Equals(hashed, hash);
    }

    private string GetMatching(string hash,int passwordLength)
    {
        string result = string.Empty;
        int stringlength = passwordLength;
        long  nrCombinations = NrCombinations(this.chars.Length, stringlength);
        long x = 0;

        Parallel.For(0, nrCombinations, (i, loopState) =>
        {
            if (IsMatch(hash,i, passwordLength))
            {
                x = i;
                loopState.Stop();
                return;
            }
        }); 


        if (x > 0)
        {
            result = this.GenerateString(x, passwordLength);
        }

        return result;

    }

So I was looking at http://codahale.com/how-to-safely-store-a-password/# and became curious how fast different hash could be bruteforced on a somewhat powerful desktop computer and was tempted to test it

Most of the algorithms I've seen though are single-threaded and it struck me that this would be a really interesting challenge in using c# 4.0 Parallel.net/Plinq extensions and concurrent structures (like ConcurrentBag and IProducerConsumer).

So my task is as follows, build the most efficient/performant bruteforce checker of a password of n-length and charset[x] using parallelization, ie generate all possible strings of a given charset and length until a match is found. Assume at least two cores and reasonable amount of ram

I'm going to give it a whirl myself, let the best man/woman win :)

EDIT

First attempt without comparing performance yet and limited scope and known password length

    char[] chars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };

    public long NrCombinations(int nrChars, int stringLength)
    {
        Func<long, int, long> power = null;
        power = (i, p) => p == 1 ? i : i * power(i, p - 1);

        return power(nrChars, stringLength);
    }


    public static bool StringArrayEquals(char[] a, char[] b)
    {
        if (a.Length != b.Length)
            return false;
        for (int i = 0; i < a.Length; i++)
        {
            if (!a[i].Equals(b[i]))
                return false;
        }
        return true;
    }

    public char[]  GenerateString(int i, int stringLength)
    {
        char[] current = new char[stringLength];
        for (int i = 0; i < stringLength; i++)
        {
            double remainder = i % this.chars.Length;   
            i = i / this.chars.Length;         
            current[i] = this.chars[(int) remainder];
        }
        return current;
    }

    public bool IsMatch(int i, char[] password)
    {
        return StringArrayEquals(GenerateString(i, password.Length), password);
    }

    private int GetMatching(string passwordString)
    {
        char[] password = passwordString.ToArray();
        int nrCombinations = (int)NrCombinations(this.chars.Length, password.Length);

        return ParallelEnumerable.Range(0, nrCombinations).WithDegreeOfParallelism(10).FirstOrDefault(i => IsMatch(i, password));

    }

Next Attempt

Using ParallelEnumerable wasnt to clever since it's restricted to int in size, you pretty soon need atleast long even though I doubt that will hold you for long with large passwords charsets. Guess you either have to go BigInt or start breaking it down somehow after that.

    public long NrCombinations(int nrChars, int stringLength)
    {
        Func<long, int, long> power = null;
        power = (i, p) => p == 1 ? i : i * power(i, p - 1);

        return power(nrChars, stringLength);
    }


    public string GenerateString(long number, int sentenceLength)
    {
        char[] current = new char[sentenceLength];
        for (int i = 0; i < sentenceLength; i++)
        {
            double remainder = number % this.chars.Length;   
            number = number / this.chars.Length;         
            current[i] = this.chars[(int) remainder];
        }
        return new string(current);
    }

    public bool IsMatch(string hash, long  i, int passwordLength)
    {
        string generated = GenerateString(i, passwordLength);
        string hashed = GetMasterHash(generated, this.site);
        return string.Equals(hashed, hash);
    }

    private string GetMatching(string hash,int passwordLength)
    {
        string result = string.Empty;
        int stringlength = passwordLength;
        long  nrCombinations = NrCombinations(this.chars.Length, stringlength);
        long x = 0;

        Parallel.For(0, nrCombinations, (i, loopState) =>
        {
            if (IsMatch(hash,i, passwordLength))
            {
                x = i;
                loopState.Stop();
                return;
            }
        }); 


        if (x > 0)
        {
            result = this.GenerateString(x, passwordLength);
        }

        return result;

    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你与昨日 2024-10-15 15:13:08

为什么使用 NrCombinations 方法,而不仅仅是

long combinations = (long)Math.Pow(base, stringLength);

我还建议不要使用 int 来使用 nrCombinations,因为只有 6 个字符与您的基本 36 字母表一起使用麻烦(36^6>2^31)。使用。我认为不需要 BigInteger ,因为如果你需要大数字,那么暴力破解无论如何都不是一个选择。

我有这样的想法:通过使用一种 De Bruijn 序列流来加速暴力破解是可能的。看起来很合理,但我必须重新考虑这一点,因为我现在没有代码可以显示。

Why the NrCombinations method and not just

long combinations = (long)Math.Pow(base, stringLength);

I would also recommend against int for nrCombinations because with only six characters with your base 36 alphabet you will get in trouble (36^6 > 2^31). Use long. I don't think BigInteger is needed because if you need that big numbers brute force will not be an option anyway.

I have this idea that it might be possible to speed up brute force by using a kind of De Bruijn sequence stream. Seems reasonable but I have to get back on that because I have no code to show right now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文