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)); }
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); }
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); }
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); }
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; }