我正在尝试构建一个可移植的类库,该类库生成 OAuth url 供其他类/应用程序使用。这个使用 OAuth 的类库必须是一个可移植的类库,以便它可以与我正在构建的不同版本的 DropBox API 一起使用。
这个类的一部分需要生成一个 SHA1 哈希来生成 oauth_signature。
我知道可移植类库不支持 System.Security.Cryptography,所以无论如何这个类可以在没有该类的情况下生成 SHA1 哈希?
我正在尝试构建一个可移植的类库,该类库生成 OAuth url 供其他类/应用程序使用。这个使用 OAuth 的类库必须是一个可移植的类库,以便它可以与我正在构建的不同版本的 DropBox API 一起使用。
这个类的一部分需要生成一个 SHA1 哈希来生成 oauth_signature。
我知道可移植类库不支持 System.Security.Cryptography,所以无论如何这个类可以在没有该类的情况下生成 SHA1 哈希?
我认为最简单的方法是使用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 实现具有一些深远的依赖关系(异常的本地化等),而从 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/ 它对我来说很好用(跨平台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);
}
Mono为它自己提供了一个SHA1 的托管实现(但它不像@CodeInChaos 建议mscorlib.dll
的那样位于)。Mono.Security.dll
它是开源的,经过很好的测试,并且表现得与 Microsoft 实现完全一样(例如,它派生自SHA1
, HashAlgorith
... implements ICryptoTransform
...),因此它应该是一个简单的替代品。
SHA-1 Wikipedia 文章包含伪代码,您可以将其用作您自己实现的指南。但是,与加密函数一样,我强烈建议使用久经考验的实现。
假设您想要一个 SHA-256 实现,您可以在BouncyCastle中找到一个,它以源代码形式提供。那里的相关类称为 Org.BouncyCastle.Crypto.Digests.Sha256Digest(这是它的来源)。
您可能想查看新的.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 项目):
这是一个使用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());
}
当我必须达到相同的结果时,这对我有用。你也可以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/
我也想签署 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]);
}
}