C# SSH传输的Mono.Security Diffie Helman密钥生成异常/挂起

C# SSH传输的Mono.Security Diffie Helman密钥生成异常/挂起,c#,git,ngit,C#,Git,Ngit,我正在尝试在NGit上通过SSH进行推送。我使用此处列出的方法指定自己的密钥: 它在第一次推送时与克隆人配合良好。在这之后,它有30%的时间失败,始终使用Mono中的此方法。安全性: Mono.Security.dll!Mono.Math.BigInteger.Kernel.MinusEq(Mono.Math.BigInteger big, Mono.Math.BigInteger small) 要么失败并显示消息:“加密函数期间出错”,要么无限期挂起此函数。同样,它是否成功似乎完全是随机的。

我正在尝试在NGit上通过SSH进行推送。我使用此处列出的方法指定自己的密钥:

它在第一次推送时与克隆人配合良好。在这之后,它有30%的时间失败,始终使用Mono中的此方法。安全性:

Mono.Security.dll!Mono.Math.BigInteger.Kernel.MinusEq(Mono.Math.BigInteger big, Mono.Math.BigInteger small)
要么失败并显示消息:“加密函数期间出错”,要么无限期挂起此函数。同样,它是否成功似乎完全是随机的。NGit中的函数正在调用它:

DiffieHellmanManaged dh = new DiffieHellmanManaged (pspec.P.GetBytes (), pspec.G.GetBytes (), 0);
发电机对内(KeyPairGenerator.cs)

有什么想法吗?如果没有,有没有其他方法生成Diffie-Helman密钥

非常感谢

干杯

更新:我发现了一个我并不完全理解的奇怪的解决方案:

以前,我创建了一个新线程,因为我从UI调用它,不希望它挂起。这是一个STA线程,因为我们正在构建一个VSTO应用程序,它不支持UI组件中的MTA/BackgroundWorker()等(您可以根据需要指定它为STA,这在很大程度上限制了旧线程()。我发现在推送过程中,当用户四处点击时,问题发生得更频繁(因此进行了一些git签出),因此我禁用了线程,并直接从UI运行它。从那时起,它像地狱一样冻结用户界面,但不会在计算BigInt时挂起pr崩溃。我对这种情况完全感到困惑,除非:Office(我们正在为其构建插件)不知何故无法为BigInt计算提供足够内存的线程(或者管理不当,这并不完全令人惊讶),或者,出于某种原因,BigInt计算无法在线程上下文中调用(可能是线程->Ngit->锐化->单声道安全->单声道数学(32位数字)中断线程??)


知道这是什么原因吗?

我在使用NGit+SSH私钥从Git存储库获取/拉取时遇到了完全相同的问题,可以从多个线程请求

我追踪到它在多线程环境中运行时的问题(可以找到错误报告和复制它的代码)。尽管出于任何原因,我只能在Windows环境中复制该问题。在OSX中的Mono上,它似乎工作正常

为了解决这个问题,我将NSch改为使用DiffieHellmanManaged的改进实现,该实现使用与相同的逻辑计算大整数本身的ModPow

public static biginger ModPower(此biginger值、biginger exp、biginger n)
{
如果(exp<0)
抛出新ArgumentOutOfRangeException(“指数”,“幂必须大于等于0”);
如果(n==0)
抛出新的DivideByZeroException();
BigInteger结果=新的BigInteger(1)%n;
while(exp!=0)
{
如果(exp%2!=0)
{
结果=结果*值;
结果=结果%n;
}
如果(exp==1)
打破
值=值*值;
值=值%n;
exp>>=1;
}
返回结果;
}
public static BigInteger ModPower(this BigInteger value, BigInteger exp, BigInteger n)
    {
        if (exp < 0)
            throw new ArgumentOutOfRangeException("exponent", "power must be >= 0");
        if (n == 0)
            throw new DivideByZeroException();

        BigInteger result = new BigInteger(1) % n;
        while (exp != 0)
        {
            if (exp % 2 != 0)
            {
                result = result * value;
                result = result % n;
            }
            if (exp == 1)
                break;
            value = value * value;
            value = value % n;
            exp >>= 1;
        }
        return result;
    }