Example #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Session"/> class.
        /// </summary>
        protected Session()
        {
            _id = Crypto8.GenerateNonce();
#if DEBUG
            _ident = InternalUtils.BytesToString(_id);
#endif
        }
        private byte[] ProcessOutgoingData(MessageDirection direction, byte[] plaintext)
        {
            var chiper = (byte[])null;

            // Handshaking
            if (_outgoingState == 0)
            {
                chiper = (byte[])plaintext.Clone();

                _direction = direction;
                if (_crypto == null)
                {
                    _crypto = new Crypto8(direction, _keyPair);
                }
            }

            if (direction != _direction)
            {
                throw new InvalidOperationException("Tried to process an outgoing message coming from a different direction."); // -> Protocol Exception?
            }
            // _outgoingState == 2 means we're the server.
            // Usually processing 20104 - LoginSuccessMessage.
            if (_outgoingState == 2)
            {
                Debug.Assert(_remoteNonce != null);
                Debug.Assert(_localNonce == null);

                var key         = Crypto8.GenerateKeyPair();
                var localNonce  = Crypto8.GenerateNonce();
                var remoteNonce = _remoteNonce;

                var tmpChiper = new byte[plaintext.Length + KeyPair.NonceLength + KeyPair.KeyLength];
                Buffer.BlockCopy(localNonce, 0, tmpChiper, 0, KeyPair.NonceLength);
                Buffer.BlockCopy(key.PublicKey, 0, tmpChiper, KeyPair.NonceLength, KeyPair.KeyLength);
                Buffer.BlockCopy(plaintext, 0, tmpChiper, KeyPair.NonceLength + KeyPair.KeyLength, plaintext.Length);

                _crypto.Encrypt(ref tmpChiper);

                Debug.WriteLine($"Server-nonce: {ToHexString(localNonce)}");
                Debug.WriteLine($"Shared-key: {ToHexString(key.PublicKey)}");

                _crypto.UpdateNonce(localNonce, UpdateNonceType.Encrypt);
                _crypto.UpdateSharedKey(key.PublicKey);

                _localNonce = localNonce;
                chiper      = tmpChiper;
                //_key = key;
            }
            // _outgoingState == 3 means we're the client.
            // Usually processing 10101 - LoginRequestMessage.
            else if (_outgoingState == 3)
            {
                var serverKey  = _serverKey;
                var sessionKey = _sessionKey;
                Debug.Assert(serverKey != null, "Server key was null.");
                Debug.Assert(sessionKey != null, "Session key was null.");

                // Generate a ClientNonce.
                var localNonce = Crypto8.GenerateNonce();

                Debug.WriteLine($"Generated ClientNonce: {ToHexString(localNonce)}");

                // Craft the new packet which is
                // tmpChiper = sessionKey + localNonce + plaintext.
                var tmpChiper = new byte[plaintext.Length + KeyPair.NonceLength * 2];
                Buffer.BlockCopy(sessionKey, 0, tmpChiper, 0, KeyPair.NonceLength);
                Buffer.BlockCopy(localNonce, 0, tmpChiper, KeyPair.NonceLength, KeyPair.NonceLength);
                Buffer.BlockCopy(plaintext, 0, tmpChiper, KeyPair.NonceLength * 2, plaintext.Length);

                // Use our specified from the constructor _keyPair.PublicKey and specified _serverKey from the constructor
                // to generate the blake2b nonce and encrypt using _keyPair.PrivateKey and the generated blake2b nonce.
                _crypto.UpdateSharedKey(serverKey);
                _crypto.Encrypt(ref tmpChiper);

                // Craft another new packet which is
                // chiper = _keyPair.PublicKey + tmpChiper.
                chiper = new byte[tmpChiper.Length + KeyPair.KeyLength];
                Buffer.BlockCopy(_crypto.KeyPair.PublicKey, 0, chiper, 0, KeyPair.KeyLength);
                Buffer.BlockCopy(tmpChiper, 0, chiper, KeyPair.KeyLength, tmpChiper.Length);

                _localNonce = localNonce;
            }
            // Messages after the previous states are processed the same way.
            else if (_outgoingState > (int)_direction)
            {
                var tmpChiper = (byte[])plaintext.Clone();

                _crypto.Encrypt(ref tmpChiper);
                chiper = tmpChiper;
            }

            return(chiper);
        }