__int64 __fastcall RBX::Security::SessionCrypto::isTestOnly(unsigned __int8 format)
{
  return format >> 7;
}

void __fastcall RBX::Security::SessionCrypto::resetKeyExchangeKeys(RBX::Security::SessionCrypto *this, bool error)
{
  std::unique_ptr<RBX::Security::SessionCrypto::KeyExchangeKeys>::reset(&this->keyExchangeKeys, 0LL);
  this->isEarlySessionReady = 0;
  if ( error )
    *&this->isSessionReady = 256;
}

void __fastcall RBX::Security::SessionCrypto::setRakCryptoFormat(
        RBX::Security::SessionCrypto *this,
        RBX::Security::SessionCrypto::CryptoFormat value)
{
  this->rakFormat = value;
}

// local variable allocation has failed, the output may be wrong!
// Hidden C++ exception states: #wind=4
std::pair<std::string,bool> *__fastcall RBX::Security::SessionCrypto::verifyPreauthMac(
        std::pair<std::string,bool> *result,
        RBX::StringView *msg,
        RBX::StringView *preauthBlob)
{
  bool v5; // bl
  char v6; // r13
  _QWORD *v7; // rax
  __int64 v8; // r8
  unsigned __int64 v9; // rsi
  unsigned __int64 v10; // rcx
  unsigned __int64 v11; // rdx
  unsigned __int64 Length; // r9
  _QWORD *v13; // r8
  const char *Data; // r10
  char v15; // al
  unsigned __int64 v16; // rcx
  unsigned __int8 *Instance; // rcx
  unsigned __int64 v18; // r12
  _BYTE *v19; // r15
  __int128 v20; // xmm6
  char *v21; // rdi
  std::_String_val<std::_Simple_types<char> >::_Bxty Bx; // xmm7
  unsigned int v23; // r9d
  unsigned __int64 v24; // rdx
  char *Ptr; // rcx
  unsigned __int8 *Mylast; // rcx
  std::string *v27; // rbx
  unsigned __int64 v28; // rdx
  char *v29; // rax
  unsigned __int64 v30; // rdx
  char *v31; // rcx
  char *v32; // rcx
  unsigned __int64 v33; // rdx
  unsigned __int8 *v34; // rax
  unsigned __int64 v35; // rdx
  char *v36; // rax
  _WORD name[4]; // [rsp+28h] [rbp-E0h]
  std::_String_val<std::_Simple_types<char> >::_Bxty name_8; // [rsp+30h] [rbp-D8h] BYREF
  _BYTE name_24[48]; // [rsp+40h] [rbp-C8h] OVERLAPPED BYREF
  std::vector<unsigned char> key; // [rsp+70h] [rbp-98h] BYREF
  __int64 v42; // [rsp+88h] [rbp-80h]
  _BYTE v43[48]; // [rsp+98h] [rbp-70h] OVERLAPPED BYREF
  RBX::StringView v44; // [rsp+C8h] [rbp-40h] BYREF
  RBX::StringView v45; // [rsp+D8h] [rbp-30h] BYREF
  std::string v46; // [rsp+E8h] [rbp-20h] BYREF
  char v48; // [rsp+180h] [rbp+78h]

  v5 = 1;
  v48 = 1;
  v6 = 0;
  name[0] = 0;
  *&v43[32] = 0LL;
  v7 = &v43[16];
  v8 = 2LL;
  do
  {
    *v7 = 0LL;
    v7[1] = 0LL;
    v7 += 2;
    --v8;
  }
  while ( v8 );
  *&name_24[16] = 0LL;
  *&name_24[32] = 0LL;
  v9 = 15LL;
  *&name_24[40] = 15LL;
  if ( DFFlag::ForceNewPaBlob2.value || preauthBlob->Length > 0x20 )
  {
    v10 = 16LL;
    v11 = 0LL;
    Length = preauthBlob->Length;
    v13 = &v43[16];
    do
    {
      if ( Length == v10 )
        break;
      Data = preauthBlob->Data;
      v15 = preauthBlob->Data[v10];
      v16 = v10 + 1;
      *(name + v11) = v15;
      if ( Length - v16 < 0x10 )
        break;
      *v13 = &Data[v16];
      v13[1] = 16LL;
      v10 = v16 + 16;
      if ( v10 >= Length )
        break;
      ++v11;
      v13 += 2;
    }
    while ( v11 < 2 );
  }
  else
  {
    LOBYTE(name[0]) = 6;
    *&v43[16] = preauthBlob->Data + 16;
    *&v43[24] = 16LL;
  }
  Instance = RBX::Security::KeyRing::getInstance();
  key._Mypair._Myval2._Myfirst = Instance;
  v18 = 0LL;
  v19 = &v43[16];
  v20 = *&name_24[32];
  v21 = *&name_24[16];
  Bx = *&name_24[16];
  while ( 1 )
  {
    if ( v6 )
      goto LABEL_52;
    v23 = *(name + v18);
    *&name_24[8] = 15LL;
    *name_24 = 10LL;
    strcpy(name_8._Buf, "PreAuthKey");
    RBX::Security::KeyRing::getKeyForConsumption(Instance, &key._Mypair._Myval2._Mylast, &name_8, v23);
    if ( *&name_24[8] >= 0x10uLL )
    {
      v24 = *&name_24[8] + 1LL;
      Ptr = name_8._Ptr;
      if ( (*&name_24[8] + 1LL) >= 0x1000 )
      {
        v24 = *&name_24[8] + 40LL;
        Ptr = *(name_8._Ptr - 1);
        if ( (name_8._Ptr - Ptr - 8) > 0x1F )
          _invalid_parameter_noinfo_noreturn();
      }
      operator delete(Ptr, v24);
    }
    *name_24 = 0LL;
    *&name_24[8] = 15LL;
    name_8._Buf[0] = 0;
    Mylast = key._Mypair._Myval2._Mylast;
    if ( key._Mypair._Myval2._Mylast == key._Mypair._Myval2._Myend || !*v19 )
    {
      v5 = 0;
      v48 = 0;
    }
    else
    {
      *v43 = key._Mypair._Myval2._Mylast;
      *&v43[8] = key._Mypair._Myval2._Myend - key._Mypair._Myval2._Mylast;
      v44 = *v43;
      v45 = *msg;
      v27 = RBX::Crypto::computeKeyedBlake2b(&v46, &v45, &v44, 16);
      if ( &name_24[16] != v27 )
      {
        if ( v9 >= 0x10 )
        {
          v28 = v9 + 1;
          v29 = v21;
          if ( v9 + 1 >= 0x1000 )
          {
            v28 = v9 + 40;
            v21 = *(v21 - 1);
            if ( (v29 - v21 - 8) > 0x1F )
LABEL_44:
              _invalid_parameter_noinfo_noreturn();
          }
          operator delete(v21, v28);
        }
        Bx = v27->_Mypair._Myval2._Bx;
        *&name_24[16] = v27->_Mypair._Myval2._Bx;
        v20 = *&v27->_Mypair._Myval2._Mysize;
        *&name_24[32] = v20;
        v27->_Mypair._Myval2._Mysize = 0LL;
        v27->_Mypair._Myval2._Myres = 15LL;
        v27->_Mypair._Myval2._Bx._Buf[0] = 0;
        v9 = *&name_24[40];
        v21 = *&name_24[16];
      }
      if ( v46._Mypair._Myval2._Myres >= 0x10 )
      {
        v30 = v46._Mypair._Myval2._Myres + 1;
        v31 = v46._Mypair._Myval2._Bx._Ptr;
        if ( v46._Mypair._Myval2._Myres + 1 >= 0x1000 )
        {
          v30 = v46._Mypair._Myval2._Myres + 40;
          v31 = *(v46._Mypair._Myval2._Bx._Ptr - 1);
          if ( (v46._Mypair._Myval2._Bx._Ptr - v31 - 8) > 0x1F )
            goto LABEL_44;
        }
        operator delete(v31, v30);
      }
      v32 = &name_24[16];
      if ( v9 >= 0x10 )
        v32 = v21;
      if ( *v32 == **v19 && *(v32 + 1) == *(*v19 + 8LL) )
      {
        v6 = 1;
        v5 = v48;
      }
      else
      {
        v5 = 0;
        v48 = 0;
      }
      Mylast = key._Mypair._Myval2._Mylast;
    }
    if ( Mylast )
    {
      v33 = v42 - Mylast;
      v34 = Mylast;
      if ( (v42 - Mylast) >= 0x1000 )
      {
        Mylast = *(Mylast - 1);
        v33 += 39LL;
        if ( (v34 - Mylast - 8) > 0x1F )
          _invalid_parameter_noinfo_noreturn();
      }
      operator delete(Mylast, v33);
    }
    ++v18;
    v19 += 16;
    if ( v18 >= 2 )
      break;
    Instance = key._Mypair._Myval2._Myfirst;
  }
  if ( v6 )
  {
LABEL_52:
    result->first._Mypair._Myval2._Bx = Bx;
    *&result->first._Mypair._Myval2._Mysize = v20;
    result->second = v5;
    return result;
  }
  name_8._Ptr = 0LL;
  *name_24 = 0LL;
  *&name_24[8] = 15LL;
  result->first._Mypair._Myval2._Bx._Ptr = 0LL;
  result->first._Mypair._Myval2._Mysize = 0LL;
  result->first._Mypair._Myval2._Myres = 0LL;
  result->first._Mypair._Myval2._Bx = name_8;
  *&result->first._Mypair._Myval2._Mysize = *name_24;
  result->second = 0;
  if ( v9 >= 0x10 )
  {
    v35 = v9 + 1;
    v36 = v21;
    if ( v9 + 1 >= 0x1000 )
    {
      v35 = v9 + 40;
      v21 = *(v21 - 1);
      if ( (v36 - v21 - 8) > 0x1F )
        _invalid_parameter_noinfo_noreturn();
    }
    operator delete(v21, v35);
  }
  return result;
}

void __fastcall RBX::Security::SessionCrypto::~SessionCrypto(RBX::Security::SessionCrypto *this)
{
  std::_Ref_count_base *Rep; // rbx
  RBX::Security::SessionCrypto::KeyExchangeKeys *Myval2; // rbx

  this->__vftable = RBX::Security::SessionCrypto::`vftable';
  Rep = this->earlyAuthData._Rep;
  if ( Rep )
  {
    if ( _InterlockedExchangeAdd(&Rep->_Uses, 0xFFFFFFFF) == 1 )
    {
      Rep->_Destroy(Rep);
      if ( _InterlockedExchangeAdd(&Rep->_Weaks, 0xFFFFFFFF) == 1 )
        Rep->_Delete_this(Rep);
    }
  }
  Myval2 = this->keyExchangeKeys._Mypair._Myval2;
  if ( Myval2 )
  {
    RBX::Security::SessionCrypto::KeyExchangeKeys::~KeyExchangeKeys(Myval2);
    operator delete(Myval2, 0xE0uLL);
  }
}

bool __fastcall RBX::Security::SessionCrypto::isKeyExchangeComplete(RBX::Security::SessionCrypto *this)
{
  return !this->isError && this->isSessionReady;
}

_BOOL8 __fastcall RBX::Security::SessionCrypto::isAesGcm(RBX::Security::SessionCrypto::CryptoFormat format)
{
  return (format & 2) != 0;
}

void __fastcall RBX::Security::SessionCrypto::initCommon(RBX::Security::SessionCrypto *this)
{
  std::unique_ptr<RBX::Security::SessionCrypto::KeyExchangeKeys> *p_keyExchangeKeys; // rdi
  RBX::Security::SessionCrypto::KeyExchangeKeys *v2; // rax
  RBX::Security::SessionCrypto::KeyExchangeKeys *v3; // rbx

  *&this->isEarlySessionReady = 0;
  p_keyExchangeKeys = &this->keyExchangeKeys;
  this->isError = 0;
  v2 = operator new(0xE0uLL);
  v3 = v2;
  if ( v2 )
  {
    sodium_memzero(v2, 0x20uLL);
    sodium_memzero(&v3->secretEphemeralKey, 0x20uLL);
    sodium_memzero(&v3->publicEarlyKey, 0x20uLL);
    sodium_memzero(&v3->secretEarlyKey, 0x20uLL);
    sodium_memzero(&v3->earlySessionKeyClientToServer, 0x20uLL);
    sodium_memzero(&v3->earlySessionKeyServerToClient, 0x20uLL);
  }
  else
  {
    v3 = 0LL;
  }
  std::unique_ptr<RBX::Security::SessionCrypto::KeyExchangeKeys>::reset(p_keyExchangeKeys, v3);
  crypto_kx_keypair(
    p_keyExchangeKeys->_Mypair._Myval2->publicEphemeralKey._Elems,
    p_keyExchangeKeys->_Mypair._Myval2->secretEphemeralKey._Elems);
}

bool __fastcall RBX::Security::SessionCrypto::getSupportAes(RBX::Security::SessionCrypto *this)
{
  int is_available; // eax

  if ( DFFlag::ScNoAes.value || (is_available = crypto_aead_aes256gcm_is_available(), is_available != 1) )
    LOBYTE(is_available) = 0;
  return is_available;
}

__int64 __fastcall RBX::Security::SessionCrypto::getRakCryptoFormat(RBX::Security::SessionCrypto *this)
{
  return this->rakFormat;
}

RBX::Security::SessionCrypto::CryptoFormat __fastcall RBX::Security::SessionCrypto::getEnabledForRaknet(
        RBX::Security::SessionCrypto *this)
{
  RBX::Security::SessionCrypto::CryptoFormat result; // al

  result = this->rakFormat;
  if ( result )
    return ~result >> 7;
  return result;
}

std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::encryptString(
        RBX::Security::SessionCrypto *this,
        std::optional<std::string > *result,
        const std::string *message)
{
  unsigned __int64 Mysize; // rax
  RBX::ArrayView<unsigned char> v6; // [rsp+20h] [rbp-18h] BYREF

  Mysize = message->_Mypair._Myval2._Mysize;
  if ( message->_Mypair._Myval2._Myres >= 0x10 )
    message = message->_Mypair._Myval2._Bx._Ptr;
  v6.buffer = message;
  v6.length = Mysize;
  RBX::Security::SessionCrypto::encryptData(this, result, &v6);
  return result;
}

bool __fastcall RBX::Security::SessionCrypto::encryptRakDataInPlace(
        RBX::Security::SessionCrypto *this,
        RBX::MutableArrayView<unsigned char> *messageToBox)
{
  unsigned __int64 length; // r9
  unsigned __int64 v4; // r9
  bool isServer; // cl
  const unsigned __int8 *buffer; // r11
  unsigned __int8 *v7; // r8
  int (__fastcall *v8)(unsigned __int8 *, unsigned __int8 *, unsigned __int64 *, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, const unsigned __int8 *, const unsigned __int8 *); // r10
  __int64 v9; // rax
  unsigned __int64 macLen; // [rsp+68h] [rbp+10h] BYREF

  length = messageToBox->length;
  if ( length < 0x12 || this->isError || !this->isSessionReady )
    return 0;
  v4 = length - 18;
  isServer = this->isServer;
  buffer = messageToBox->buffer;
  v7 = &messageToBox->buffer[v4];
  qmemcpy(v7, "UniqueNumbeR", 12);
  *v7 = _InterlockedExchangeAdd64(&this->txRakNonce, 1uLL);
  v8 = crypto_aead_chacha20poly1305_ietf_encrypt_detached;
  if ( (this->rakFormat & 2) != 0 )
    v8 = crypto_aead_aes256gcm_encrypt_detached;
  v9 = 96LL;
  if ( !isServer )
    v9 = 64LL;
  return v8(buffer, v7 + 2, &macLen, buffer, v4, 0LL, 0LL, 0LL, v7, this + v9) == 0;
}

std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::encryptData(
        RBX::Security::SessionCrypto *this,
        std::optional<std::string > *result,
        RBX::ArrayView<unsigned char> *message)
{
  unsigned __int64 v6; // rsi
  std::optional<std::string > *p_box; // r10
  char *Ptr; // rcx
  unsigned __int64 Myres; // rdx
  __int64 v10; // r9
  const unsigned __int8 *k; // r9
  char *v12; // r8
  bool Has_value; // al
  unsigned __int64 v14; // rdx
  char *v16; // rax
  unsigned __int8 *m[2]; // [rsp+60h] [rbp-19h]
  __int128 v18; // [rsp+70h] [rbp-9h]
  __int128 v19; // [rsp+80h] [rbp+7h]
  std::optional<std::string > box; // [rsp+90h] [rbp+17h] BYREF
  unsigned __int64 maclen_p; // [rsp+F8h] [rbp+7Fh] BYREF

  *&v18 = 0LL;
  *&v19 = 0LL;
  v6 = 15LL;
  *(&v19 + 1) = 15LL;
  *&box._Dummy = v18;
  *&box._Value._Mypair._Myval2._Mysize = v19;
  box._Has_value = 1;
  std::string::resize(&box, message->length + 28, 0);
  p_box = &box;
  Ptr = box._Value._Mypair._Myval2._Bx._Ptr;
  Myres = box._Value._Mypair._Myval2._Myres;
  if ( box._Value._Mypair._Myval2._Myres >= 0x10 )
    p_box = box._Value._Mypair._Myval2._Bx._Ptr;
  *m = *message;
  if ( !this->isError && this->isSessionReady )
  {
    v10 = 96LL;
    if ( !this->isServer )
      v10 = 64LL;
    k = this + v10;
    if ( box._Value._Mypair._Myval2._Mysize == m[1] + 28 )
    {
      v12 = &p_box->_Value._Mypair._Myval2._Bx._Buf[m[1]];
      *v12 = std::_Ref_count_obj2<std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>,std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>)>,std::function<void (std::string)>)>>::`vftable'[4]
           + _InterlockedExchangeAdd64(&this->appNonce, 1uLL);
      *(v12 + 2) = 1919246957;
      if ( !crypto_aead_chacha20poly1305_ietf_encrypt_detached(
              p_box,
              &p_box->_Value._Mypair._Myval2._Bx._Buf[m[1] + 12],
              &maclen_p,
              m[0],
              m[1],
              0LL,
              0LL,
              0LL,
              &p_box->_Value._Mypair._Myval2._Bx._Buf[m[1]],
              k) )
      {
        result->_Has_value = 0;
        Has_value = box._Has_value;
        if ( box._Has_value )
        {
          *&result->_Dummy = *&box._Dummy;
          *&result->_Value._Mypair._Myval2._Mysize = *&box._Value._Mypair._Myval2._Mysize;
          box._Value._Mypair._Myval2._Mysize = 0LL;
          box._Value._Mypair._Myval2._Myres = 15LL;
          box._Value._Mypair._Myval2._Bx._Buf[0] = 0;
          result->_Has_value = 1;
        }
        else
        {
          v6 = box._Value._Mypair._Myval2._Myres;
        }
        if ( Has_value && v6 >= 0x10 )
        {
          v14 = v6 + 1;
          Ptr = box._Value._Mypair._Myval2._Bx._Ptr;
          if ( v6 + 1 < 0x1000
            || (v14 = v6 + 40,
                Ptr = *(box._Value._Mypair._Myval2._Bx._Ptr - 1),
                (box._Value._Mypair._Myval2._Bx._Ptr - Ptr - 8) <= 0x1F) )
          {
LABEL_16:
            operator delete(Ptr, v14);
            return result;
          }
LABEL_23:
          _invalid_parameter_noinfo_noreturn();
        }
        return result;
      }
      Myres = box._Value._Mypair._Myval2._Myres;
      Ptr = box._Value._Mypair._Myval2._Bx._Ptr;
    }
  }
  result->_Has_value = 0;
  if ( box._Has_value && Myres >= 0x10 )
  {
    v14 = Myres + 1;
    v16 = Ptr;
    if ( v14 < 0x1000 )
      goto LABEL_16;
    v14 += 39LL;
    Ptr = *(Ptr - 1);
    if ( (v16 - Ptr - 8) <= 0x1F )
      goto LABEL_16;
    goto LABEL_23;
  }
  return result;
}

bool __fastcall RBX::Security::SessionCrypto::earlyEncryptData(
        RBX::Security::SessionCrypto *this,
        RBX::MutableArrayView<unsigned char> *box,
        RBX::ArrayView<unsigned char> *message,
        size_t aadSize)
{
  unsigned __int8 *buffer; // rbx
  __int64 v8; // rsi
  const unsigned __int8 *ad; // rdi
  const unsigned __int8 *k; // rsi
  unsigned __int64 length; // r10
  unsigned __int8 *npub; // [rsp+40h] [rbp-38h]
  unsigned __int64 macLen; // [rsp+80h] [rbp+8h] BYREF

  if ( this->isError || !this->isEarlySessionReady )
    return 0;
  buffer = box->buffer;
  v8 = 160LL;
  ad = message->buffer;
  if ( !this->isServer )
    v8 = 128LL;
  k = &this->keyExchangeKeys._Mypair._Myval2->publicEphemeralKey._Elems[v8];
  memcpy_0(buffer, ad, aadSize);
  length = message->length;
  npub = &buffer[length];
  *npub = std::_Ref_count_obj2<std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>,std::function<void (std::shared_ptr<RBX::Reflection::Tuple const>)>,std::function<void (std::string)>)>>::`vftable'[4]
        + _InterlockedExchangeAdd64(&this->appNonce, 1uLL);
  *(npub + 2) = 1919246957;
  return !crypto_aead_chacha20poly1305_ietf_encrypt_detached(
            &buffer[aadSize],
            npub + 12,
            &macLen,
            &ad[aadSize],
            length - aadSize,
            ad,
            aadSize,
            0LL,
            npub,
            k)
      && macLen == 16;
}

bool __fastcall RBX::Security::SessionCrypto::earlyDecryptData(
        RBX::Security::SessionCrypto *this,
        RBX::MutableArrayView<unsigned char> *message,
        RBX::ArrayView<unsigned char> *box,
        size_t aadSize)
{
  unsigned __int8 *buffer; // rbx
  __int64 v7; // rsi
  const unsigned __int8 *ad; // rdi
  const unsigned __int8 *k; // rsi

  if ( this->isError || !this->isEarlySessionReady )
    return 0;
  buffer = message->buffer;
  v7 = 128LL;
  if ( !this->isServer )
    v7 = 160LL;
  ad = box->buffer;
  k = &this->keyExchangeKeys._Mypair._Myval2->publicEphemeralKey._Elems[v7];
  memcpy_0(buffer, box->buffer, aadSize);
  return !crypto_aead_chacha20poly1305_ietf_decrypt_detached(
            &buffer[aadSize],
            0LL,
            &ad[aadSize],
            message->length - aadSize,
            &ad[message->length + 12],
            ad,
            aadSize,
            &ad[message->length],
            k);
}

std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::decryptString(
        RBX::Security::SessionCrypto *this,
        std::optional<std::string > *result,
        const std::string *box)
{
  unsigned __int64 Mysize; // rax
  RBX::ArrayView<unsigned char> v6; // [rsp+20h] [rbp-18h] BYREF

  Mysize = box->_Mypair._Myval2._Mysize;
  if ( box->_Mypair._Myval2._Myres >= 0x10 )
    box = box->_Mypair._Myval2._Bx._Ptr;
  v6.buffer = box;
  v6.length = Mysize;
  RBX::Security::SessionCrypto::decryptData(this, result, &v6);
  return result;
}

char __fastcall RBX::Security::SessionCrypto::decryptRakDataInPlace(
        RBX::Security::SessionCrypto *this,
        RBX::MutableArrayView<unsigned char> *boxToMessage)
{
  unsigned __int64 length; // r8
  unsigned __int64 v4; // r9
  const unsigned __int8 *buffer; // r10
  int (__fastcall *v6)(unsigned __int8 *, unsigned __int8 *, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, const unsigned __int8 *, unsigned __int64, const unsigned __int8 *, const unsigned __int8 *); // rbp
  int v7; // edi
  __int64 v8; // rsi
  int v9; // edi

  length = boxToMessage->length;
  if ( length < 0x12 )
    return 0;
  buffer = boxToMessage->buffer;
  if ( this->isError || !this->isSessionReady )
    return 0;
  v6 = crypto_aead_chacha20poly1305_ietf_decrypt_detached;
  v4 = length - 18;
  if ( (this->rakFormat & 2) != 0 )
    v6 = crypto_aead_aes256gcm_decrypt_detached;
  v7 = *&buffer[v4];
  v8 = *&buffer[v4];
  if ( (v6)(buffer, 0LL, buffer) )
    return 0;
  v9 = v7 - LOWORD(this->rxRakNonce);
  if ( v9 >= -32768 )
  {
    if ( v9 > 0 )
    {
      this->rxRakNonce &= 0xFFFFFFFFFFFF0000uLL;
      this->rxRakNonce |= v8;
    }
    return 1;
  }
  else
  {
    this->rxRakNonce = v8 | (this->rxRakNonce + 0x10000) & 0xFFFFFFFFFFFF0000uLL;
    return 1;
  }
}

// Hidden C++ exception states: #wind=1
std::optional<std::string > *__fastcall RBX::Security::SessionCrypto::decryptData(
        RBX::Security::SessionCrypto *this,
        std::optional<std::string > *result,
        RBX::ArrayView<unsigned char> *box)
{
  unsigned __int64 length; // rax
  unsigned __int64 v7; // r14
  std::optional<std::string > *p_message; // r11
  char *Ptr; // rcx
  unsigned __int64 Myres; // rdx
  __int64 v11; // rax
  bool Has_value; // al
  unsigned __int64 v13; // rdx
  char *v15; // rax
  unsigned __int8 *c[2]; // [rsp+50h] [rbp-9h]
  unsigned __int8 *ca[2]; // [rsp+50h] [rbp-9h]
  __int128 v18; // [rsp+60h] [rbp+7h]
  std::optional<std::string > message; // [rsp+70h] [rbp+17h] BYREF

  length = box->length;
  if ( length < 0x1C )
  {
    result->_Has_value = 0;
    return result;
  }
  c[0] = 0LL;
  *&v18 = 0LL;
  *(&v18 + 1) = 15LL;
  *&message._Dummy = *c;
  *&message._Value._Mypair._Myval2._Mysize = v18;
  message._Has_value = 1;
  v7 = length - 28;
  std::string::resize(&message, length - 28, 0);
  p_message = &message;
  Ptr = message._Value._Mypair._Myval2._Bx._Ptr;
  Myres = message._Value._Mypair._Myval2._Myres;
  if ( message._Value._Mypair._Myval2._Myres >= 0x10 )
    p_message = message._Value._Mypair._Myval2._Bx._Ptr;
  *ca = *box;
  if ( !this->isError && this->isSessionReady && v7 == ca[1] - 28 && ca[1] >= 0x1C )
  {
    v11 = 64LL;
    if ( !this->isServer )
      v11 = 96LL;
    if ( !crypto_aead_chacha20poly1305_ietf_decrypt_detached(
            p_message,
            0LL,
            ca[0],
            v7,
            &ca[0][v7 + 12],
            0LL,
            0LL,
            &ca[0][v7],
            this + v11) )
    {
      result->_Has_value = 0;
      Has_value = message._Has_value;
      if ( message._Has_value )
      {
        *&result->_Dummy = *&message._Dummy;
        *&result->_Value._Mypair._Myval2._Mysize = *&message._Value._Mypair._Myval2._Mysize;
        *&message._Value._Mypair._Myval2._Mysize = _mm_load_si128(&_xmm);
        message._Value._Mypair._Myval2._Bx._Buf[0] = 0;
        result->_Has_value = 1;
      }
      if ( Has_value && message._Value._Mypair._Myval2._Myres >= 0x10 )
      {
        v13 = message._Value._Mypair._Myval2._Myres + 1;
        Ptr = message._Value._Mypair._Myval2._Bx._Ptr;
        if ( message._Value._Mypair._Myval2._Myres + 1 < 0x1000
          || (v13 = message._Value._Mypair._Myval2._Myres + 40,
              Ptr = *(message._Value._Mypair._Myval2._Bx._Ptr - 1),
              (message._Value._Mypair._Myval2._Bx._Ptr - Ptr - 8) <= 0x1F) )
        {
LABEL_18:
          operator delete(Ptr, v13);
          return result;
        }
LABEL_25:
        _invalid_parameter_noinfo_noreturn();
      }
      return result;
    }
    Myres = message._Value._Mypair._Myval2._Myres;
    Ptr = message._Value._Mypair._Myval2._Bx._Ptr;
  }
  result->_Has_value = 0;
  if ( message._Has_value && Myres >= 0x10 )
  {
    v13 = Myres + 1;
    v15 = Ptr;
    if ( v13 < 0x1000 )
      goto LABEL_18;
    v13 += 39LL;
    Ptr = *(Ptr - 1);
    if ( (v15 - Ptr - 8) <= 0x1F )
      goto LABEL_18;
    goto LABEL_25;
  }
  return result;
}

void __fastcall RBX::Security::SessionCrypto::SessionCrypto(RBX::Security::SessionCrypto *this)
{
  this->__vftable = RBX::Security::SessionCrypto::`vftable';
  this->appNonce._Storage._Value = 0LL;
  this->txRakNonce._Storage._Value = 0LL;
  this->keyExchangeKeys._Mypair._Myval2 = 0LL;
  *&this->isServer = 0;
  this->rakFormat = NoCrypto;
  this->earlyAuthData._Ptr = 0LL;
  this->earlyAuthData._Rep = 0LL;
  this->rxRakNonce = 0x754E657571696E55LL;
  _InterlockedExchange64(&this->txRakNonce, 0x754E657571696E55LL);
}

RBX::Security::SessionCrypto *__fastcall RBX::Security::SessionCrypto::`scalar deleting destructor'(
        RBX::Security::SessionCrypto *this,
        char a2)
{
  RBX::Security::SessionCrypto::~SessionCrypto(this);
  if ( (a2 & 1) != 0 )
    operator delete(this, 0x80uLL);
  return this;
}

void __fastcall RBX::Security::SessionCrypto::KeyExchangeKeys::~KeyExchangeKeys(
        RBX::Security::SessionCrypto::KeyExchangeKeys *this)
{
  sodium_memzero(&this->secretEphemeralKey, 0x20uLL);
  sodium_memzero(&this->publicEarlyKey, 0x20uLL);
  sodium_memzero(&this->secretEarlyKey, 0x20uLL);
  sodium_memzero(&this->earlySessionKeyClientToServer, 0x20uLL);
  sodium_memzero(&this->earlySessionKeyServerToClient, 0x20uLL);
}

FF enum __shex RBX::Security::SessionCrypto::CryptoFormat : __int8
FF {                                       // XREF: RBX::Security::SessionCrypto/r
FF     NoCrypto                 = 0x0,
FF     ChaCha20Poly1305Ietf     = 0x1,
FF     Aes256Gcm                = 0x2,
FF     TestMask                 = -0x80,
FF     TestChaCha20Poly1305Ietf = -0x7F,
FF     TestAes256Gcm            = -0x7E,
FF };

00000000 struct __cppobj RBX::Security::SessionCrypto::KeyExchangeKeys // sizeof=0xE0
00000000 {
00000000     std::array<unsigned char,32> publicEphemeralKey;
00000020     std::array<unsigned char,32> secretEphemeralKey;
00000040     std::array<unsigned char,32> publicEarlyKey;
00000060     std::array<unsigned char,32> secretEarlyKey;
00000080     std::array<unsigned char,32> earlySessionKeyClientToServer;
000000A0     std::array<unsigned char,32> earlySessionKeyServerToClient;
000000C0     std::array<unsigned char,32> peerPublicEphemeralKey;
000000E0 };

00000000 struct __cppobj __declspec(align(8)) RBX::Security::EarlyAuthData // sizeof=0x48
00000000 {
00000000     std::string preauthBlob;
00000020     std::string authBlob;
00000040     unsigned __int8 authVersion;
00000041     // padding byte
00000042     // padding byte
00000043     // padding byte
00000044     // padding byte
00000045     // padding byte
00000046     // padding byte
00000047     // padding byte
00000048 };

00000000 struct __cppobj std::_Ptr_base<RBX::Security::EarlyAuthData> // sizeof=0x10
00000000 {                                       // XREF: std::shared_ptr<RBX::Security::EarlyAuthData>/r
00000000     RBX::Security::EarlyAuthData *_Ptr; // XREF: RBX::Network::Client::setTicket(std::string const &):loc_1411932AA/w
00000008     std::_Ref_count_base *_Rep;         // XREF: RBX::Network::Client::setTicket(std::string const &)+11F/w
00000008                                         // RakNet::RakPeer::processRbxOpenRequest2(uchar const *,unsigned __int64,RakNet::SystemAddress const &,RakNet::SystemAddress const &,std::shared_ptr<RakNet::RakNetSocket> &,ushort,RBX::StringView)+8C/w ...
00000010 };

 00000000 struct __cppobj RBX::Security::SessionCrypto // sizeof=0x80
00000000 {                                       // XREF: RBX::Security::RakPeerCrypto/r
00000000                                         // RBX::Security::HeartbeatBlobCrypto/r
00000000     RBX::Security::SessionCrypto_vtbl *__vftable;
00000008     std::atomic<unsigned __int64> appNonce;
00000010     std::atomic<unsigned __int64> txRakNonce;
00000018     unsigned __int64 rxRakNonce;
00000020     std::unique_ptr<RBX::Security::SessionCrypto::KeyExchangeKeys> keyExchangeKeys;
00000028     bool isServer;
00000029     bool isEarlySessionReady;
0000002A     bool isSessionReady;
0000002B     bool isError;
0000002C     RBX::Security::SessionCrypto::CryptoFormat rakFormat;
0000002D     // padding byte
0000002E     // padding byte
0000002F     // padding byte
00000030     std::shared_ptr<RBX::Security::EarlyAuthData> earlyAuthData;
00000040     std::array<unsigned char,32> sessionKeyClientToServer;
00000060     std::array<unsigned char,32> sessionKeyServerToClient;
00000080 };

Using this information. Write a session_crypto in rust. A full implementation. Reverse engineer the psuedocode and use anything to help you.