Esempio n. 1
0
        public byte[] ReadMessageData(byte[] messageData)
        {
            (byte[] decryptedMessage, _) = ChaCha20Poly1305.DecryptWithAdditionalData(_transportState.ReceiveDecryptionKey,
                                                                                      _transportState.ReceiveNonce.GetBytes(), new byte[0], messageData);

            _transportState.ReceiveNonce.Increment();

            if (_transportState.ReceiveNonce.Value == 1000)
            {
                _transportState.RotateReceiveKey();
            }

            return(decryptedMessage.SubArray(0, messageData.Length - 16));
        }
Esempio n. 2
0
        public int ReadMessageLength(byte[] messageData)
        {
            (byte[] decryptedLength, _) = ChaCha20Poly1305.DecryptWithAdditionalData(_transportState.ReceiveDecryptionKey,
                                                                                     _transportState.ReceiveNonce.GetBytes(), new byte[0], messageData);

            _transportState.ReceiveNonce.Increment();

            int messageLength = decryptedLength.ToUShortBigEndian();
            int messageMax    = 65535;

            if (messageLength - 16 > messageMax)
            {
                throw new MessageException($"Invalid message length {messageLength}. Maximum: {messageMax}");
            }

            return(messageLength);
        }
Esempio n. 3
0
        public (List <byte[]> messages, int totalRead) Read(byte[] messageData, int length)
        {
            int           position = 0;
            List <byte[]> messages = new List <byte[]>();

            if (length < 18)
            {
                return(messages, 0);
            }

            while (position < length)
            {
                (byte[] decryptedLength, _) = ChaCha20Poly1305.DecryptWithAdditionalData(_transportState.ReceiveDecryptionKey,
                                                                                         _transportState.ReceiveNonce.GetBytes(), new byte[0], messageData.SubArray(position, 18));

                ushort messageLength = decryptedLength.ToUShortBigEndian();
                if (messageLength == 0)
                {
                    throw new MessageException("Invalid message length");
                }

                int encryptedMessageLength = 18 + messageLength + 16;
                int currentMessageLength   = length - position;
                if (encryptedMessageLength > currentMessageLength)
                {
                    return(messages, position);
                }

                _transportState.ReceiveNonce.Increment();
                (byte[] decryptedMessage, _) = ChaCha20Poly1305.DecryptWithAdditionalData(_transportState.ReceiveDecryptionKey,
                                                                                          _transportState.ReceiveNonce.GetBytes(), new byte[0], messageData.SubArray(position + 18, messageLength));

                _transportState.ReceiveNonce.Increment();
                messages.Add(decryptedMessage);

                position = position + encryptedMessageLength;
            }

            return(messages, position);
        }
Esempio n. 4
0
        public (byte[] tempK1, ECKeyPair ephemeralKey) ReadActOneRequest(Span <byte> message, int length)
        {
            if (_state.HandshakeState != HandshakeState.Initialized)
            {
                throw new InvalidOperationException($"Invalid handshake state {_state.HandshakeState}. Must be Initialized");
            }

            if (length != 50)
            {
                throw new ArgumentException("ACT1_READ_FAILED");
            }

            byte        version = message.Slice(0, 1)[0];
            ECKeyPair   responderEphemeralKey = new ECKeyPair(message.Slice(1, 33), false);
            Span <byte> c = message.Slice(34, 16);

            if (version != 0)
            {
                throw new NotSupportedException("ACT1_BAD_VERSION");
            }

            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(responderEphemeralKey.PublicKeyCompressed));
            byte[] ss            = ECDH.ComputeHashedPoint(responderEphemeralKey.PublicKeyParameters, _state.LocalKeyPair.PrivateKey);
            (byte[] chainingKey, byte[] tempK1) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);
            _state.ChainingKey = chainingKey;

            (_, byte[] mac) = ChaCha20Poly1305.DecryptWithAdditionalData(tempK1, _state.ReceiveNonce.GetBytes(), handshakeHash, new byte[0]);

            if (!c.SequenceEqual(mac))
            {
                throw new ArgumentException("ACT1_BAD_TAG");
            }

            _state.ReceiveNonce.Increment();
            _state.HandshakeHash  = SHA256.ComputeHash(handshakeHash.ConcatToNewArray(c.ToArray()));
            _state.HandshakeState = HandshakeState.Act1;
            return(tempK1, responderEphemeralKey);
        }
Esempio n. 5
0
        public void ReadActThreeRequest(Span <byte> message, int length)
        {
            if (length != 66)
            {
                throw new ArgumentException("ACT3_READ_FAILED");
            }

            byte        version = message.Slice(0, 1)[0];
            Span <byte> c       = message.Slice(1, 49);

            //byte[] t = message.SubArray(50, 16);

            if (version != 0)
            {
                throw new NotSupportedException("ACT3_BAD_VERSION");
            }

            (byte[] rs, _) = ChaCha20Poly1305.DecryptWithAdditionalData(_state.TempKey2, _state.ReceiveNonce.GetBytes(), _state.HandshakeHash, c.ToArray());
            ECKeyPair rsKey = new ECKeyPair(((Span <byte>)rs).Slice(0, 33), false);

            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(c.ToArray()));
            byte[] ss            = ECDH.ComputeHashedPoint(rsKey.PublicKeyParameters, _state.EphemeralKeyPair.PrivateKey);
            (byte[] chainingKey, _) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);

            //byte[] p, byte[] mac2) = ChaCha20Poly1305.decryptWithAD(tempK3, new byte[12], handshakeHash, t);
            // TODO: do mac check

            (byte[] decryptKey, byte[] encryptKey) = HmacSha256.ComputeHashes(chainingKey, new byte[0]);

            _state.ChainingKey          = chainingKey;
            _state.HandshakeHash        = handshakeHash;
            _state.SendEncryptionKey    = encryptKey;
            _state.ReceiveDecryptionKey = decryptKey;
            _state.SendNonce.Reset();
            _state.ReceiveNonce.Reset();
            _state.HandshakeState = HandshakeState.Finished;
        }