【问题标题】:PowerShell get file MD5 as base64 stringPowerShell 获取文件 MD5 作为 base64 字符串
【发布时间】:2020-09-22 19:47:52
【问题描述】:

我有以下 .NET 代码生成文件 MD5 的 base64 字符串:

using (FileStream fileStream = new FileStream(fileName, FileMode.Open))
{
    using (MD5 md5 = MD5.Create())
    {
        using (CryptoStream cryptoStream = new CryptoStream((Stream) fileStream, (ICryptoTransform) md5, CryptoStreamMode.Read))
        {
            byte[] buffer = new byte[4096];
            do
              ;
            while (cryptoStream.Read(buffer, 0, buffer.Length) > 0);
            return Convert.ToBase64String(md5.Hash);
        }
    }
}

它是工作代码的一部分。

现在我需要创建一个 PowerShell 脚本来执行一些自动化操作,并且还需要创建文件的相同 base64 哈希。我写了以下内容:

$uploadFilePath = "C:\temp\test.txt"
$fileHashMD5 = Get-FileHash $uploadFilePath -Algorithm MD5
$bytes = [System.Text.Encoding]::ASCII.GetBytes($fileHashMD5.Hash)
$fileHashBase64 =[Convert]::ToBase64String($bytes)

但这会返回与上面生成的结果不同的结果。

我在 PS 脚本中做错了什么?

【问题讨论】:

  • 您正在使用 7 位 US-ASCII 将十六进制字符串转换为与该十六进制字符串完全不匹配的字节
  • 顺便说一句,.NET 代码也很古怪。您可以将ComputeHash(Stream) 与流一起使用,无需循环读取数据。你可以写var bytes=md5.ComputeHash(fileStream);
  • @PanagiotisKanavos 尝试过 - 仍然给出不同的结果
  • 试过什么?你尝试了什么,你得到了什么?问题中的代码肯定是错误的。 Get-FileHash 没有损坏。 still gives different result 表示十六进制字符串不同。他们是吗?如果不是,则是将一种字符串格式转换为另一种需要修复的代码
  • 为什么不按原样使用十六进制字符串? Git 哈希是十六进制字符串,而不是 Base64

标签: .net powershell


【解决方案1】:

MD5字符串的大小写有区别吗?举个例子:

> [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("string to encode".ToLower()))
> c3RyaW5nIHRvIGVuY29kZQ==
> [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("string to encode".ToUpper()))
> U1RSSU5HIFRPIEVOQ09ERQ==

相同的字符串但不同的base64输出。

【讨论】:

  • 这与问题代码显示的错误相同 - 哈希是一个十六进制字符串。您无法使用编码获取十六进制字符串的值
【解决方案2】:

最终编写了以下模仿 .NET 函数的函数:

function Calc-File-Hash($filename) {
    Using-Object($fileStream = new-object System.IO.FileStream("C:\temp\test.txt", [System.IO.FileMode]::Open)) {
        Using-Object($md5 = [System.Security.Cryptography.MD5]::Create()) {
            $cryptoStream = new-object System.Security.Cryptography.CryptoStream($fileStream, $md5, [System.Security.Cryptography.CryptoStreamMode]::Read)
            $buffer = [System.Byte[]]::new(4096)
            do {
    
            }
            while ($cryptoStream.Read($buffer, 0, $buffer.Length) -gt 0)
            return [Convert]::ToBase64String($md5.Hash)
        }
    }
}

Using-Object 函数取自以下帖子: How to implement using statement in powershell?

【讨论】:

  • 你已经有了 Get-FileHash $uploadFilePath -Algorithm MD5 的哈希值。问题在于代码的其余部分 - 哈希是字节的十六进制表示。获取该字符串的 7 位 US-ASCII 表示返回完全不同的字节
猜你喜欢
  • 2017-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
  • 1970-01-01
  • 2019-02-26
  • 2015-06-05
相关资源
最近更新 更多