NBitcoin 抛出 InvalidOperationException 消息:"Mac HMACSHA256 not recognised."

NBitcoin throws InvalidOperationException with the message: "Mac HMACSHA256 not recognised."

我在尝试签署交易时收到消息:

Transaction payment = new Transaction();
BitcoinSecret PaymentSecret = new BitcoinSecret("1sXCvdpXz...UqkXW9mvT");
...
payment.Sign(Container.PaymentSecret, false);

我深入研究了开源 NBitcoin API 并找出这些行给我的错误消息。我能做什么? (https://github.com/NicolasDorier/NBitcoin/blob/master/NBitcoin/Crypto/DeterministicECDSA.cs)

try
{
    hmac = MacUtilities.GetMac(macName);
}
catch(SecurityUtilityException nsae)
{
    throw new InvalidOperationException(nsae.Message, nsae);
}

HMAC 后面有一个连字符。 HMAC-SHA256

我刚在我的机器上试过代码,它运行得很好。

public void CanSignSimple()
{
    Key bob = new Key();
    Transaction tx = new Transaction();
    tx.Inputs.Add(new TxIn()
    {
        ScriptSig = bob.ScriptPubKey
    });
    tx.Sign(bob, false);
}

需要注意的是,我现在没有使用Bouncy castle库。我在 NBitcoin 内部复制了 bouncycastle 所需的部分。 您的错误似乎是您将 NBitcoin 与官方 BouncyCastle 一起使用,只有当您使用官方 BouncyCastle lib 自己重新编译所有内容,或者您​​使用的是旧版本的 NBitcoin 时,才会发生这种情况。

您使用的是什么版本?

如果有人想弄清楚到底发生了什么,这里有一个代码片段会导致错误:

    string mechanism = "HMACSHA256";
    if (mechanism.StartsWith("HMAC"))
    {
        Console.WriteLine("good");
    }
    else
    {
        Console.WriteLine("bad");
    }
    Console.ReadLine();

如果你设置机制="HMAC-SHA256",那么这个错误就不会发生。 如果你使用mechanism.StartsWith("HMAC",StringComparison.InvariantCulture),那么错误就不会发生。

我还修复了 github 中的错误并创建了对 NBitcoin API 的拉取请求,希望以后不会发生在其他人身上。

问题出在这里:

NBitcoin/NBitcoin.BouncyCastle/security/MacUtilities.cs

public static IMac GetMac(string algorithm)
{
    ...
    if(mechanism.StartsWith("HMAC"))
    {
        ...
    }
    ...
}

机制字符串是 "HMACSHA256" 并且 if 语句永远不会对我求值,因为我的语言是匈牙利语而 "CS" 是匈牙利语中的一个字母。因此根据 StartsWith 函数 "HMACSHA256" 在匈牙利语中不以 "HMAC" 开头。

Nicolas Dorier 在 NBitcoin API 中修复了这个问题,因为在 StartWith 函数中添加了 StringComparison.OrdinalIgnoreCase 设置。

万一有人想测试它,这里有一封来自 Nicolas 的电子邮件:

Ok, for history.

Thread.CurrentThread.CurrentCulture = new CultureInfo("hu"); 
string mechanism = "HMACSHA256"; 
var v1 = mechanism.StartsWith("HMAC");

mechanism = "HMAC-SHA256"; 
var v2 = mechanism.StartsWith("HMAC");

In hungarian, v1 is false and v2 true.