我有以下使用BouncyCastle(dotnet版本)的代码从消息中获取HMAC-SHA1。

我有这个小图书馆课:

public class HashingTools
{
    static string hmacKey = "81310910a060c5705c1d3cedf370bcf9";
    public static int HashSizeInBytes = 20;
    static KeyParameter keyParameter = null;
    private static HMac hmacInstance;

    static HashingTools()
    {
        hmacInstance = new HMac(new Sha1Digest());
        hmacInstance.Init(newKeyParameter(Encoding.UTF8.GetBytes(hmacKey)));
    }

    public static byte[] HashSha1(byte[] message)
    {
        byte[] result = new byte[hmacInstance.GetMacSize()];

        hmacInstance.BlockUpdate(message, 0, message.Length);
        hmacInstance.DoFinal(result, 0);

        return result;
    }
}


而且我有很多消息都通过这种方法使用相同的密钥:hmacKey,并且我想尽可能地加快它的使用速度,并尽可能多地重用,同时仍然要考虑安全性参数。 (随机,新鲜...)。

如果我尝试重用或并行化hmac实例,则会在Org.BouncyCastle.Crypto.Macs.Hmac.BlockUpdate内收到“数组超出范围”异常。

我已经创建了用于复制的单元测试(1或2个并行散列函数可以正常运行,而100个则可以出错):

[Test]
public void TestBulkHashing()
{
    var messages = new List<byte[]>();

    foreach (var index in Enumerable.Range(0, 100))
    {
        var buffer = new byte[4096];
        Random r = new Random();
        r.NextBytes(buffer);

        messages.Add(buffer);
    }

    Parallel.ForEach(messages, m =>
    {
        HashingTools.HashSha1(m);
    });
}

最佳答案

正如@dlatikay正确推测的那样,这是一个同步错误。 Bouncycastle的类不是线程安全的,除非它们明确声明是安全的。

如果修改HashSha1方法以显式同步线程,则不会出现异常:

public static byte[] HashSha1(byte[] message) {
    byte[] result = new byte[hmacInstance.GetMacSize()];
    lock(hmacInstance) {
        hmacInstance.BlockUpdate(message, 0, message.Length);
        hmacInstance.DoFinal(result, 0);
    }

    return result;
}


对于您有关优化的问题,Bouncycastle已经预先计算了涉及密钥的计算部分。调用DoFinal(...)时,内部状态将重置为该预先计算的值,因此,如果您使用相同的键,则无需为下一个HMac再次调用Init()。您的代码已经利用了这种优化,因此,除非您想编写自己的哈希代码,否则我认为您无法做更多的事情。

关于c# - 弹力城堡HMAC SHA1,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57506514/

10-12 03:23