【问题标题】:Generate SHA1 Hash in Portable Class Library在可移植类库中生成 SHA1 哈希
【发布时间】:2012-05-02 12:28:10
【问题描述】:

我正在尝试构建一个可移植的类库,它可以生成 OAuth url 供其他类/应用程序使用。这个使用 OAuth 的类库必须是可移植的类库,以便它可以与我正在构建的不同版本的 DropBox API 一起使用。

这个类的一部分需要生成一个 SHA1 哈希来生成 oauth_signature。

我知道可移植类库不支持 System.Security.Cryptography,那么这个类是否可以在没有该类的情况下生成 SHA1 哈希?

【问题讨论】:

  • 你可以从 Mono.Security 复制一些代码。
  • 我在 SHA1Managed 类中看不到任何麻烦的依赖项。每当我看的时候,便携式给我的印象就是未完成。
  • 这将是一个问题,但它是一个非常简单的字符串构建类,有几个方法,所以只要他们完成未完成的工作就不是问题。

标签: c# sha1 portable-class-library


【解决方案1】:

我认为最简单的方法是使用 PCLCrypto nuget 包。然后你可以这样做:

private static string CalculateSha1Hash(string input)
{
        // step 1, calculate MD5 hash from input
        var hasher = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha1);
        byte[] inputBytes = Encoding.UTF8.GetBytes(input);
        byte[] hash = hasher.HashData(inputBytes);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
}

【讨论】:

  • 我同意 - 但您可能希望更改示例以显示正在使用的密钥:byte[] keyMaterial;字节[] 数据;变种算法 = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha1); CryptographicHash hasher = algorithm.CreateHash(keyMaterial); hasher.Append(数据);字节[] mac = hasher.GetValueAndReset(); string macBase64 = Convert.ToBase64String(mac);
  • 很好的例子!我有一个小补充。在一行中创建十六进制字符串 5:return string.Join("", hash.Select(b => b.ToString("x2")).ToArray());
【解决方案2】:

我最近也需要这个,我发现从 HashLib 实现 SHA1 更容易:http://hashlib.codeplex.com/

Mono 实现具有一些深远的依赖关系(异常的本地化等),而从 HashLib 中您只需要复制少量文件而不需要对其进行任何更改:

Converters.cs
Hash.cs
HashBuffer.cs
HashCryptoNotBuildIn.cs
HashResult.cs
IHash.cs
SHA0.cs
SHA1.cs

总共 55 KB 的代码,所以不会太重。

【讨论】:

  • 为我工作。不过,我确实必须在您的列表中添加一些其他文件。 IHashInfo.cs(不是所有东西都需要)。在上述引用的类之一中使用的 .SubArray() 扩展方法也需要 ArrayExtentions.cs。我缩小了 HashFactory 类以匹配移植的类——但它确实完成了工作。感谢您的提示。起初,我看着所有的课程,头晕目眩。你的清单真的很有帮助。
  • 这个很好用,谢谢!就像 rouen 提到的那样,您的列表中缺少 IHashInfo.cs。由于我只需要一个字符串到 SHA1 的转换,我能够将代码大小缩小到 ~ 26 KB。
【解决方案3】:

我使用了这个 BouncyCastle Nuget 包:https://www.nuget.org/packages/BouncyCastle-PCL/,它对我来说很好用(跨平台 Windows Store App、.Net Framework 4.5、Silverlight 5、Windows Phone 8、Xamarin.Android、Xamarin.iOS )

使用 HMACSHA1 生成这样的签名:

public string GenerateSignature(string key, string signatureBase)
{
   var keyBytes = Encoding.UTF8.GetBytes(key);
   HMACSHA1 hashAlgorithm = new HMACSHA1(keyBytes);            
   byte[] dataBuffer = Encoding.UTF8.GetBytes(signatureBase);
   byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
   return Convert.ToBase64String(hashBytes);
}

【讨论】:

    【解决方案4】:

    Mono 为其自己的mscorlib.dll 提供了一个managed implementation of SHA1(但它不像@CodeInChaos 建议的那样位于Mono.Security.dll 中)。

    它是开源的,经过很好的测试,其行为与 Microsoft 实现完全相同(例如,它源自 SHA1HashAlgorith... 实现 ICryptoTransform...)所以它应该是一个简单的插件替换。

    【讨论】:

    • 你能帮我用它来简单地散列一个字符串吗?代码几乎没有评论,所以我觉得很难理解。
    • 您需要将字符串转换为字节,例如System.Text.XXXEncoding.GetBytes()。小心编码(例如 UTF8 比 ASCII 好得多),因为不同的字节会产生不同的哈希值。
    • 我不知道如何使用它。有人可以帮我从某个字符串生成 SHA1 哈希吗?
    【解决方案5】:

    SHA-1 Wikipedia article 包含伪代码,您可以将其用作自己实现的指南。但是,与加密函数一样,我强烈建议使用久经考验的实现。

    假设您想要一个 SHA-256 实现,您可以在BouncyCastle 中找到一个,它以源代码形式提供。那里的相关类称为 Org.BouncyCastle.Crypto.Digests.Sha256Digest(这是它的source)。

    【讨论】:

      【解决方案6】:

      您可能想查看新的 .NET Standard 库:

      https://docs.microsoft.com/en-us/dotnet/articles/standard/library

      它是便携的,包括System.Security.Cryptography

          /// <summary>
          /// Compute hash for string encoded as UTF8
          /// </summary>
          /// <param name="input">String to be hashed.</param>
          /// <returns>40-character hex string.</returns>
          public static string GetSha1(string input)
          {
              using (var sha1 = System.Security.Cryptography.SHA1.Create())
              {
                  byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                  byte[] hash = sha1.ComputeHash(inputBytes);
      
                  StringBuilder sb = new StringBuilder();
                  for (int i = 0; i < hash.Length; i++)
                  {
                      sb.Append(hash[i].ToString("X2"));
                  }
                  return sb.ToString();
              }
          }
      

      您还可以在此处获得一些帮助(使用 .NET 标准库创建 PCL 项目):

      https://xamarinhelp.com/dot-net-standard-pcl-xamarin-forms/

      【讨论】:

        【解决方案7】:

        这里是一个使用BouncyCastle的例子

            public static string ComputeSha1(string data)
            {
                var sha1Digest = new Org.BouncyCastle.Crypto.Digests.Sha1Digest();
                var hash = new byte[sha1Digest.GetDigestSize()];
        
                var dataBytes = Encoding.UTF8.GetBytes(data);
                foreach (var b in dataBytes)
                {
                    sha1Digest.Update(b);
                }
                sha1Digest.DoFinal(hash, 0);
        
                return string.Join("", hash.Select(b => b.ToString("x2")).ToArray());
            }
        

        【讨论】:

          【解决方案8】:

          我也想签署 OAuth,并且正在研究 PCL Crypto - 该测试显示了 HmacSha1 哈希的创建,并将结果与​​标准 .NET Framework 方式进行比较。

              [Test]
              public void CreateHash_VersusComputeHash_ReturnsEquivalent()
              {
                  // USING TRADITIONAL .NET:
                  var key = new byte[32];
                  var contentBytes = Encoding.UTF8.GetBytes("some kind of content to hash");
                  new RNGCryptoServiceProvider().GetBytes(key);
          
                  var alg = new HMACSHA1(key); // Bouncy castle usage does not differ from this
                  var result = alg.ComputeHash(contentBytes);
          
          
          
          
                  // USING PCL CRYPTO:
                  var algorithm = WinRTCrypto.MacAlgorithmProvider.OpenAlgorithm(MacAlgorithm.HmacSha1);
          
                  byte[] mac;
                  using (var hasher = algorithm.CreateHash(key))
                  {
                      hasher.Append(contentBytes);
                      mac = hasher.GetValueAndReset();
                  }
          
          
          
          
                  // Assert results:
                  Assert.AreEqual(result.Length, mac.Length);
          
                  for (var i = 0; i < result.Length; i++)
                  {
                      Assert.AreEqual(result[i], mac[i]);
                  }
              }
          

          【讨论】:

            【解决方案9】:

            当我必须达到相同的结果时,这对我有用。您也可以使用 SHA512 和其他人来做到这一点。

            using System.Security.Cryptography;
            
            public static string HashSHA1(this string value)
            {
                using (var sha = SHA1.Create())
                {
                   return Convert.ToBase64String(sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(value)));
                }
            }
            

            代码引用自:https://xamarinhelp.com/cryptography-in-xamarin-forms/

            【讨论】:

              猜你喜欢
              • 2015-04-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-02-26
              • 2014-03-20
              • 1970-01-01
              • 2016-10-27
              • 2021-11-19
              相关资源
              最近更新 更多