【问题标题】:decrypt hash using sha256managed使用 sha256managed 解密哈希
【发布时间】:2015-07-27 17:37:57
【问题描述】:

嗯,一周前我开始使用c#,有点迷茫。

我从密码学开始,基本上是哈希和盐。

这个周末我的老师给了我们一些“家庭作业”,我和我所有的伙伴都很困惑。

我有这个简单的代码:

练习包括“解密”一个散列密码(使用 SHA256managed 散列),我们知道它是一个 4 个字符的数字。

我尝试用循环来做,并一个一个地解密所有字符,但我卡住了,我不知道如何继续。

如果您能帮我解决这个问题,我将不胜感激。

谢谢!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;

namespace Examen
{
    class Program
    {
        static void Main(string[] args)
        {

            string hashed_password = "YOSGtSkJ41KX7K80FEmg+vme4ioLsp3qr28XU8nDQ9c=";



            Console.ReadLine();
        }


    }
}

【问题讨论】:

  • 我有点困惑,你是说散列密码也包含盐吗?您是否还说密码是 4 个数字,例如 0000 到 9999?你知道盐是什么吗,它也是4个数字吗?
  • 原始密码可以是 0000 到 9999 之间的一个值,并且哈希密码不包含盐。对不起我的英语,我是一个不会说英语的人。我必须在 0000 和 9999 之间找到这个值(非散列密码)
  • 示例是给出的实际值吗?我通过一个相当不错的破解程序 (crackstation.net) 运行它,但没有找到结果。
  • 搜索词 - Rainbow tables

标签: c# encryption hash


【解决方案1】:

哈希是一种单向函数。给定密码“1805”,您将得到哈希值“2DOrd5wHHjYbtrSvQ+SyTH6HUDID5z+XV/cV8aYOSzs=”。

您不能倒退:给定哈希值“2DOrd5wHHjYbtrSvQ+SyTH6HUDID5z+XV/cV8aYOSzs=”,您无法计算密码“1805”。

但是,您可以尝试所有可能的密码,并查看每个密码的哈希值。然后,你有一个所有可能的哈希列表,所有可能的密码从“0000”到“9999”。在这种情况下,该哈希列表中的某处是您感兴趣的:'YOSGtSkJ41KX7K80FEmg+vme4ioLsp3qr28XU8nDQ9c='。

您的程序应该会花费不到一秒钟的时间来发现密码。

请注意,您的程序必须以与密码相同的格式对数据进行哈希处理,即 8 个字节的数据,采用 UTF-16LE 编码。确保散列的数据格式与散列密码的数据格式相同,否则永远找不到匹配项。

【讨论】:

    【解决方案2】:

    您需要做的是计算 0000-9999 之间所有值的哈希值,直到找到匹配的哈希值。

    下面是一个为您计算哈希的方法示例,给定一个字符串:Obtain SHA-256 string of a string

    编辑:这是一个简单的例子。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Security.Cryptography;
    
    namespace TestConsoleProject
    {
    
    class Program
    {
            static void Main(string[] args)
            {
                string hashed_password = "YOSGtSkJ41KX7K80FEmg+vme4ioLsp3qr28XU8nDQ9c=";
                int index;
    
                for(index = 0; index <= 9999; index++)
                {
                    if (hashed_password.Equals(sha256_hash(index.ToString("0000"))))
                        break;                            
                }
    
                Console.WriteLine("Password is: " + index.ToString("0000"));
    
                Console.ReadLine();
            }
    
            public static String sha256_hash(String value)
            {
                using (SHA256 hash = SHA256Managed.Create())
                {
                    return Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(value.ToCharArray())));
                }
            }
        }
    }
    

    【讨论】:

    • 没错,用蛮力攻击,但我不知道该怎么做
    • 我知道如何散列密码,但我不知道如何使用暴力攻击获取原始字符串的值
    • 您的代码永远不会等于或找到该字符串。 hashed_password 是 base-64 编码,而不是十六进制。
    • 可能,但SelectString.Join 是不必要的。只需返回 Convert.ToBase64String(hash.ComputeHash(...)) 的值。
    • 另外,您可以使用.ToString("0000"),而不是使用“pad left”,这样可以减少创建额外字符串的需要。
    【解决方案3】:

    我可能是错的,但我很确定它不可能解密散列字符串。这就是为什么使用 sha256 或 sha512 将密码存储在数据库中的原因。

    【讨论】:

    • 其实是有办法的,因为老师在课堂上给我们展示了结果。
    • 不可能解密它们,但你可以做字典或暴力攻击,通过SHA256运行guess并比较两者结果。如果它们匹配,则您基本上解密了它。
    • 是的,我的意思是蛮力攻击。
    • 是的,我同意,一个从 0000 到 9999 的简单循环,对循环的当前位置进行散列,然后比较结果即可解决。
    • 我该怎么做?几天前我才开始使用 c#,这对我来说有点困难
    【解决方案4】:

    我的方法是暴力破解,因为你说你已经知道这是一个 4 位数字。

    你可以这样做:

      static void Main(string[] args)
        {
            string hashed = "YOSGtSkJ41KX7K80FEmg+vme4ioLsp3qr28XU8nDQ9c=";
    
            for (int i = 1000; i <=9999; i++)
            {
                string digit = i.ToString().PadLeft(4, '0');
                string s = ComputeSHA256(digit);
                if (s == hashed)
                {
                    Console.WriteLine(digit + "is my decrypted hash");
                    break;
                }
            }
            Console.ReadKey();
        }
    
        static string ComputeSHA256(string plainText)
        {
             SHA256Managed sha256Managed = new SHA256Managed();
            Encoding u16LE = Encoding.Unicode;
            string hash = String.Empty;
            byte[] hashed = sha256Managed.ComputeHash(u16LE.GetBytes(plainText), 0, u16LE.GetByteCount(plainText));
            return Convert.ToBase64String(hashed);
        }
    

    【讨论】:

    • 您的代码永远不会等于或找到字符串。 hashed_pa​​ssword 是 base-64 编码的,而不是十六进制的。另外,他不使用盐,因此必须将其除去。您还错过了 999 个可能的密码(0000 到 0999)。
    • 我错过了他关于不使用盐的 cmets。我是从 1000 开始做的,因为他明确说这是一个 4 个字符的数字,但是是的,前面可能又是 0 ......你对 base64 部分也是正确的......我也更正了在查看下面 Jim 的注释后编码部分......现在给出了答案......它是 8765
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 2021-11-14
    • 2013-07-12
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多