public override bool onHandshake() { //wait for RSA from server RSAEncryption RSA = null; SyncObject syncObject = null; DiffieHellman diffieHellman = new DiffieHellman(256); if (!base.ReceiveMessage((IMessage message) => { MsgRsaPublicKey rsaKey = message as MsgRsaPublicKey; if (rsaKey != null) { RSA = new RSAEncryption(Connection.RSA_KEY_SIZE, rsaKey.Modulus, rsaKey.Exponent, true); return(true); } return(false); }).Wait <bool>(false, 30000)) { if (syncObject.TimedOut) { throw new TimeoutException(TimeOutMessage); } Client.Disconnect(DisconnectReason.TimeOut); throw new Exception("The RSA Exchange failed"); } //Calculate and apply the public key as key //If the key is spoofed the next packet that's being send could fail if public key is generated wrong :) byte[] SecretHash = SHS_KeyExchange.CalculateSecretHash(RSA.Parameters.Modulus, RSA.Parameters.Exponent); Client.Connection.protection.ApplyPrivateKey(SecretHash); bool BlockedCertificate = false; if (!(syncObject = base.ReceiveMessage((IMessage message) => { MsgServerEncryption mse = message as MsgServerEncryption; if (mse != null) { Client.UseUDP = mse.UseUdp; uint[] TempKey = new uint[SecretHash.Length]; for (int i = 0; i < TempKey.Length; i++) { TempKey[i] = SecretHash[i]; } byte[] EncryptedDiffieKey = new byte[mse.Key.Length]; Array.Copy(mse.Key, EncryptedDiffieKey, mse.Key.Length); //Decrypt the diffie-hellman key with our SecretHash which is generated by our Public RSA UnsafeXor XorEncryption = new UnsafeXor(TempKey, true); XorEncryption.Decrypt(mse.Key, 0, mse.Key.Length); //read the Diffie-Hellman key long index = Client.PrivateKeyOffset % 65535; if (index <= 4) { index = 10; } byte[] diffieData = new byte[BitConverter.ToInt32(mse.Key, (int)(index - 4))]; //get the key length Array.Copy(mse.Key, index, diffieData, 0, diffieData.Length); //copy the diffie-hellman key in between random data //fix RSA Encrypted Data //Array.Copy(mse.Key, mse.Key.Length - (diffieLen.Length + diffieData.Length), mse.Key, index - 4, diffieLen.Length + diffieData.Length); //Array.Resize(ref mse.Key, mse.Key.Length - (diffieLen.Length + diffieData.Length)); //set original size back //check if key is original uint KeyHash = BitConverter.ToUInt32(new CRC32().ComputeHash(mse.Key), 0); if (KeyHash != mse.KeyHash) { return(false); } diffieHellman.GenerateResponse(new PayloadReader(diffieData)); Client.Certificate = mse.certificate; if (!Client.onVerifyCertificate(mse.certificate)) { BlockedCertificate = true; return(false); } Client.Connection.protection.ApplyPrivateKey(EncryptedDiffieKey); //apply Encrypted Key base.SendMessage(new MsgDiffiehellman(diffieHellman.GetDiffie())); Client.Connection.protection.ApplyPrivateKey(diffieHellman.Key); //apply diffie-hellman key return(true); } return(false); })).Wait <bool>(false, 30000)) { Client.Disconnect(DisconnectReason.TimeOut); Client.onException(new Exception("Handshake went wrong, CHS_KeyExchange"), ErrorType.Core); if (!BlockedCertificate) { if (syncObject.TimedOut) { throw new TimeoutException(TimeOutMessage); } throw new Exception("Diffie-Hellman key-exchange failed."); } throw new Exception("The certificate provided by the server was blocked by the user"); } return(true); }
public override bool onHandshake() { DiffieHellman diffieHellman = new DiffieHellman(256); //send RSA public key RSAEncryption RSA = KeyHandler.GetPrivateKey(); base.SendMessage(new MsgRsaPublicKey(RSA.Parameters)); //Calculate and apply the public key as key //If the key is spoofed the next packet that's being send could fail if public key is generated wrong :) byte[] SecretHash = SHS_KeyExchange.CalculateSecretHash(RSA.Parameters.Modulus, RSA.Parameters.Exponent); Client.Connection.protection.ApplyPrivateKey(SecretHash);//apply our secret hash based on the public key //generate a big random key byte[] encryptionKey = new byte[65535]; new Random(DateTime.Now.Millisecond).NextBytes(encryptionKey); //encrypt the key with RSA byte[] cryptedKey = RSA.Encrypt(encryptionKey, 0, encryptionKey.Length); diffieHellman = KeyHandler.GetDiffieHellman(); byte[] diffieStr = diffieHellman.GetDiffie(); long index = Client.PrivateKeyOffset % 65535; if (index <= 4) { index = 10; } byte[] diffieLen = BitConverter.GetBytes(diffieStr.Length); //create a backup of encrypted RSA data //byte[] RsaBackup = new byte[diffieLen.Length + diffieStr.Length]; //Array.Copy(cryptedKey, index - 4, RsaBackup, 0, RsaBackup.Length); //Rsa Backup Data Array.Copy(diffieLen, 0, cryptedKey, index - 4, diffieLen.Length); //write Diffie-Hellman key length Array.Copy(diffieStr, 0, cryptedKey, index, diffieStr.Length); //copy the diffie-hellman key in between random data //maybe not secure adding this at the end of the encrypted data but whatever for now //Array.Resize(ref cryptedKey, cryptedKey.Length + RsaBackup.Length); //Array.Copy(RsaBackup, 0, cryptedKey, cryptedKey.Length - RsaBackup.Length, RsaBackup.Length); uint KeyHash = BitConverter.ToUInt32(new CRC32().ComputeHash(cryptedKey), 0); CertInfo certificate = new CertInfo(serverProperties.ServerCertificate); certificate.FingerPrintMd5 = BitConverter.ToString(MD5.Create().ComputeHash(serverProperties.ServerCertificate.PrivateKey)).Replace("-", ""); certificate.FingerPrintSha1 = BitConverter.ToString(SHA1.Create().ComputeHash(serverProperties.ServerCertificate.PrivateKey)).Replace("-", ""); certificate.KeyAlgorithm = "RSA with " + Connection.RSA_KEY_SIZE + "bit"; certificate.Compression = ""; //serverProperties.Compression.ToString(); certificate.Cipher = ""; // serverProperties.Encryption.ToString(); certificate.HandshakeMethod = "RSA" + Connection.RSA_KEY_SIZE + "-DiffieHellman-AES256"; if (!serverProperties.ServerCertificate.ShowProtectionMethods) { certificate.Cipher = ""; certificate.Compression = ""; certificate.HandshakeMethod = ""; certificate.KeyAlgorithm = ""; } Client.Certificate = certificate; //Convert bytes to UINT uint[] TempKey = new uint[SecretHash.Length]; for (int i = 0; i < TempKey.Length; i++) { TempKey[i] = SecretHash[i]; } //Encrypt the diffie-hellman key with our SecretHash which is generated by our Public RSA UnsafeXor XorEncryption = new UnsafeXor(TempKey, true); XorEncryption.Encrypt(ref cryptedKey, 0, cryptedKey.Length); //send encryption info + diffie-hellman base.SendMessage(new MsgServerEncryption(serverProperties.AllowUdp, certificate, cryptedKey, KeyHash)); //apply the Encrypted Key, Yes the Encrypted Key, if spoofed the key should change at the client side ;) Client.Connection.protection.ApplyPrivateKey(cryptedKey); if (!base.ReceiveMessage((IMessage message) => { MsgDiffiehellman diffie = message as MsgDiffiehellman; if (diffie != null) { try { diffieHellman.HandleResponse(new PayloadReader(diffie.DiffieHellman)); Client.Connection.protection.ApplyPrivateKey(diffieHellman.Key); //apply diffie-hellman key return(true); } catch { return(false); } } return(false); }).Wait <bool>(false, 30000)) { Client.Disconnect(DisconnectReason.TimeOut); Client.onException(new Exception("Handshake went wrong, SHS_KeyExchange"), ErrorType.Core); return(false); } return(true); }
public UnsafeXorProtection() : base() { this.unsafeXor = new UnsafeXor(true); }