Надувной замок Diffie-Hellman DHParams Issue
Я пытаюсь использовать библиотеки.net для bouncy castle для обмена ключами Диффи-Хеллмана и столкнулся с проблемой при создании объекта DHParams.
Мое решение будет включать центральный орган, который будет генерировать отдельный ключ / пару DH для каждого подключаемого клиента. Идея заключается в том, что я буду хранить отдельное соглашение о ключе DH для каждого подключенного клиента. Затем я отправлю значение p,g клиенту, где клиент рассчитает его соответствие ключу dh. Я хочу генерировать разные значения p,g для каждого клиента. Я использую BigInteger для этого, но сталкиваюсь с некоторыми проблемами.
Когда я пытаюсь создать новый объект DHParameters, он выдает следующее исключение всякий раз, когда я использую битовую длину, отличную от 768:
System.ArgumentException was unhandled
Message="generator must in the range [2, p - 2]\r\nParameter name: g"
Source="BouncyCastle.Crypto"
ParamName="g"
StackTrace:
at Org.BouncyCastle.Crypto.Parameters.DHParameters..ctor(BigInteger p, BigInteger g, BigInteger q, Int32 m, Int32 l, BigInteger j, DHValidationParameters validation)
at Org.BouncyCastle.Crypto.Parameters.DHParameters..ctor(BigInteger p, BigInteger g, BigInteger q, Int32 l)
at TestDH.Program.Main(String[] args) in C:\dev\source\TestDH\TestDH\Program.cs:line 30
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
"generator must in the range [2, p - 2]"
Я не уверен, имеет ли это значение, но я попробовал все виды различных значений для определенности в конструкторе BigInteger.
Вот мой код:
SecureRandom sr = new SecureRandom();
// p,g generation, done by central authority
BigInteger g512 = new BigInteger(512, 30, sr);
BigInteger p512 = new BigInteger(512, 30, sr);
// p,g is then sent to client from central authority
// common - performed by both server and client sides
IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("DH");
DHParameters dhParams = new DHParameters(p512, g512, null, 512); // Here is where I get the exception if the first parameter if BigInteger is not 768 or lager
Проблема в том, что генерация 768-битного простого числа занимает слишком много времени - свыше 5 секунд на двухъядерном процессоре 2,1 ГГц без запуска других процессов. Это слишком большая сумма штрафа для каждого клиента, который инициирует соединение. Я хотел бы использовать меньшую длину в битах для BigInteger.
Я, вероятно, делаю это совершенно неправильно - есть скудная документация о том, как сделать DH с надувным замком, и тесты / примеры просто не соответствуют моему случаю использования. Я не хочу иметь предварительно сгенерированные значения p,g.
РЕДАКТИРОВАТЬ Кажется, даже длина 768 бит дает ошибки один раз в некоторое время. После перезапуска моей машины я мог работать без разрядов, кроме 1024, и даже тогда только в 80% случаев. Я думаю, что я делаю что-то не так.
1 ответ
Я понял. Вы не должны использовать конструктор для DHParameters. Используйте утилиту генератора для получения ваших параметров. Вот код, который работает:
const int DefaultPrimeProbability = 30;
DHParametersGenerator generator = new DHParametersGenerator();
generator.Init(512, DefaultPrimeProbability, new SecureRandom());
DHParameters parameters = generator.GenerateParameters();
KeyGenerationParameters kgp = new DHKeyGenerationParameters(new SecureRandom(), parameters);
keyGen.Init(kgp);
AsymmetricCipherKeyPair aliceKeyPair = keyGen.GenerateKeyPair();
IBasicAgreement aliceKeyAgree = AgreementUtilities.GetBasicAgreement("DH");
aliceKeyAgree.Init(aliceKeyPair.Private);
AsymmetricCipherKeyPair bobKeyPair = keyGen.GenerateKeyPair();
IBasicAgreement bobKeyAgree = AgreementUtilities.GetBasicAgreement("DH");
bobKeyAgree.Init(bobKeyPair.Private);
BigInteger aliceAgree = aliceKeyAgree.CalculateAgreement(bobKeyPair.Public);
BigInteger bobAgree = bobKeyAgree.CalculateAgreement(aliceKeyPair.Public);
if (!aliceAgree.Equals(bobAgree))
{
throw new Exception("Keys do not match.");
}
// generate key from prime integers generated above