public KeyExchangeMessage(UInt32 messageVersion, UInt32 sequence, UInt32 flags,
		                           ECPublicKey baseKey, byte[] baseKeySignature,
		                           ECPublicKey ratchetKey,
		                           IdentityKey identityKey)
        {
            MaxVersion = CiphertextMessage.CURRENT_VERSION;
            Version = messageVersion;
            Sequence = sequence;
            Flags = flags;
            BaseKey = baseKey;
            BaseKeySignature = baseKeySignature;
            RatchetKey = ratchetKey;
            IdentityKey = identityKey;

            byte[] version = { ByteUtil.IntsToByteHighAndLow(Version, MaxVersion) };
            var keyExchangeMsg = new WhisperProtos.KeyExchangeMessage {
                id = (Sequence << 5) | Flags,
                baseKey = BaseKey.Serialize(),
                ratchetKey = RatchetKey.Serialize(),
                identityKey = IdentityKey.Serialize()
            };

            if(Version >= 3)
            {
                keyExchangeMsg.baseKeySignature = BaseKeySignature;
            }

            byte[] bytes;
            using(var stream = new MemoryStream())
            {
                Serializer.Serialize(stream, keyExchangeMsg);
                bytes = stream.ToArray();
            }
            _serialized = ByteUtil.Combine(version, bytes);
        }
        public KeyExchangeMessage(byte[] serialized)
        {
            try
            {
                byte[][] parts = ByteUtil.split(serialized, 1, serialized.Length - 1);
                this.version          = (uint)ByteUtil.highBitsToInt(parts[0][0]);
                this.supportedVersion = (uint)ByteUtil.lowBitsToInt(parts[0][0]);

                if (this.version <= CiphertextMessage.UNSUPPORTED_VERSION)
                {
                    throw new LegacyMessageException("Unsupported legacy version: " + this.version);
                }

                if (this.version > CiphertextMessage.CURRENT_VERSION)
                {
                    throw new InvalidVersionException("Unknown version: " + this.version);
                }

                WhisperProtos.KeyExchangeMessage message = WhisperProtos.KeyExchangeMessage.ParseFrom(parts[1]);

                if (!message.HasId || !message.HasBaseKey ||
                    !message.HasRatchetKey || !message.HasIdentityKey ||
                    (this.version >= 3 && !message.HasBaseKeySignature))
                {
                    throw new InvalidMessageException("Some required fields missing!");
                }

                this.sequence         = message.Id >> 5;
                this.flags            = message.Id & 0x1f;
                this.serialized       = serialized;
                this.baseKey          = Curve.decodePoint(message.BaseKey.ToByteArray(), 0);
                this.baseKeySignature = message.BaseKeySignature.ToByteArray();
                this.ratchetKey       = Curve.decodePoint(message.RatchetKey.ToByteArray(), 0);
                this.identityKey      = new IdentityKey(message.IdentityKey.ToByteArray(), 0);
            }
            catch (InvalidKeyException e)
            {
                throw new InvalidMessageException(e);
            }
        }