summary refs log tree commit diff
path: root/Crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs')
-rw-r--r--Crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs64
1 files changed, 64 insertions, 0 deletions
diff --git a/Crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs b/Crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs
new file mode 100644
index 000000000..28437a268
--- /dev/null
+++ b/Crypto/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+	public class ECDHWithKdfBasicAgreement
+		: ECDHBasicAgreement
+	{
+		private readonly string algorithm;
+		private readonly IDerivationFunction kdf;
+
+		public ECDHWithKdfBasicAgreement(
+			string				algorithm,
+			IDerivationFunction	kdf)
+		{
+			if (algorithm == null)
+				throw new ArgumentNullException("algorithm");
+			if (kdf == null)
+				throw new ArgumentNullException("kdf");
+
+			this.algorithm = algorithm;
+			this.kdf = kdf;
+		}
+
+		public override BigInteger CalculateAgreement(
+			ICipherParameters pubKey)
+		{
+			// Note that the ec.KeyAgreement class in JCE only uses kdf in one
+			// of the engineGenerateSecret methods.
+
+			BigInteger result = base.CalculateAgreement(pubKey);
+
+			int keySize = GeneratorUtilities.GetDefaultKeySize(algorithm);
+
+			DHKdfParameters dhKdfParams = new DHKdfParameters(
+				new DerObjectIdentifier(algorithm),
+				keySize,
+				bigIntToBytes(result));
+
+			kdf.Init(dhKdfParams);
+
+			byte[] keyBytes = new byte[keySize / 8];
+			kdf.GenerateBytes(keyBytes, 0, keyBytes.Length);
+
+			return new BigInteger(1, keyBytes);
+		}
+
+		private byte[] bigIntToBytes(
+			BigInteger r)
+		{
+			int byteLength = X9IntegerConverter.GetByteLength(privKey.Parameters.G.X);
+			return X9IntegerConverter.IntegerToBytes(r, byteLength);
+		}
+	}
+}