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.
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:
public DHParameters GenerateParameters()
{
var generator = new DHParametersGenerator();
generator.Init(BitSize, DefaultPrimeProbability, new SecureRandom());
return generator.GenerateParameters();
}
Wanna get g and p as strings?
public string GetG(DHParameters parameters)
{
return parameters.G.ToString();
}
public string GetP(DHParameters parameters)
{
return parameters.P.ToString();
}
How to generate a and 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?
// 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
.
Let's say you generated b and B and already got p, g and A. To compute the shared secret:
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.
Hope this is useful.