public static byte[] GetObsoleteSharedSecret(AsymmetricCipherKeyPair localKeyWithPrivate, byte[] remotePublicKeyDerEncoded) { var remotePublicKey = PublicKeyFactory.CreateKey(remotePublicKeyDerEncoded); var agreement = new ECDHBasicAgreement(); agreement.Init(localKeyWithPrivate.Private); return agreement.CalculateAgreement(remotePublicKey).ToByteArray(); }
public static byte[] GetSharedSecret(AsymmetricCipherKeyPair localKeyWithPrivate, byte[] remotePublicKeyDerEncoded) { var remotePublicKey = PublicKeyFactory.CreateKey(remotePublicKeyDerEncoded); var agreement = new ECDHBasicAgreement(); agreement.Init(localKeyWithPrivate.Private); using (var sha = SHA256.Create()) { // CalculateAgreement returns a BigInteger, whose length is variable, and bits are not whitened. // So hash it. return sha.ComputeHash(agreement.CalculateAgreement(remotePublicKey).ToByteArray()); } }
public static EncryptionResult EncryptMessage(byte[] userKey, byte[] userSecret, byte[] data, ushort padding = 0, bool randomisePadding = false) { var Random = new SecureRandom(); var Salt = new byte[16]; Random.NextBytes(Salt); var Curve = ECNamedCurveTable.GetByName("prime256v1"); var Spec = new ECDomainParameters(Curve.Curve, Curve.G, Curve.N, Curve.H, Curve.GetSeed()); var Generator = new ECKeyPairGenerator(); Generator.Init(new ECKeyGenerationParameters(Spec, new SecureRandom())); var KeyPair = Generator.GenerateKeyPair(); var AgreementGenerator = new ECDHBasicAgreement(); AgreementGenerator.Init(KeyPair.Private); var IKM = AgreementGenerator.CalculateAgreement(new ECPublicKeyParameters(Spec.Curve.DecodePoint(userKey), Spec)); var PRK = GenerateHKDF(userSecret, IKM.ToByteArrayUnsigned(), Encoding.UTF8.GetBytes("Content-Encoding: auth\0"), 32); var PublicKey = ((ECPublicKeyParameters)KeyPair.Public).Q.GetEncoded(false); var CEK = GenerateHKDF(Salt, PRK, CreateInfoChunk("aesgcm", userKey, PublicKey), 16); var Nonce = GenerateHKDF(Salt, PRK, CreateInfoChunk("nonce", userKey, PublicKey), 12); if (randomisePadding && (padding > 0)) padding = Convert.ToUInt16(Math.Abs(Random.NextInt()) % (padding + 1)); var Input = new byte[padding + 2 + data.Length]; Buffer.BlockCopy(ConvertInt(padding), 0, Input, 0, 2); Buffer.BlockCopy(data, 0, Input, padding + 2, data.Length); var Cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding"); Cipher.Init(true, new AeadParameters(new KeyParameter(CEK), 128, Nonce)); var Message = new byte[Cipher.GetOutputSize(Input.Length)]; Cipher.DoFinal(Input, 0, Input.Length, Message, 0); return new EncryptionResult { Salt = Salt, Payload = Message, PublicKey = PublicKey }; }
public void TestECBasicAgreementTest() { SecureRandom random = new SecureRandom(); FpCurve curve = new FpCurve( new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b ECDomainParameters parameters = new ECDomainParameters( curve, curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n ECKeyPairGenerator pGen = new ECKeyPairGenerator(); ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(parameters, random); pGen.Init(genParam); AsymmetricCipherKeyPair p1 = pGen.GenerateKeyPair(); AsymmetricCipherKeyPair p2 = pGen.GenerateKeyPair(); // // two way // IBasicAgreement e1 = new ECDHBasicAgreement(); IBasicAgreement e2 = new ECDHBasicAgreement(); e1.Init(p1.Private); e2.Init(p2.Private); BigInteger k1 = e1.CalculateAgreement(p2.Public); BigInteger k2 = e2.CalculateAgreement(p1.Public); if (!k1.Equals(k2)) { Fail("calculated agreement test failed"); } // // two way // e1 = new ECDHCBasicAgreement(); e2 = new ECDHCBasicAgreement(); e1.Init(p1.Private); e2.Init(p2.Private); k1 = e1.CalculateAgreement(p2.Public); k2 = e2.CalculateAgreement(p1.Public); if (!k1.Equals(k2)) { Fail("calculated agreement test failed"); } }
BigInteger ECDHAgree(byte[] publicKey, byte[] privateKey) { var domain = SecNamedCurves.GetByName ("secp160r1"); ECDHBasicAgreement agreement = new ECDHBasicAgreement (); BigInteger privKeyInt = new BigInteger (privateKey); ECDomainParameters parm = new ECDomainParameters(domain.Curve, domain.G, domain.N); ECPrivateKeyParameters privKey = new ECPrivateKeyParameters (privKeyInt, parm); agreement.Init (privKey); var pt = Key.Curve.Curve.DecodePoint (publicKey); ECPublicKeyParameters pubParams = new ECPublicKeyParameters (pt, parm); return agreement.CalculateAgreement (pubParams); }
protected virtual byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey) { ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement(); basicAgreement.Init(privateKey); BigInteger agreement = basicAgreement.CalculateAgreement(publicKey); return BigIntegers.AsUnsignedByteArray(agreement); }
protected virtual byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey) { ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement(); basicAgreement.Init(privateKey); BigInteger agreementValue = basicAgreement.CalculateAgreement(publicKey); /* * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for * any given field; leading zeros found in this octet string MUST NOT be truncated. */ return BigIntegers.AsUnsignedByteArray(basicAgreement.GetFieldSize(), agreementValue); }
/// <summary> /// Generates the KDF parameters. /// Sess Sections 7 & 8 of RFC 6637 (http://tools.ietf.org/html/rfc6637) for more details /// </summary> /// <returns></returns> private void UpdateDigestWithKDFParameters(IDigest digest) { var agreement = new ECDHBasicAgreement(); agreement.Init(_privateKey); var zb = agreement.CalculateAgreement(_publicKey).ToByteArrayUnsigned(); digest.Update(0x00); digest.Update(0x00); digest.Update(0x00); digest.Update(0x01); digest.BlockUpdate(zb, 0, zb.Length); var oid = _publicKey.PublicKeyParamSet.ToBytes(); digest.Update((byte)oid.Length); digest.BlockUpdate(oid, 0, oid.Length); digest.Update((byte)PublicKeyAlgorithmTag.Ecdh); digest.Update(0x3); digest.Update(0x1); digest.Update((byte)_publicKey.HashAlgorithm); digest.Update((byte)_publicKey.SymmetricKeyAlgorithm); digest.BlockUpdate(_anonymousSender, 0, _anonymousSender.Length); digest.BlockUpdate(_fingerPrint, 0, _fingerPrint.Length); }
public override void ProcessClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePrivateKey privateKey, byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length < 1) { throw new ArgumentException("data"); } byte[] ecPointData = new byte[data[0]]; Buffer.BlockCopy(data, 1, ecPointData, 0, ecPointData.Length); ECPoint ecPoint = domainParameters.Curve.DecodePoint(ecPointData); var theirPublicKey = new ECPublicKeyParameters(ecPoint, domainParameters); // Calculate the actual agreement var agreement = new ECDHBasicAgreement(); agreement.Init(this.privateKey); preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), 32); this.logger?.Debug("Pre-Master secret: " + BitConverter.ToString(preMasterSecret)); }
/// <summary> /// Called by client to get his ephemaral ECC keys /// TODO: get information about which ECC curve should be used /// </summary> /// <param name="version"></param> /// <param name="data"></param> /// <returns></returns> public override byte[] ProcessServerKeys(ProtocolVersion version, byte[] data, X509Certificate serverCertificate) { if (data == null) { throw new ArgumentNullException(nameof(data)); } if (data.Length < 4) throw new ArgumentException(nameof(data)); //if (data[0] != 3 || data[1] != 0 || data[2] != 23) if (data[0] != 3 || data[1] != 0) { throw new ArgumentException(nameof(data)); } //if (data[3] != 65 || data[4] > data.Length - 4) if (data[4] > data.Length - 4) { throw new ArgumentException(nameof(data)); } // Extract the public key from the data byte[] ecPointData = new byte[data[3]]; Buffer.BlockCopy(data, 4, ecPointData, 0, ecPointData.Length); var ecPoint = this.ObtainCurveNameAndPoint(ecPointData, serverCertificate); var theirPublicKey = new ECPublicKeyParameters(ecPoint, this.domainParameters); // Calculate the actual agreement var agreement = new ECDHBasicAgreement(); agreement.Init(this.privateKey); this.preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), 32); var signature = new byte[data.Length - 4 - data[3]]; Buffer.BlockCopy(data, 4 + data[3], signature, 0, signature.Length); return signature; }