在可移植类库中生成SHA1哈希

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

此类的一部分需要生成SHA1哈希以生成oauth_signature。

我知道可移植类库不支持System.Security.Cryptography,所以无论如何这个类可以生成没有该类的SHA1哈希?

Mono为它自己的mscorlib.dll提供了SHA1的托管实现 (但它不像@CodeInChaos建议的那样位于Mono.Security.dll中)。

它是开源的,经过严格测试,意味着与Microsoft实现完全相同(例如,它派生自SHA1HashAlgorith …实现ICryptoTransform ……)因此它应该是一个简单的替代品。

我认为最简单的方法是使用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(); } 

好吧我最近也需要这个,我发现从HashLib获取SHA1实现要容易得多: http ://hashlib.codeplex.com/

Mono实现有一些远程依赖(exception的本地化等),而从HashLib只需要复制几个文件而不需要对它们进行任何更改:

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

总共55 KB的代码,所以没什么太重的。

我使用过这个BouncyCastle Nuget软件包: https ://www.nuget.org/packages/BouncyCastle-PCL/它对我来说很好用(跨平台Windowsapp store,.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); } 

SHA-1维基百科文章包含伪代码,您可以将其用作自己实现的指南。 但是,与加密函数一样,我强烈建议使用经过试验和测试的实现。

假设你想要一个SHA-256实现,你可以在BouncyCastle中找到一个,它以源代码forms提供。 那里的相关课叫做Org.BouncyCastle.Crypto.Digests.Sha256Digest(这里是它的来源 )。

您可能想要查看新的.NET标准库:

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

它是可移植的,包含System.Security.Cryptography

  ///  /// Compute hash for string encoded as UTF8 ///  /// String to be hashed. /// 40-character hex string. 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/

我也希望签署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]); } } 

当我必须达到同样的结果时,这对我有用。 您也可以使用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/

以下是使用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()); }