Исключение / зависание на Mono.Security Генерация ключа Диффи-Хелмана для SSH Transport
Я пытаюсь сделать толчки через SSH на NGit. Я указываю свои собственные ключи, используя метод, изложенный здесь: NGit устанавливает соединение с файлом закрытого ключа.
Хорошо работает с клоном и при первом нажатии. После этого происходит сбой 30% времени, всегда в этом методе в Mono.Security:
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);
в GenerateKeyPair (KeyPairGenerator.cs)
Есть идеи? Если нет, есть ли способы генерировать ключи Диффи-Хелмана каким-то другим способом?
Спасибо,
Ура,
ОБНОВЛЕНИЕ: я обнаружил странное решение, которое я не совсем понимаю:
Ранее я создал новый поток, так как я вызывал его из пользовательского интерфейса и не хотел, чтобы он зависал. Это был поток STA, так как мы создаем приложение VSTO, и оно не поддерживает MTA / BackgroundWorker() и т. Д. Из компонентов пользовательского интерфейса (в значительной степени ограничивая вас старым потоком (), поскольку вы можете указать, что это STA по мере необходимости). Я обнаружил, что проблема возникает чаще, когда пользователь щелкает по кнопке во время выполнения push (таким образом, делая некоторые проверки git), поэтому я отключил многопоточность и запустил ее непосредственно из пользовательского интерфейса. С тех пор он замораживает пользовательский интерфейс, но не зависает при сбое при расчете BigInt. Я полностью озадачен тем, как это происходит, если: Office (для которого мы создаем аддоны) каким-то образом не предоставит потоку с достаточным объемом памяти для вычислений BigInt (или неправильно управляет этой памятью, что не было бы совершенно удивительно) или, по какой-то причине, вычисления BigInt просто не могут быть вызваны в многопоточном контексте (может быть, Thread-> Ngit-> Sharpen-> Mono.Security-> Mono.Math (32-значное число) прервал работу с потоками??)
Есть идеи, что может быть причиной этого?
1 ответ
У меня были точно такие же проблемы при использовании закрытого ключа NGit + SSH для извлечения / извлечения данных из репозитория Git, который можно было запрашивать из нескольких потоков.
Я обнаружил, что это проблема с Mono.Security Mono.Math.BigInteger, когда он запускается в многопоточном контексте (отчет об ошибке и код для его репликации можно найти здесь). Хотя по какой-то причине я мог воспроизвести проблему только в среде Windows. На Mono в OSX вроде все работало нормально.
Чтобы обойти эту проблему, я в итоге изменил NSch на использование модифицированной реализации DiffieHellmanManaged, которая вычисляла ModPow для самих BigIntegers, используя ту же логику, что и System.Numerics.BigInteger.
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;
}