I'm writing an app that'll exchange data between a phone and a Windows PC, and I want to protect the data sent with key generated with a Diffie-Hellman exchange.
我正在编写一个应用程序,它将在手机和Windows PC之间交换数据,我想保护使用Diffie-Hellman交换机生成的密钥发送的数据。
I'm trying to use BouncyCastle for that, but the almost non-existant documentation for the C# implementation has me stumped.
我正在尝试使用BouncyCastle,但C#实现的几乎不存在的文档让我感到难过。
What I want to know is: what's the workflow for generating a DH key and computing a shared key when the other side's key is received? (I'm assuming I can send my key as a string and I can work with the other side's key as a string.) What objects/methods do I use in C# for that?
我想知道的是:当收到另一方的密钥时,生成DH密钥和计算共享密钥的工作流程是什么? (我假设我可以将我的密钥作为字符串发送,我可以将另一方的密钥作为字符串使用。)我在C#中使用哪些对象/方法?
1 个解决方案
#1
3
Alright, after a lot of trial, I got it working. Posting answer in case someone else needs it.
好吧,经过大量的试验,我得到了它的工作。发布答案以防其他人需要它。
I'll assume the reader (1) knows what Diffie-Hellman is and what it's useful for (read here for details) and (2) already imported Bouncycastle to a .NET project via NuGet.
我假设读者(1)知道什么是Diffie-Hellman以及它对什么有用(在这里详细阅读)和(2)已经通过NuGet将Bouncycastle导入到.NET项目中。
Imports you'll need:
您需要的进口:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
How to generate g and p:
如何生成g和p:
public DHParameters GenerateParameters()
{
var generator = new DHParametersGenerator();
generator.Init(BitSize, DefaultPrimeProbability, new SecureRandom());
return generator.GenerateParameters();
}
Wanna get g and p as strings?
想得到g和p作为字符串?
public string GetG(DHParameters parameters)
{
return parameters.G.ToString();
}
public string GetP(DHParameters parameters)
{
return parameters.P.ToString();
}
How to generate a and A:
如何生成A和A:
public AsymmetricCipherKeyPair GenerateKeys(DHParameters parameters)
{
var keyGen = GeneratorUtilities.GetKeyPairGenerator("DH");
var kgp = new DHKeyGenerationParameters(new SecureRandom(), parameters);
keyGen.Init(kgp);
return keyGen.GenerateKeyPair();
}
Wanna read a and A as a string?
想读一个和A作为一个字符串?
// This returns A
public string GetPublicKey(AsymmetricCipherKeyPair keyPair)
{
var dhPublicKeyParameters = _generatedKey.Public as DHPublicKeyParameters;
if (dhPublicKeyParameters != null)
{
return dhPublicKeyParameters.Y.ToString();
}
throw new NullReferenceException("The key pair provided is not a valid DH keypair.");
}
// This returns a
public string GetPrivateKey(AsymmetricCipherKeyPair keyPair)
{
var dhPrivateKeyParameters = _generatedKey.Private as DHPrivateKeyParameters;
if (dhPrivateKeyParameters != null)
{
return dhPrivateKeyParameters.X.ToString();
}
throw new NullReferenceException("The key pair provided is not a valid DH keypair.");
}
To import the parameters from strings just do:
要从字符串导入参数,请执行以下操作:
var importedParameters = new DHParameters(p, g);
To generate b and B just use GenerateKeys()
with importedParameters
instead of the generated parameters
.
要生成b和B,只需使用带有导入参数的GenerateKeys()而不是生成的参数。
Let's say you generated b and B and already got p, g and A. To compute the shared secret:
假设你生成了b和B,并且已经得到了p,g和A.要计算共享密钥:
public BigInteger ComputeSharedSecret(string A, AsymmetricKeyParameter bPrivateKey, DHParameters internalParameters)
{
var importedKey = new DHPublicKeyParameters(new BigInteger(A), internalParameters);
var internalKeyAgree = AgreementUtilities.GetBasicAgreement("DH");
internalKeyAgree.Init(bPrivateKey);
return internalKeyAgree.CalculateAgreement(importedKey);
}
Repeat for A and now you have a shared secret between 2 clients, ready to be used to encrypt communications.
重复A,现在您有2个客户端之间的共享密钥,准备用于加密通信。
Hope this is useful.
希望这很有用。
#1
3
Alright, after a lot of trial, I got it working. Posting answer in case someone else needs it.
好吧,经过大量的试验,我得到了它的工作。发布答案以防其他人需要它。
I'll assume the reader (1) knows what Diffie-Hellman is and what it's useful for (read here for details) and (2) already imported Bouncycastle to a .NET project via NuGet.
我假设读者(1)知道什么是Diffie-Hellman以及它对什么有用(在这里详细阅读)和(2)已经通过NuGet将Bouncycastle导入到.NET项目中。
Imports you'll need:
您需要的进口:
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
How to generate g and p:
如何生成g和p:
public DHParameters GenerateParameters()
{
var generator = new DHParametersGenerator();
generator.Init(BitSize, DefaultPrimeProbability, new SecureRandom());
return generator.GenerateParameters();
}
Wanna get g and p as strings?
想得到g和p作为字符串?
public string GetG(DHParameters parameters)
{
return parameters.G.ToString();
}
public string GetP(DHParameters parameters)
{
return parameters.P.ToString();
}
How to generate a and A:
如何生成A和A:
public AsymmetricCipherKeyPair GenerateKeys(DHParameters parameters)
{
var keyGen = GeneratorUtilities.GetKeyPairGenerator("DH");
var kgp = new DHKeyGenerationParameters(new SecureRandom(), parameters);
keyGen.Init(kgp);
return keyGen.GenerateKeyPair();
}
Wanna read a and A as a string?
想读一个和A作为一个字符串?
// This returns A
public string GetPublicKey(AsymmetricCipherKeyPair keyPair)
{
var dhPublicKeyParameters = _generatedKey.Public as DHPublicKeyParameters;
if (dhPublicKeyParameters != null)
{
return dhPublicKeyParameters.Y.ToString();
}
throw new NullReferenceException("The key pair provided is not a valid DH keypair.");
}
// This returns a
public string GetPrivateKey(AsymmetricCipherKeyPair keyPair)
{
var dhPrivateKeyParameters = _generatedKey.Private as DHPrivateKeyParameters;
if (dhPrivateKeyParameters != null)
{
return dhPrivateKeyParameters.X.ToString();
}
throw new NullReferenceException("The key pair provided is not a valid DH keypair.");
}
To import the parameters from strings just do:
要从字符串导入参数,请执行以下操作:
var importedParameters = new DHParameters(p, g);
To generate b and B just use GenerateKeys()
with importedParameters
instead of the generated parameters
.
要生成b和B,只需使用带有导入参数的GenerateKeys()而不是生成的参数。
Let's say you generated b and B and already got p, g and A. To compute the shared secret:
假设你生成了b和B,并且已经得到了p,g和A.要计算共享密钥:
public BigInteger ComputeSharedSecret(string A, AsymmetricKeyParameter bPrivateKey, DHParameters internalParameters)
{
var importedKey = new DHPublicKeyParameters(new BigInteger(A), internalParameters);
var internalKeyAgree = AgreementUtilities.GetBasicAgreement("DH");
internalKeyAgree.Init(bPrivateKey);
return internalKeyAgree.CalculateAgreement(importedKey);
}
Repeat for A and now you have a shared secret between 2 clients, ready to be used to encrypt communications.
重复A,现在您有2个客户端之间的共享密钥,准备用于加密通信。
Hope this is useful.
希望这很有用。