16

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

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

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

4

9 回答 9

16

我认为最简单的方法是使用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();
}
于 2014-11-23T10:28:35.740 回答
8

好吧,我最近也需要这个,我发现从 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 的代码,所以没什么大不了的。

于 2014-03-14T14:45:29.097 回答
7

我使用了这个 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);
}
于 2015-01-09T13:43:28.087 回答
6

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

它是开源的,经过很好的测试,并且表现得与 Microsoft 实现完全一样(例如,它派生自SHA1, HashAlgorith... implements ICryptoTransform...),因此它应该是一个简单的替代品。

于 2012-04-20T23:10:24.337 回答
2

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

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

于 2012-04-20T23:01:06.423 回答
2

您可能想查看新的.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/

于 2017-04-19T08:33:21.213 回答
1

这是一个使用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());
    }
于 2018-03-02T13:50:21.307 回答
0

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

于 2017-08-14T18:00:23.397 回答
0

我也想签署 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]);
        }
    }
于 2017-01-11T06:10:49.320 回答