Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (Zephyr)
  • No Skin
Collapse
RipperStore Logo
  1. Home
  2. Assets
  3. Looking for...
  4. Worlds
  5. Nero's MMD World VIP and 18+ Code

Nero's MMD World VIP and 18+ Code

Scheduled Pinned Locked Moved Unsolved Worlds
codemmd
213 Posts 61 Posters 99.8k Views 138 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S sillystarfish

    hello does anyone knows the code?

    mischievousM
    mischievousM
    mischievous
    wrote on last edited by
    #154

    @sillystarfish codes are different for everyone now so they cant be handed out anymore

    sick of generic egirls and eboys, where's all the unique avatars

    1 Reply Last reply
    1
    • LucianL
      LucianL
      Lucian
      wrote on last edited by Lucian
      #155

      (updated August 9th 2025)
      Premium code override: 744036
      Spicy code override: 851420

      If they no longer work/patched, do let me know, and I will create a small script to generate them with your username

      Codes are patched, so I will be working on a script to generate your own codes, give me a few days

      1 Reply Last reply
      3
      • LucianL
        LucianL
        Lucian
        wrote on last edited by
        #156

        the udon code use a constant string, followed by the date of the month, with the vrchat username, followed by either miku or bunda for premiun and spicy, then end with the # character.

        this entire line combo is then hashed with a SHA256 UTF8 calculation.
        Finally you strip away all the letter and keep only the numbers.

        The result is a line of numbers, you only take the first 6 numbers, and there you are, you have your monthly access code.

        I am pretty sure i can make a script to make it happen

        S A 2 Replies Last reply
        😦 👍
        8
        • That1GuyT
          That1GuyT
          That1Guy
          wrote on last edited by
          #157

          this sounds awesome.
          goodluck to your success.

          1 Reply Last reply
          1
          • LucianL Lucian

            the udon code use a constant string, followed by the date of the month, with the vrchat username, followed by either miku or bunda for premiun and spicy, then end with the # character.

            this entire line combo is then hashed with a SHA256 UTF8 calculation.
            Finally you strip away all the letter and keep only the numbers.

            The result is a line of numbers, you only take the first 6 numbers, and there you are, you have your monthly access code.

            I am pretty sure i can make a script to make it happen

            S
            S
            supernova1980
            wrote on last edited by
            #158

            @Lucian What's the constant string? Where can I get it?

            LucianL 1 Reply Last reply
            2
            • S supernova1980

              @Lucian What's the constant string? Where can I get it?

              LucianL
              LucianL
              Lucian
              wrote on last edited by
              #159

              @supernova1980

              public class udoncrashtest : UdonSharp.UdonSharpBehaviour
              {
              private System.String __lcl_hashKey_SystemString_0 = null;
              private System.String __intnl_SystemString_1 = null;
              private System.Object __intnl_SystemObject_0 = null;
              private System.Char __intnl_SystemChar_1 =  ;
              private System.String __const_SystemString_0 = "";
              private System.Boolean __0_isSpicy__param = False;
              private System.String __0___0__GenerateCode__ret = null;
              private System.UInt32 __gintnl_SystemUInt32_4 = 2184;
              private System.UInt32 __gintnl_SystemUInt32_1 = 672;
              private System.UInt32 __gintnl_SystemUInt32_0 = 40;
              private System.UInt32 __gintnl_SystemUInt32_3 = 952;
              private System.UInt32 __gintnl_SystemUInt32_2 = 812;
              private System.Boolean __const_SystemBoolean_0 = False;
              private System.Boolean __const_SystemBoolean_1 = True;
              private System.String __lcl_formattedDate_SystemString_0 = null;
              private System.DateTime __0___0_GetLastDayOfMonth__ret = 1/1/0001 12:00:00 AM;
              private System.String __const_SystemString_5 = "dd/MM/yyyy";
              private System.String __intnl_SystemString_6 = null;
              private System.Char[] __intnl_SystemCharArray_0 = null;
              private System.Char[] __intnl_SystemCharArray_1 = null;
              private System.String __const_SystemString_10 = "__0___0_SHA256_UTF8__ret";
              private System.String __const_SystemString_11 = "MM";
              private System.Int64 __refl_typeid = -8934105941663349694;
              private System.UInt32 __const_SystemUInt32_0 = 4294967295;
              private System.String premiumCode = null;
              private System.String __intnl_SystemString_3 = null;
              private System.String __lcl_codeKey_SystemString_0 = null;
              private System.String __lcl_finalCode_SystemString_0 = null;
              private System.String __const_SystemString_2 = "bundabunda";
              private System.Boolean __0___0_IsValidSpicyCode__ret = False;
              private System.String __intnl_SystemString_0 = null;
              private System.Char __intnl_SystemChar_0 =  ;
              private System.String __const_SystemString_7 = "7oXtAXHz";
              private System.String __lcl_hash64_SystemString_0 = null;
              private System.DateTime __0_dateTime__param = 1/1/0001 12:00:00 AM;
              private System.String __1_code__param = null;
              private System.DateTime __lcl_dt_SystemDateTime_0 = 1/1/0001 12:00:00 AM;
              private System.UInt32 __intnl_returnJump_SystemUInt32_0 = 0;
              private VRC.SDKBase.VRCPlayerApi _playerLocal = null;
              private System.String __const_SystemString_4 = "bunda";
              private System.Int32 __lcl_i_SystemInt32_0 = 0;
              private System.String __intnl_SystemString_5 = null;
              private System.String __const_SystemString_9 = "__0_SHA256_UTF8";
              private System.String __refl_typename = "nerokeypad.KeypadPrivateCodesManager";
              private System.Int32 __intnl_SystemInt32_1 = 0;
              private System.Int32 __intnl_SystemInt32_0 = 0;
              private System.Int32 __intnl_SystemInt32_3 = 0;
              private System.Int32 __intnl_SystemInt32_2 = 0;
              private System.Int32 __intnl_SystemInt32_5 = 0;
              private System.Int32 __intnl_SystemInt32_4 = 0;
              private System.Int32 __intnl_SystemInt32_7 = 0;
              private System.Int32 __intnl_SystemInt32_6 = 0;
              private System.String __intnl_SystemString_2 = null;
              private System.DateTime __intnl_SystemDateTime_0 = 1/1/0001 12:00:00 AM;
              private System.String __const_SystemString_1 = "miku";
              private System.String __0_name__param = null;
              private System.Boolean __0_isRetry__param = False;
              private System.String __0_code__param = null;
              private System.DateTime __0_date__param = 1/1/0001 12:00:00 AM;
              private System.String __const_SystemString_6 = "#";
              private System.String spicyCode = null;
              private System.Int32 __const_SystemInt32_1 = 1;
              private System.Int32 __const_SystemInt32_0 = 0;
              private System.Int32 __const_SystemInt32_3 = 4;
              private System.Int32 __const_SystemInt32_2 = 5;
              private System.Int32 __const_SystemInt32_4 = 6;
              public VRC.Udon.UdonBehaviour _hashLibrary;
              private System.Boolean __0___0_IsValidPremiumCode__ret = False;
              private System.Boolean __intnl_SystemBoolean_0 = False;
              private System.Boolean __intnl_SystemBoolean_1 = False;
              private System.Boolean __intnl_SystemBoolean_2 = False;
              private System.Boolean __intnl_SystemBoolean_3 = False;
              private System.Boolean __intnl_SystemBoolean_4 = False;
              private System.String __intnl_SystemString_4 = null;
              private System.String __const_SystemString_3 = "mikumiku";
              private System.String __const_SystemString_8 = "__3_text__param";
              
              
              public void _start()
              {
              _playerLocal = get_LocalPlayer();
              UNDEF_99797_992();
              }
              public void __0_IsValidPremiumCode()
              {
              __intnl_SystemBoolean_0 = __const_SystemString_0 == premiumCode;
              if (__intnl_SystemBoolean_0)
              {
              __0___0_IsValidPremiumCode__ret = __const_SystemBoolean_0;
              return;
              }
              __0___0_IsValidPremiumCode__ret = __0_code__param == premiumCode;
              return;
              }
              public void __0_IsValidSpicyCode()
              {
              __intnl_SystemBoolean_1 = __const_SystemString_0 == spicyCode;
              if (__intnl_SystemBoolean_1)
              {
              __0___0_IsValidSpicyCode__ret = __const_SystemBoolean_0;
              return;
              }
              __0___0_IsValidSpicyCode__ret = __1_code__param == spicyCode;
              return;
              }
              private void __0_GetLastDayOfMonth()
              {
              __intnl_SystemInt32_0 = __0_dateTime__param.get_Year();
              __intnl_SystemInt32_1 = __0_dateTime__param.get_Month();
              __intnl_SystemInt32_2 = __0_dateTime__param.get_Year();
              __intnl_SystemInt32_3 = __0_dateTime__param.get_Month();
              __intnl_SystemInt32_4 = DaysInMonth(__intnl_SystemInt32_3, __intnl_SystemInt32_2);
              __0___0_GetLastDayOfMonth__ret = ctor(__intnl_SystemInt32_4, __intnl_SystemInt32_1, __intnl_SystemInt32_0);
              return;
              }
              private void UNDEF_99797_992()
              {
              __intnl_SystemDateTime_0 = get_Now();
              __0_dateTime__param = __intnl_SystemDateTime_0;
              __0_GetLastDayOfMonth();
              __lcl_dt_SystemDateTime_0 = __0___0_GetLastDayOfMonth__ret;
              __intnl_SystemString_0 = _playerLocal.get_displayName();
              __0_name__param = __intnl_SystemString_0;
              __0_date__param = __lcl_dt_SystemDateTime_0;
              __0_isSpicy__param = __const_SystemBoolean_0;
              __0_isRetry__param = __const_SystemBoolean_0;
              __0__GenerateCode();
              premiumCode = __0___0__GenerateCode__ret;
              __intnl_SystemString_1 = _playerLocal.get_displayName();
              __0_name__param = __intnl_SystemString_1;
              __0_date__param = __lcl_dt_SystemDateTime_0;
              __0_isSpicy__param = __const_SystemBoolean_1;
              __0_isRetry__param = __const_SystemBoolean_0;
              __0__GenerateCode();
              spicyCode = __0___0__GenerateCode__ret;
              }
              private void __0__GenerateCode()
              {
              for (;;)
              {
              __lcl_hashKey_SystemString_0 = __const_SystemString_1;
              if (__0_isRetry__param)
              {
              if (__0_isSpicy__param)
              {
              __lcl_hashKey_SystemString_0 = __const_SystemString_2;
              }
              else
              {
              __lcl_hashKey_SystemString_0 = __const_SystemString_3;
              }
              }
              else
              {
              if (__0_isSpicy__param)
              {
              __lcl_hashKey_SystemString_0 = __const_SystemString_4;
              }
              }
              __lcl_formattedDate_SystemString_0 = __0_date__param.ToString(__const_SystemString_5);
              __intnl_SystemString_2 = op_Addition(__0_name__param, __lcl_hashKey_SystemString_0);
              __intnl_SystemString_3 = op_Addition(__const_SystemString_6, __intnl_SystemString_2);
              __intnl_SystemString_4 = op_Addition(__lcl_formattedDate_SystemString_0, __intnl_SystemString_3);
              __lcl_codeKey_SystemString_0 = op_Addition(__const_SystemString_7, __intnl_SystemString_4);
              _hashLibrary.SetProgramVariable(__lcl_codeKey_SystemString_0, __const_SystemString_8);
              _hashLibrary.SendCustomEvent(__const_SystemString_9);
              __intnl_SystemObject_0 = _hashLibrary.GetProgramVariable(__const_SystemString_10);
              __intnl_SystemString_5 = __intnl_SystemObject_0;
              __lcl_hash64_SystemString_0 = __intnl_SystemString_5;
              __lcl_finalCode_SystemString_0 = __const_SystemString_0;
              __lcl_i_SystemInt32_0 = __const_SystemInt32_0;
              for (;;)
              {
              __intnl_SystemInt32_5 = __lcl_hash64_SystemString_0.get_Length();
              __intnl_SystemBoolean_2 = op_LessThan(__intnl_SystemInt32_5, __lcl_i_SystemInt32_0);
              if (__intnl_SystemBoolean_2)
              {
              break;
              }
              __intnl_SystemCharArray_0 = __lcl_hash64_SystemString_0.ToCharArray(__const_SystemInt32_1, __lcl_i_SystemInt32_0);
              __intnl_SystemChar_0 = __intnl_SystemCharArray_0.Get(__const_SystemInt32_0);
              __intnl_SystemBoolean_3 = IsDigit(__intnl_SystemChar_0);
              if (__intnl_SystemBoolean_3)
              {
              __intnl_SystemCharArray_1 = __lcl_hash64_SystemString_0.ToCharArray(__const_SystemInt32_1, __lcl_i_SystemInt32_0);
              __intnl_SystemChar_1 = __intnl_SystemCharArray_1.Get(__const_SystemInt32_0);
              __lcl_finalCode_SystemString_0 = Concat(__intnl_SystemChar_1, __lcl_finalCode_SystemString_0);
              }
              __lcl_i_SystemInt32_0 = op_Addition(__const_SystemInt32_1, __lcl_i_SystemInt32_0);
              }
              __intnl_SystemInt32_5 = __lcl_finalCode_SystemString_0.get_Length();
              __intnl_SystemBoolean_2 = __const_SystemInt32_2 == __intnl_SystemInt32_5;
              if (__intnl_SystemBoolean_2)
              {
              __intnl_SystemString_6 = __0_date__param.ToString(__const_SystemString_11);
              __lcl_finalCode_SystemString_0 = op_Addition(__intnl_SystemString_6, __lcl_finalCode_SystemString_0);
              }
              else
              {
              __intnl_SystemBoolean_3 = !__0_isRetry__param;
              if (__intnl_SystemBoolean_3)
              {
              __intnl_SystemInt32_6 = __lcl_finalCode_SystemString_0.get_Length();
              __intnl_SystemBoolean_3 = op_LessThanOrEqual(__const_SystemInt32_3, __intnl_SystemInt32_6);
              }
              if (__intnl_SystemBoolean_3)
              {
              __intnl_SystemString_6 = op_Addition(__0_name__param, __0_name__param);
              __0_name__param = __intnl_SystemString_6;
              __0_date__param = __0_date__param;
              __0_isSpicy__param = __0_isSpicy__param;
              __0_isRetry__param = __const_SystemBoolean_1;
              }
              __lcl_finalCode_SystemString_0 = __0___0__GenerateCode__ret;
              }
              }
              __intnl_SystemInt32_7 = __lcl_finalCode_SystemString_0.get_Length();
              __intnl_SystemBoolean_4 = op_GreaterThan(__const_SystemInt32_4, __intnl_SystemInt32_7);
              if (__intnl_SystemBoolean_4)
              {
              __lcl_finalCode_SystemString_0 = __lcl_finalCode_SystemString_0.Substring(__const_SystemInt32_4, __const_SystemInt32_0);
              }
              __0___0__GenerateCode__ret = __lcl_finalCode_SystemString_0;
              return;
              }
              }
              
              WorcestershireW 1 Reply Last reply
              1
              • LucianL Lucian

                the udon code use a constant string, followed by the date of the month, with the vrchat username, followed by either miku or bunda for premiun and spicy, then end with the # character.

                this entire line combo is then hashed with a SHA256 UTF8 calculation.
                Finally you strip away all the letter and keep only the numbers.

                The result is a line of numbers, you only take the first 6 numbers, and there you are, you have your monthly access code.

                I am pretty sure i can make a script to make it happen

                A
                A
                ArthurTheFur
                wrote on last edited by
                #160

                @Lucian Any updates on the script you are making?

                1 Reply Last reply
                0
                • LucianL Lucian

                  @supernova1980

                  public class udoncrashtest : UdonSharp.UdonSharpBehaviour
                  {
                  private System.String __lcl_hashKey_SystemString_0 = null;
                  private System.String __intnl_SystemString_1 = null;
                  private System.Object __intnl_SystemObject_0 = null;
                  private System.Char __intnl_SystemChar_1 =  ;
                  private System.String __const_SystemString_0 = "";
                  private System.Boolean __0_isSpicy__param = False;
                  private System.String __0___0__GenerateCode__ret = null;
                  private System.UInt32 __gintnl_SystemUInt32_4 = 2184;
                  private System.UInt32 __gintnl_SystemUInt32_1 = 672;
                  private System.UInt32 __gintnl_SystemUInt32_0 = 40;
                  private System.UInt32 __gintnl_SystemUInt32_3 = 952;
                  private System.UInt32 __gintnl_SystemUInt32_2 = 812;
                  private System.Boolean __const_SystemBoolean_0 = False;
                  private System.Boolean __const_SystemBoolean_1 = True;
                  private System.String __lcl_formattedDate_SystemString_0 = null;
                  private System.DateTime __0___0_GetLastDayOfMonth__ret = 1/1/0001 12:00:00 AM;
                  private System.String __const_SystemString_5 = "dd/MM/yyyy";
                  private System.String __intnl_SystemString_6 = null;
                  private System.Char[] __intnl_SystemCharArray_0 = null;
                  private System.Char[] __intnl_SystemCharArray_1 = null;
                  private System.String __const_SystemString_10 = "__0___0_SHA256_UTF8__ret";
                  private System.String __const_SystemString_11 = "MM";
                  private System.Int64 __refl_typeid = -8934105941663349694;
                  private System.UInt32 __const_SystemUInt32_0 = 4294967295;
                  private System.String premiumCode = null;
                  private System.String __intnl_SystemString_3 = null;
                  private System.String __lcl_codeKey_SystemString_0 = null;
                  private System.String __lcl_finalCode_SystemString_0 = null;
                  private System.String __const_SystemString_2 = "bundabunda";
                  private System.Boolean __0___0_IsValidSpicyCode__ret = False;
                  private System.String __intnl_SystemString_0 = null;
                  private System.Char __intnl_SystemChar_0 =  ;
                  private System.String __const_SystemString_7 = "7oXtAXHz";
                  private System.String __lcl_hash64_SystemString_0 = null;
                  private System.DateTime __0_dateTime__param = 1/1/0001 12:00:00 AM;
                  private System.String __1_code__param = null;
                  private System.DateTime __lcl_dt_SystemDateTime_0 = 1/1/0001 12:00:00 AM;
                  private System.UInt32 __intnl_returnJump_SystemUInt32_0 = 0;
                  private VRC.SDKBase.VRCPlayerApi _playerLocal = null;
                  private System.String __const_SystemString_4 = "bunda";
                  private System.Int32 __lcl_i_SystemInt32_0 = 0;
                  private System.String __intnl_SystemString_5 = null;
                  private System.String __const_SystemString_9 = "__0_SHA256_UTF8";
                  private System.String __refl_typename = "nerokeypad.KeypadPrivateCodesManager";
                  private System.Int32 __intnl_SystemInt32_1 = 0;
                  private System.Int32 __intnl_SystemInt32_0 = 0;
                  private System.Int32 __intnl_SystemInt32_3 = 0;
                  private System.Int32 __intnl_SystemInt32_2 = 0;
                  private System.Int32 __intnl_SystemInt32_5 = 0;
                  private System.Int32 __intnl_SystemInt32_4 = 0;
                  private System.Int32 __intnl_SystemInt32_7 = 0;
                  private System.Int32 __intnl_SystemInt32_6 = 0;
                  private System.String __intnl_SystemString_2 = null;
                  private System.DateTime __intnl_SystemDateTime_0 = 1/1/0001 12:00:00 AM;
                  private System.String __const_SystemString_1 = "miku";
                  private System.String __0_name__param = null;
                  private System.Boolean __0_isRetry__param = False;
                  private System.String __0_code__param = null;
                  private System.DateTime __0_date__param = 1/1/0001 12:00:00 AM;
                  private System.String __const_SystemString_6 = "#";
                  private System.String spicyCode = null;
                  private System.Int32 __const_SystemInt32_1 = 1;
                  private System.Int32 __const_SystemInt32_0 = 0;
                  private System.Int32 __const_SystemInt32_3 = 4;
                  private System.Int32 __const_SystemInt32_2 = 5;
                  private System.Int32 __const_SystemInt32_4 = 6;
                  public VRC.Udon.UdonBehaviour _hashLibrary;
                  private System.Boolean __0___0_IsValidPremiumCode__ret = False;
                  private System.Boolean __intnl_SystemBoolean_0 = False;
                  private System.Boolean __intnl_SystemBoolean_1 = False;
                  private System.Boolean __intnl_SystemBoolean_2 = False;
                  private System.Boolean __intnl_SystemBoolean_3 = False;
                  private System.Boolean __intnl_SystemBoolean_4 = False;
                  private System.String __intnl_SystemString_4 = null;
                  private System.String __const_SystemString_3 = "mikumiku";
                  private System.String __const_SystemString_8 = "__3_text__param";
                  
                  
                  public void _start()
                  {
                  _playerLocal = get_LocalPlayer();
                  UNDEF_99797_992();
                  }
                  public void __0_IsValidPremiumCode()
                  {
                  __intnl_SystemBoolean_0 = __const_SystemString_0 == premiumCode;
                  if (__intnl_SystemBoolean_0)
                  {
                  __0___0_IsValidPremiumCode__ret = __const_SystemBoolean_0;
                  return;
                  }
                  __0___0_IsValidPremiumCode__ret = __0_code__param == premiumCode;
                  return;
                  }
                  public void __0_IsValidSpicyCode()
                  {
                  __intnl_SystemBoolean_1 = __const_SystemString_0 == spicyCode;
                  if (__intnl_SystemBoolean_1)
                  {
                  __0___0_IsValidSpicyCode__ret = __const_SystemBoolean_0;
                  return;
                  }
                  __0___0_IsValidSpicyCode__ret = __1_code__param == spicyCode;
                  return;
                  }
                  private void __0_GetLastDayOfMonth()
                  {
                  __intnl_SystemInt32_0 = __0_dateTime__param.get_Year();
                  __intnl_SystemInt32_1 = __0_dateTime__param.get_Month();
                  __intnl_SystemInt32_2 = __0_dateTime__param.get_Year();
                  __intnl_SystemInt32_3 = __0_dateTime__param.get_Month();
                  __intnl_SystemInt32_4 = DaysInMonth(__intnl_SystemInt32_3, __intnl_SystemInt32_2);
                  __0___0_GetLastDayOfMonth__ret = ctor(__intnl_SystemInt32_4, __intnl_SystemInt32_1, __intnl_SystemInt32_0);
                  return;
                  }
                  private void UNDEF_99797_992()
                  {
                  __intnl_SystemDateTime_0 = get_Now();
                  __0_dateTime__param = __intnl_SystemDateTime_0;
                  __0_GetLastDayOfMonth();
                  __lcl_dt_SystemDateTime_0 = __0___0_GetLastDayOfMonth__ret;
                  __intnl_SystemString_0 = _playerLocal.get_displayName();
                  __0_name__param = __intnl_SystemString_0;
                  __0_date__param = __lcl_dt_SystemDateTime_0;
                  __0_isSpicy__param = __const_SystemBoolean_0;
                  __0_isRetry__param = __const_SystemBoolean_0;
                  __0__GenerateCode();
                  premiumCode = __0___0__GenerateCode__ret;
                  __intnl_SystemString_1 = _playerLocal.get_displayName();
                  __0_name__param = __intnl_SystemString_1;
                  __0_date__param = __lcl_dt_SystemDateTime_0;
                  __0_isSpicy__param = __const_SystemBoolean_1;
                  __0_isRetry__param = __const_SystemBoolean_0;
                  __0__GenerateCode();
                  spicyCode = __0___0__GenerateCode__ret;
                  }
                  private void __0__GenerateCode()
                  {
                  for (;;)
                  {
                  __lcl_hashKey_SystemString_0 = __const_SystemString_1;
                  if (__0_isRetry__param)
                  {
                  if (__0_isSpicy__param)
                  {
                  __lcl_hashKey_SystemString_0 = __const_SystemString_2;
                  }
                  else
                  {
                  __lcl_hashKey_SystemString_0 = __const_SystemString_3;
                  }
                  }
                  else
                  {
                  if (__0_isSpicy__param)
                  {
                  __lcl_hashKey_SystemString_0 = __const_SystemString_4;
                  }
                  }
                  __lcl_formattedDate_SystemString_0 = __0_date__param.ToString(__const_SystemString_5);
                  __intnl_SystemString_2 = op_Addition(__0_name__param, __lcl_hashKey_SystemString_0);
                  __intnl_SystemString_3 = op_Addition(__const_SystemString_6, __intnl_SystemString_2);
                  __intnl_SystemString_4 = op_Addition(__lcl_formattedDate_SystemString_0, __intnl_SystemString_3);
                  __lcl_codeKey_SystemString_0 = op_Addition(__const_SystemString_7, __intnl_SystemString_4);
                  _hashLibrary.SetProgramVariable(__lcl_codeKey_SystemString_0, __const_SystemString_8);
                  _hashLibrary.SendCustomEvent(__const_SystemString_9);
                  __intnl_SystemObject_0 = _hashLibrary.GetProgramVariable(__const_SystemString_10);
                  __intnl_SystemString_5 = __intnl_SystemObject_0;
                  __lcl_hash64_SystemString_0 = __intnl_SystemString_5;
                  __lcl_finalCode_SystemString_0 = __const_SystemString_0;
                  __lcl_i_SystemInt32_0 = __const_SystemInt32_0;
                  for (;;)
                  {
                  __intnl_SystemInt32_5 = __lcl_hash64_SystemString_0.get_Length();
                  __intnl_SystemBoolean_2 = op_LessThan(__intnl_SystemInt32_5, __lcl_i_SystemInt32_0);
                  if (__intnl_SystemBoolean_2)
                  {
                  break;
                  }
                  __intnl_SystemCharArray_0 = __lcl_hash64_SystemString_0.ToCharArray(__const_SystemInt32_1, __lcl_i_SystemInt32_0);
                  __intnl_SystemChar_0 = __intnl_SystemCharArray_0.Get(__const_SystemInt32_0);
                  __intnl_SystemBoolean_3 = IsDigit(__intnl_SystemChar_0);
                  if (__intnl_SystemBoolean_3)
                  {
                  __intnl_SystemCharArray_1 = __lcl_hash64_SystemString_0.ToCharArray(__const_SystemInt32_1, __lcl_i_SystemInt32_0);
                  __intnl_SystemChar_1 = __intnl_SystemCharArray_1.Get(__const_SystemInt32_0);
                  __lcl_finalCode_SystemString_0 = Concat(__intnl_SystemChar_1, __lcl_finalCode_SystemString_0);
                  }
                  __lcl_i_SystemInt32_0 = op_Addition(__const_SystemInt32_1, __lcl_i_SystemInt32_0);
                  }
                  __intnl_SystemInt32_5 = __lcl_finalCode_SystemString_0.get_Length();
                  __intnl_SystemBoolean_2 = __const_SystemInt32_2 == __intnl_SystemInt32_5;
                  if (__intnl_SystemBoolean_2)
                  {
                  __intnl_SystemString_6 = __0_date__param.ToString(__const_SystemString_11);
                  __lcl_finalCode_SystemString_0 = op_Addition(__intnl_SystemString_6, __lcl_finalCode_SystemString_0);
                  }
                  else
                  {
                  __intnl_SystemBoolean_3 = !__0_isRetry__param;
                  if (__intnl_SystemBoolean_3)
                  {
                  __intnl_SystemInt32_6 = __lcl_finalCode_SystemString_0.get_Length();
                  __intnl_SystemBoolean_3 = op_LessThanOrEqual(__const_SystemInt32_3, __intnl_SystemInt32_6);
                  }
                  if (__intnl_SystemBoolean_3)
                  {
                  __intnl_SystemString_6 = op_Addition(__0_name__param, __0_name__param);
                  __0_name__param = __intnl_SystemString_6;
                  __0_date__param = __0_date__param;
                  __0_isSpicy__param = __0_isSpicy__param;
                  __0_isRetry__param = __const_SystemBoolean_1;
                  }
                  __lcl_finalCode_SystemString_0 = __0___0__GenerateCode__ret;
                  }
                  }
                  __intnl_SystemInt32_7 = __lcl_finalCode_SystemString_0.get_Length();
                  __intnl_SystemBoolean_4 = op_GreaterThan(__const_SystemInt32_4, __intnl_SystemInt32_7);
                  if (__intnl_SystemBoolean_4)
                  {
                  __lcl_finalCode_SystemString_0 = __lcl_finalCode_SystemString_0.Substring(__const_SystemInt32_4, __const_SystemInt32_0);
                  }
                  __0___0__GenerateCode__ret = __lcl_finalCode_SystemString_0;
                  return;
                  }
                  }
                  
                  WorcestershireW
                  WorcestershireW
                  Worcestershire
                  wrote on last edited by
                  #161

                  @Lucian I've taken a stab at making my own script but to no avail. not sure exactly what's wrong, as every 'if' statement seems to match. Guess I'll wait to see your solution cuz now I'm hella curious as to how the hell they calculate the codes.

                  This method is hella confusing(most likely on purpose). My interpretation is: they use hash256 to hash '{fixed_value}{dd/mm/yyy}#{user_name}{salt}', and since thecall this value hash64 I assumed they encode it in base64;
                  Then iterate over the hash64 prepending only the digits, thus reversing the order;
                  If length = 5 they prepend the month in 'mm' format,else if 4 <= length(?) they rerun the function one more time, this time hashing '{fixed_value}{dd/mm/yyy}#{user_name+user_name}{salt+salt}' and again, if length = 5 prepend month in 'mm' format, if not return the code, the generated code is trimmed to 6 digits.

                  This is probably wrong, but this is the best I could do reading the code you gave

                  LucianL 1 Reply Last reply
                  2
                  • WorcestershireW
                    WorcestershireW
                    Worcestershire
                    wrote on last edited by
                    #162

                    Well, I give up XD Anyone wants the python code I created so far here it is, it doesn't seem to generate valid codes and I can't seem to figure out why. I tried to keep the structure as similar to the decompiled code as I could.

                    import datetime, calendar, hashlib, base64
                    PRE_SEED = '7oXtAXHz'
                    
                    def get_date():
                        now = datetime.datetime.now()
                        last_day = calendar.monthrange(now.year, now.month)[1]  
                        date = datetime.date(now.year, now.month, last_day)
                        return date
                    
                    def generate_code(name : str, date : datetime.datetime, is_spicy : bool, is_retry : bool):
                        hash_key = "bundabunda" if is_retry and is_spicy else \
                        "mikumiku"   if is_retry and not is_spicy else \
                        "bunda"      if not is_retry and is_spicy else \
                        "miku"
                            
                        formatted_date = date.strftime('%d/%m/%Y')
                    
                        code_key = f'{PRE_SEED}{formatted_date}#{name}{hash_key}'.encode('utf-8')
                        hash64 = hashlib.sha256(code_key).hexdigest() 
                        final_code = b''
                        for ch in hash64:
                            if ch.isdigit():
                                final_code = ch+final_code
                    
                    
                        
                    
                        if len(final_code) == 5: #This is weird because the chances of actuallt extracting 5 digits from the hash is nearly zero
                             final_code = f'{date.strftime("%m")}{final_code}'
                        if not is_retry and len(final_code) >= 4:
                            return generate_code(name * 2,date,is_spicy,True)
                            
                        return final_code[:6]
                    
                    def main():
                        player_name = input('Nome no VRChat: ')
                        date = get_date()
                        premium_code = generate_code(name=player_name,date=date,is_spicy=False,is_retry=False)
                        spicy_code = generate_code(name=player_name,date=date,is_spicy=True,is_retry=False)
                        print(f'Senha: {premium_code}\nSpicy: {spicy_code}')
                    
                    if __name__ == '__main__':
                        main()
                    
                    1 Reply Last reply
                    2
                    • WorcestershireW Worcestershire

                      @Lucian I've taken a stab at making my own script but to no avail. not sure exactly what's wrong, as every 'if' statement seems to match. Guess I'll wait to see your solution cuz now I'm hella curious as to how the hell they calculate the codes.

                      This method is hella confusing(most likely on purpose). My interpretation is: they use hash256 to hash '{fixed_value}{dd/mm/yyy}#{user_name}{salt}', and since thecall this value hash64 I assumed they encode it in base64;
                      Then iterate over the hash64 prepending only the digits, thus reversing the order;
                      If length = 5 they prepend the month in 'mm' format,else if 4 <= length(?) they rerun the function one more time, this time hashing '{fixed_value}{dd/mm/yyy}#{user_name+user_name}{salt+salt}' and again, if length = 5 prepend month in 'mm' format, if not return the code, the generated code is trimmed to 6 digits.

                      This is probably wrong, but this is the best I could do reading the code you gave

                      LucianL
                      LucianL
                      Lucian
                      wrote on last edited by
                      #163

                      @Worcestershire yeah, i am currently working on getting a better outcome on the script.

                      So far, I am getting the exact code within vrchat, but unable to replicate it within python env.

                      So I got an idea, I am going to use the file structures instead so it will utilize the udonsharp code directly.

                      it might take a few days

                      WorcestershireW 2 Replies Last reply
                      👍
                      3
                      • NightFallen4YouN
                        NightFallen4YouN
                        NightFallen4You
                        wrote on last edited by
                        #164

                        best of luck to you - even if it doesn't work, we're all grateful for the effort ❤

                        the brainrot consumes

                        1 Reply Last reply
                        2
                        • LucianL Lucian

                          @Worcestershire yeah, i am currently working on getting a better outcome on the script.

                          So far, I am getting the exact code within vrchat, but unable to replicate it within python env.

                          So I got an idea, I am going to use the file structures instead so it will utilize the udonsharp code directly.

                          it might take a few days

                          WorcestershireW
                          WorcestershireW
                          Worcestershire
                          wrote on last edited by
                          #165

                          @Lucian I'm actually really curious about what's the discrepancy. looking forward to your code. Good Luck 🙂

                          1 Reply Last reply
                          1
                          • RoseVelvetteR
                            RoseVelvetteR
                            RoseVelvette
                            wrote on last edited by
                            #166

                            Bump for number code please I need it

                            1 Reply Last reply
                            1
                            • SkeebooS
                              SkeebooS
                              Skeeboo
                              wrote on last edited by
                              #167

                              I believe in y'all o7

                              i don't "trade" models. trading is stupid.
                              share with everyone or shut the hell up.

                              1 Reply Last reply
                              1
                              • L
                                L
                                Layui
                                wrote on last edited by
                                #168

                                someone is selling the codes on discord already so it's possible.
                                only the persistence does not work so you need to put the code always in.

                                1 Reply Last reply
                                0
                                • LucianL Lucian

                                  @Worcestershire yeah, i am currently working on getting a better outcome on the script.

                                  So far, I am getting the exact code within vrchat, but unable to replicate it within python env.

                                  So I got an idea, I am going to use the file structures instead so it will utilize the udonsharp code directly.

                                  it might take a few days

                                  WorcestershireW
                                  WorcestershireW
                                  Worcestershire
                                  wrote on last edited by
                                  #169

                                  @Lucian Any progress? couldn't get my python script to work so I gave up.

                                  1 Reply Last reply
                                  0
                                  • R
                                    R
                                    RedCob
                                    wrote on last edited by RedCob
                                    #170

                                    I'm suspecting that they're using a nonstandard SHA256-UTF8 implementation. @Lucian Is there a way for you to obtain the Udon implementation of the hashing algorithm?

                                    WorcestershireW 1 Reply Last reply
                                    1
                                    • R RedCob

                                      I'm suspecting that they're using a nonstandard SHA256-UTF8 implementation. @Lucian Is there a way for you to obtain the Udon implementation of the hashing algorithm?

                                      WorcestershireW
                                      WorcestershireW
                                      Worcestershire
                                      wrote on last edited by
                                      #171

                                      @RedCob If my reading of the code @Lucian pasted here is correct they're using the vrchat-udon-hashlib. Both call the lib using "_hashLibrary".

                                      Here's the code of the hashing it uses if it's of any help:

                                      // -*- coding: utf-8 -*-
                                      /*
                                      MIT License
                                      
                                      Copyright (c) 2021-present Devon (Gorialis) R
                                      
                                      Permission is hereby granted, free of charge, to any person obtaining a copy
                                      of this software and associated documentation files (the "Software"), to deal
                                      in the Software without restriction, including without limitation the rights
                                      to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                                      copies of the Software, and to permit persons to whom the Software is
                                      furnished to do so, subject to the following conditions:
                                      
                                      The above copyright notice and this permission notice shall be included in all
                                      copies or substantial portions of the Software.
                                      
                                      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                                      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                                      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                                      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                                      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                                      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
                                      SOFTWARE.
                                      
                                      */
                                      
                                      using System;
                                      using System.Linq;
                                      using UnityEngine;
                                      using UdonSharp;
                                      
                                      #if !COMPILER_UDONSHARP && UNITY_EDITOR
                                      using UnityEditor;
                                      using UdonSharpEditor;
                                      #endif
                                      
                                      
                                      public class UdonHashLib : UdonSharpBehaviour
                                      {
                                          // Udon does not support UTF-8 or expose System.Text.Encoding so we must implement this ourselves
                                          private byte[] ToUTF8(char[] characters)
                                          {
                                              byte[] buffer = new byte[characters.Length * 4];
                                      
                                              int writeIndex = 0;
                                              for (int i = 0; i < characters.Length; i++)
                                              {
                                                  uint character = characters[i];
                                      
                                                  if (character < 0x80)
                                                  {
                                                      buffer[writeIndex++] = (byte)character;
                                                  } else if (character < 0x800)
                                                  {
                                                      buffer[writeIndex++] = (byte)(0b11000000 | ((character >> 6) & 0b11111));
                                                      buffer[writeIndex++] = (byte)(0b10000000 | (character & 0b111111));
                                                  } else if (character < 0x10000)
                                                  {
                                                      buffer[writeIndex++] = (byte)(0b11100000 | ((character >> 12) & 0b1111));
                                                      buffer[writeIndex++] = (byte)(0b10000000 | ((character >> 6) & 0b111111));
                                                      buffer[writeIndex++] = (byte)(0b10000000 | (character & 0b111111));
                                                  } else
                                                  {
                                                      buffer[writeIndex++] = (byte)(0b11110000 | ((character >> 18) & 0b111));
                                                      buffer[writeIndex++] = (byte)(0b10000000 | ((character >> 12) & 0b111111));
                                                      buffer[writeIndex++] = (byte)(0b10000000 | ((character >> 6) & 0b111111));
                                                      buffer[writeIndex++] = (byte)(0b10000000 | (character & 0b111111));
                                                  }
                                              }
                                      
                                              // We do this to truncate off the end of the array
                                              // This would be a lot easier with Array.Resize, but Udon once again does not allow access to it.
                                              byte[] output = new byte[writeIndex];
                                      
                                              for (int i = 0; i < writeIndex; i++)
                                                  output[i] = buffer[i];
                                      
                                              return output;
                                          }
                                      
                                          /*  MD5  */
                                      
                                          private readonly ulong[] md5_init =
                                          {
                                              0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476,
                                          };
                                      
                                          private readonly ulong[] md5_constants = {
                                              0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
                                              0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
                                              0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
                                              0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
                                              0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
                                              0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
                                              0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
                                              0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
                                          };
                                      
                                          private readonly int[] md5_shifts =
                                          {
                                              7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
                                              5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
                                              4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
                                              6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,
                                          };
                                      
                                          private string MD5_Core(byte[] payload_bytes, ulong[] init, ulong[] constants, int[] shifts, ulong size_mask, int word_size, int chunk_modulo, int appended_length, int round_count, string output_format, int output_segments)
                                          {
                                              int word_bytes = word_size / 8;
                                      
                                              // Working variables a0->d0
                                              ulong[] working_variables = new ulong[4];
                                              init.CopyTo(working_variables, 0);
                                      
                                              byte[] input = new byte[chunk_modulo];
                                              ulong[] message_schedule = new ulong[16];
                                      
                                              // Each 64-byte/512-bit chunk
                                              // 64 bits/8 bytes are required at the end for the bit size
                                              for (int chunk_index = 0; chunk_index < payload_bytes.Length + appended_length + 1; chunk_index += chunk_modulo)
                                              {
                                                  int chunk_size = Mathf.Min(chunk_modulo, payload_bytes.Length - chunk_index);
                                                  int schedule_index = 0;
                                      
                                                  // Buffer message
                                                  for (; schedule_index < chunk_size; ++schedule_index)
                                                      input[schedule_index] = payload_bytes[chunk_index + schedule_index];
                                                  // Append a 1-bit if not an even chunk
                                                  if (schedule_index < chunk_modulo && chunk_size >= 0)
                                                      input[schedule_index++] = 0b10000000;
                                                  // Pad with zeros until the end
                                                  for (; schedule_index < chunk_modulo; ++schedule_index)
                                                      input[schedule_index] = 0x00;
                                                  // If the chunk is less than 56 bytes, this will be the final chunk containing the data size in bits
                                                  if (chunk_size < chunk_modulo - appended_length)
                                                  {
                                                      ulong bit_size = (ulong)payload_bytes.Length * 8ul;
                                                      input[chunk_modulo - 8] = Convert.ToByte((bit_size >> 0x00) & 0xFFul);
                                                      input[chunk_modulo - 7] = Convert.ToByte((bit_size >> 0x08) & 0xFFul);
                                                      input[chunk_modulo - 6] = Convert.ToByte((bit_size >> 0x10) & 0xFFul);
                                                      input[chunk_modulo - 5] = Convert.ToByte((bit_size >> 0x18) & 0xFFul);
                                                      input[chunk_modulo - 4] = Convert.ToByte((bit_size >> 0x20) & 0xFFul);
                                                      input[chunk_modulo - 3] = Convert.ToByte((bit_size >> 0x28) & 0xFFul);
                                                      input[chunk_modulo - 2] = Convert.ToByte((bit_size >> 0x30) & 0xFFul);
                                                      input[chunk_modulo - 1] = Convert.ToByte((bit_size >> 0x38) & 0xFFul);
                                                  }
                                      
                                                  // Copy into w[0..15]
                                                  int copy_index = 0;
                                                  for (; copy_index < 16; copy_index++)
                                                  {
                                                      message_schedule[copy_index] = 0ul;
                                                      for (int i = 0; i < word_bytes; i++)
                                                      {
                                                          message_schedule[copy_index] = message_schedule[copy_index] | ((ulong)input[(copy_index * word_bytes) + i] << (i * 8));
                                                      }
                                      
                                                      message_schedule[copy_index] = message_schedule[copy_index] & size_mask;
                                                  }
                                      
                                                  // temp vars
                                                  ulong f, g;
                                                  // work is equivalent to A, B, C, D
                                                  // This copies work from a0, b0, c0, d0
                                                  ulong[] work = new ulong[4];
                                                  working_variables.CopyTo(work, 0);
                                      
                                                  // Compression function main loop
                                                  for (copy_index = 0; copy_index < round_count; copy_index++)
                                                  {
                                                      if (copy_index < 16)
                                                      {
                                                          f = ((work[1] & work[2]) | ((size_mask ^ work[1]) & work[3])) & size_mask;
                                                          g = (ulong)copy_index;
                                                      } else if (copy_index < 32)
                                                      {
                                                          f = ((work[3] & work[1]) | ((size_mask ^ work[3]) & work[2])) & size_mask;
                                                          g = (ulong)(((5 * copy_index) + 1) % 16);
                                                      } else if (copy_index < 48)
                                                      {
                                                          f = work[1] ^ work[2] ^ work[3];
                                                          g = (ulong)(((3 * copy_index) + 5) % 16);
                                                      } else
                                                      {
                                                          f = (work[2] ^ (work[1] | (size_mask ^ work[3]))) & size_mask;
                                                          g = (ulong)(7 * copy_index % 16);
                                                      }
                                      
                                                      f = (f + work[0] + constants[copy_index] + message_schedule[g]) & size_mask;
                                                      work[0] = work[3];
                                                      work[3] = work[2];
                                                      work[2] = work[1];
                                                      work[1] = (work[1] + ((f << shifts[copy_index]) | (f >> word_size - shifts[copy_index]))) & size_mask;
                                                  }
                                      
                                                  for (copy_index = 0; copy_index < 4; copy_index++)
                                                      working_variables[copy_index] = (working_variables[copy_index] + work[copy_index]) & size_mask;
                                              }
                                      
                                              // Finalization
                                              string output = "";
                                      
                                              for (int character_index = 0; character_index < output_segments; character_index++)
                                              {
                                                  ulong value = working_variables[character_index];
                                                  output += string.Format(output_format,
                                                      ((value & 0x000000FFul) << 0x18) |
                                                      ((value & 0x0000FF00ul) << 0x08) |
                                                      ((value & 0x00FF0000ul) >> 0x08) |
                                                      ((value & 0xFF000000ul) >> 0x18)
                                                  );
                                              }
                                      
                                              return output;
                                          }
                                      
                                          public string MD5_Bytes(byte[] data)
                                          {
                                              return MD5_Core(data, md5_init, md5_constants, md5_shifts, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 4);
                                          }
                                      
                                          public string MD5_UTF8(string text)
                                          {
                                              return MD5_Core(ToUTF8(text.ToCharArray()), md5_init, md5_constants, md5_shifts, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 4);
                                          }
                                      
                                          /*  SHA1  */
                                      
                                          private readonly ulong[] sha1_init = {
                                              0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0,
                                          };
                                      
                                          private string SHA1_Core(byte[] payload_bytes, ulong[] init, ulong size_mask, int word_size, int chunk_modulo, int appended_length, int left_rotations, int round_count, string output_format, int output_segments)
                                          {
                                              int word_bytes = word_size / 8;
                                      
                                              // Working variables h0->h4
                                              ulong[] working_variables = new ulong[5];
                                              init.CopyTo(working_variables, 0);
                                      
                                              byte[] input = new byte[chunk_modulo];
                                              ulong[] message_schedule = new ulong[round_count];
                                      
                                              // Each 64-byte/512-bit chunk
                                              // 64 bits/8 bytes are required at the end for the bit size
                                              for (int chunk_index = 0; chunk_index < payload_bytes.Length + appended_length + 1; chunk_index += chunk_modulo)
                                              {
                                                  int chunk_size = Mathf.Min(chunk_modulo, payload_bytes.Length - chunk_index);
                                                  int schedule_index = 0;
                                      
                                                  // Buffer message
                                                  for (; schedule_index < chunk_size; ++schedule_index)
                                                      input[schedule_index] = payload_bytes[chunk_index + schedule_index];
                                                  // Append a 1-bit if not an even chunk
                                                  if (schedule_index < chunk_modulo && chunk_size >= 0)
                                                      input[schedule_index++] = 0b10000000;
                                                  // Pad with zeros until the end
                                                  for (; schedule_index < chunk_modulo; ++schedule_index)
                                                      input[schedule_index] = 0x00;
                                                  // If the chunk is less than 56 bytes, this will be the final chunk containing the data size in bits
                                                  if (chunk_size < chunk_modulo - appended_length)
                                                  {
                                                      ulong bit_size = (ulong)payload_bytes.Length * 8ul;
                                                      input[chunk_modulo - 1] = Convert.ToByte((bit_size >> 0x00) & 0xFFul);
                                                      input[chunk_modulo - 2] = Convert.ToByte((bit_size >> 0x08) & 0xFFul);
                                                      input[chunk_modulo - 3] = Convert.ToByte((bit_size >> 0x10) & 0xFFul);
                                                      input[chunk_modulo - 4] = Convert.ToByte((bit_size >> 0x18) & 0xFFul);
                                                      input[chunk_modulo - 5] = Convert.ToByte((bit_size >> 0x20) & 0xFFul);
                                                      input[chunk_modulo - 6] = Convert.ToByte((bit_size >> 0x28) & 0xFFul);
                                                      input[chunk_modulo - 7] = Convert.ToByte((bit_size >> 0x30) & 0xFFul);
                                                      input[chunk_modulo - 8] = Convert.ToByte((bit_size >> 0x38) & 0xFFul);
                                                  }
                                      
                                                  // Copy into w[0..15]
                                                  int copy_index = 0;
                                                  for (; copy_index < 16; copy_index++)
                                                  {
                                                      message_schedule[copy_index] = 0ul;
                                                      for (int i = 0; i < word_bytes; i++)
                                                      {
                                                          message_schedule[copy_index] = (message_schedule[copy_index] << 8) | input[(copy_index * word_bytes) + i];
                                                      }
                                      
                                                      message_schedule[copy_index] = message_schedule[copy_index] & size_mask;
                                                  }
                                                  // Extend
                                                  for (; copy_index < round_count; copy_index++)
                                                  {
                                                      ulong w = message_schedule[copy_index - 3] ^ message_schedule[copy_index - 8] ^ message_schedule[copy_index - 14] ^ message_schedule[copy_index - 16];
                                                      message_schedule[copy_index] = (
                                                          (w << left_rotations) | (w >> word_size - left_rotations)
                                                      ) & size_mask;
                                                  }
                                      
                                                  // temp vars
                                                  ulong temp, k, f;
                                                  // work is equivalent to a, b, c, d, e
                                                  // This copies work from h0, h1, h2, h3, h4
                                                  ulong[] work = new ulong[5];
                                                  working_variables.CopyTo(work, 0);
                                      
                                                  // Compression function main loop
                                                  for (copy_index = 0; copy_index < round_count; copy_index++)
                                                  {
                                                      if (copy_index < 20)
                                                      {
                                                          f = ((work[1] & work[2]) | ((size_mask ^ work[1]) & work[3])) & size_mask;
                                                          k = 0x5A827999;
                                                      } else if (copy_index < 40)
                                                      {
                                                          f = work[1] ^ work[2] ^ work[3];
                                                          k = 0x6ED9EBA1;
                                                      } else if (copy_index < 60)
                                                      {
                                                          f = (work[1] & work[2]) ^ (work[1] & work[3]) ^ (work[2] & work[3]);
                                                          k = 0x8F1BBCDC;
                                                      } else
                                                      {
                                                          f = work[1] ^ work[2] ^ work[3];
                                                          k = 0xCA62C1D6;
                                                      }
                                      
                                                      temp = (((work[0] << 5) | (work[0] >> word_size - 5)) + f + work[4] + k + message_schedule[copy_index]) & size_mask;
                                                      work[4] = work[3];
                                                      work[3] = work[2];
                                                      work[2] = ((work[1] << 30) | (work[1] >> word_size - 30)) & size_mask;
                                                      work[1] = work[0];
                                                      work[0] = temp;
                                                  }
                                      
                                                  for (copy_index = 0; copy_index < 5; copy_index++)
                                                      working_variables[copy_index] = (working_variables[copy_index] + work[copy_index]) & size_mask;
                                              }
                                      
                                              // Finalization
                                              string output = "";
                                      
                                              for (int character_index = 0; character_index < output_segments; character_index++)
                                              {
                                                  output += string.Format(output_format, working_variables[character_index]);
                                              }
                                      
                                              return output;
                                          }
                                      
                                          /* SHA0 */
                                          /* This algorithm has had documented vulnerabilites since before its formal release. */
                                          /* Near to nothing uses it, and it should not be trusted for real applications under any circumstances */
                                          /* It is only here for completeness, and there may be bugs with it due to the difficulty of finding RFC-complying implementations to test against. */
                                          /*
                                          public string SHA0_Bytes(byte[] data)
                                          {
                                              return SHA1_Core(data, sha1_init, 0xFFFFFFFFul, 32, 64, 8, 0, 80, "{0:x8}", 5);
                                          }
                                      
                                          public string SHA0_UTF8(string text)
                                          {
                                              return SHA1_Core(ToUTF8(text.ToCharArray()), sha1_init, 0xFFFFFFFFul, 32, 64, 8, 0, 80, "{0:x8}", 5);
                                          }
                                          */
                                      
                                          /* SHA1 */
                                          public string SHA1_Bytes(byte[] data)
                                          {
                                              return SHA1_Core(data, sha1_init, 0xFFFFFFFFul, 32, 64, 8, 1, 80, "{0:x8}", 5);
                                          }
                                      
                                          public string SHA1_UTF8(string text)
                                          {
                                              return SHA1_Core(ToUTF8(text.ToCharArray()), sha1_init, 0xFFFFFFFFul, 32, 64, 8, 1, 80, "{0:x8}", 5);
                                          }
                                      
                                          /*  SHA2  */
                                      
                                          private readonly ulong[] sha224_init = {
                                              0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
                                          };
                                      
                                          private readonly ulong[] sha256_init = {
                                              0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
                                          };
                                      
                                          private readonly ulong[] sha256_constants = {
                                              0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                                              0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
                                              0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
                                              0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
                                              0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
                                              0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
                                              0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
                                              0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
                                          };
                                      
                                          private readonly int[] sha256_sums =
                                          {
                                              7, 18, 3,  // s0
                                              17, 19, 10,  // s1
                                          };
                                      
                                          private readonly int[] sha256_sigmas =
                                          {
                                              2, 13, 22,  // S0
                                              6, 11, 25,  // S1
                                          };
                                      
                                          private readonly ulong[] sha384_init = {
                                              0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0x67332667ffc00b31,
                                              0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
                                          };
                                      
                                          private readonly ulong[] sha512_init = {
                                              0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1,
                                              0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
                                          };
                                      
                                          private readonly ulong[] sha512_constants = {
                                              0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
                                              0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
                                              0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
                                              0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
                                              0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
                                              0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
                                              0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
                                              0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
                                              0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
                                              0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
                                              0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
                                              0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
                                              0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
                                              0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
                                              0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
                                              0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
                                          };
                                      
                                          private readonly int[] sha512_sums =
                                          {
                                              1, 8, 7,  // s0
                                              19, 61, 6,  // s1
                                          };
                                      
                                          private readonly int[] sha512_sigmas =
                                          {
                                              28, 34, 39,  // S0
                                              14, 18, 41,  // S1
                                          };
                                      
                                          private string SHA2_Core(byte[] payload_bytes, ulong[] init, ulong[] constants, int[] sums, int[] sigmas, ulong size_mask, int word_size, int chunk_modulo, int appended_length, int round_count, string output_format, int output_segments)
                                          {
                                              int word_bytes = word_size / 8;
                                      
                                              // Working variables h0->h7
                                              ulong[] working_variables = new ulong[8];
                                              init.CopyTo(working_variables, 0);
                                      
                                              byte[] input = new byte[chunk_modulo];
                                              ulong[] message_schedule = new ulong[round_count];
                                      
                                              // Each 64-byte/512-bit chunk
                                              // 64 bits/8 bytes are required at the end for the bit size
                                              for (int chunk_index = 0; chunk_index < payload_bytes.Length + appended_length + 1; chunk_index += chunk_modulo) {
                                                  int chunk_size = Mathf.Min(chunk_modulo, payload_bytes.Length - chunk_index);
                                                  int schedule_index = 0;
                                      
                                                  // Buffer message
                                                  for (; schedule_index < chunk_size; ++schedule_index)
                                                      input[schedule_index] = payload_bytes[chunk_index + schedule_index];
                                                  // Append a 1-bit if not an even chunk
                                                  if (schedule_index < chunk_modulo && chunk_size >= 0)
                                                      input[schedule_index++] = 0b10000000;
                                                  // Pad with zeros until the end
                                                  for (; schedule_index < chunk_modulo; ++schedule_index)
                                                      input[schedule_index] = 0x00;
                                                  // If the chunk is less than 56 bytes, this will be the final chunk containing the data size in bits
                                                  if (chunk_size < chunk_modulo - appended_length) {
                                                      ulong bit_size = (ulong)payload_bytes.Length * 8ul;
                                                      input[chunk_modulo - 1] = Convert.ToByte((bit_size >> 0x00) & 0xFFul);
                                                      input[chunk_modulo - 2] = Convert.ToByte((bit_size >> 0x08) & 0xFFul);
                                                      input[chunk_modulo - 3] = Convert.ToByte((bit_size >> 0x10) & 0xFFul);
                                                      input[chunk_modulo - 4] = Convert.ToByte((bit_size >> 0x18) & 0xFFul);
                                                      input[chunk_modulo - 5] = Convert.ToByte((bit_size >> 0x20) & 0xFFul);
                                                      input[chunk_modulo - 6] = Convert.ToByte((bit_size >> 0x28) & 0xFFul);
                                                      input[chunk_modulo - 7] = Convert.ToByte((bit_size >> 0x30) & 0xFFul);
                                                      input[chunk_modulo - 8] = Convert.ToByte((bit_size >> 0x38) & 0xFFul);
                                                  }
                                      
                                                  // Copy into w[0..15]
                                                  int copy_index = 0;
                                                  for (; copy_index < 16; copy_index++)
                                                  {
                                                      message_schedule[copy_index] = 0ul;
                                                      for (int i = 0; i < word_bytes; i++)
                                                      {
                                                          message_schedule[copy_index] = (message_schedule[copy_index] << 8) | input[(copy_index * word_bytes) + i];
                                                      }
                                      
                                                      message_schedule[copy_index] = message_schedule[copy_index] & size_mask;
                                                  }
                                                  // Extend
                                                  for(; copy_index < round_count; copy_index++) {
                                                      ulong s0_read = message_schedule[copy_index - 15];
                                                      ulong s1_read = message_schedule[copy_index - 2];
                                      
                                                      message_schedule[copy_index] = (
                                                          message_schedule[copy_index - 16] +
                                                          (((s0_read >> sums[0]) | (s0_read << word_size - sums[0])) ^ ((s0_read >> sums[1]) | (s0_read << word_size - sums[1])) ^ (s0_read >> sums[2])) + // s0
                                                          message_schedule[copy_index - 7] +
                                                          (((s1_read >> sums[3]) | (s1_read << word_size - sums[3])) ^ ((s1_read >> sums[4]) | (s1_read << word_size - sums[4])) ^ (s1_read >> sums[5])) // s1
                                                      ) & size_mask;
                                                  }
                                      
                                                  // temp vars
                                                  ulong temp1, temp2;
                                                  // work is equivalent to a, b, c, d, e, f, g, h
                                                  // This copies work from h0, h1, h2, h3, h4, h5, h6, h7
                                                  ulong[] work = new ulong[8];
                                                  working_variables.CopyTo(work, 0);
                                      
                                                  // Compression function main loop
                                                  for (copy_index = 0; copy_index < round_count; copy_index++)
                                                  {
                                                      ulong ep1 = ((work[4] >> sigmas[3]) | (work[4] << word_size - sigmas[3])) ^ ((work[4] >> sigmas[4]) | (work[4] << word_size - sigmas[4])) ^ ((work[4] >> sigmas[5]) | (work[4] << word_size - sigmas[5]));
                                                      ulong ch = (work[4] & work[5]) ^ ((size_mask ^ work[4]) & work[6]);
                                                      ulong ep0 = ((work[0] >> sigmas[0]) | (work[0] << word_size - sigmas[0])) ^ ((work[0] >> sigmas[1]) | (work[0] << word_size - sigmas[1])) ^ ((work[0] >> sigmas[2]) | (work[0] << word_size - sigmas[2]));
                                                      ulong maj = (work[0] & work[1]) ^ (work[0] & work[2]) ^ (work[1] & work[2]);
                                                      temp1 = work[7] + ep1 + ch + constants[copy_index] + message_schedule[copy_index];
                                                      temp2 = ep0 + maj;
                                                      work[7] = work[6];
                                                      work[6] = work[5];
                                                      work[5] = work[4];
                                                      work[4] = (work[3] + temp1) & size_mask;
                                                      work[3] = work[2];
                                                      work[2] = work[1];
                                                      work[1] = work[0];
                                                      work[0] = (temp1 + temp2) & size_mask;
                                                  }
                                      
                                                  for (copy_index = 0; copy_index < 8; copy_index++)
                                                      working_variables[copy_index] = (working_variables[copy_index] + work[copy_index]) & size_mask;
                                              }
                                      
                                              // Finalization
                                              string output = "";
                                      
                                              for (int character_index = 0; character_index < output_segments; character_index++) {
                                                  output += string.Format(output_format, working_variables[character_index]);
                                              }
                                      
                                              return output;
                                          }
                                      
                                          /* SHA224 */
                                          public string SHA224_Bytes(byte[] data)
                                          {
                                              return SHA2_Core(data, sha224_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 7);
                                          }
                                      
                                          public string SHA224_UTF8(string text)
                                          {
                                              return SHA2_Core(ToUTF8(text.ToCharArray()), sha224_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 7);
                                          }
                                      
                                          /* SHA256 */
                                          public string SHA256_Bytes(byte[] data)
                                          {
                                              return SHA2_Core(data, sha256_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 8);
                                          }
                                      
                                          public string SHA256_UTF8(string text)
                                          {
                                              return SHA2_Core(ToUTF8(text.ToCharArray()), sha256_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 8);
                                          }
                                      
                                          /* SHA384 */
                                          public string SHA384_Bytes(byte[] data)
                                          {
                                              return SHA2_Core(data, sha384_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 6);
                                          }
                                      
                                          public string SHA384_UTF8(string text)
                                          {
                                              return SHA2_Core(ToUTF8(text.ToCharArray()), sha384_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 6);
                                          }
                                      
                                          /* SHA512 */
                                          public string SHA512_Bytes(byte[] data)
                                          {
                                              return SHA2_Core(data, sha512_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 8);
                                          }
                                      
                                          public string SHA512_UTF8(string text)
                                          {
                                              return SHA2_Core(ToUTF8(text.ToCharArray()), sha512_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 8);
                                          }
                                      }
                                      
                                      
                                      #if !COMPILER_UDONSHARP && UNITY_EDITOR
                                      
                                      [CustomEditor(typeof(UdonHashLib))]
                                      public class UdonHashLibEditor : Editor
                                      {
                                          private string inputString = "";
                                      
                                          public override void OnInspectorGUI()
                                          {
                                              // Draws the default convert to UdonBehaviour button, program asset field, sync settings, etc.
                                              if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) return;
                                      
                                              UdonHashLib inspectorBehaviour = (UdonHashLib)target;
                                      
                                              if (!EditorApplication.isPlaying)
                                                  EditorGUILayout.HelpBox("Enter play mode to run tests", MessageType.Info);
                                      
                                              EditorGUI.BeginDisabledGroup(!EditorApplication.isPlaying);
                                      
                                              // A simple string field modification with Undo handling
                                              EditorGUILayout.LabelField("Input for hash");
                                              inputString = EditorGUILayout.TextArea(inputString);
                                      
                                              if (GUILayout.Button("Calculate hashes"))
                                              {
                                      
                                                  CheckHash(inputString, true);
                                              }
                                      
                                              if (GUILayout.Button("Run test suite"))
                                              {
                                                  int testBatch = 4096;
                                                  int testCount = 0, succeeded = 0;
                                      
                                                  System.Random random = new System.Random();
                                                  string chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~\n";
                                                  string buffer = new string(Enumerable.Repeat(chars, testBatch).Select(s => s[random.Next(s.Length)]).ToArray());
                                      
                                                  Debug.Log($"Buffer generated for ASCII testing: {buffer}");
                                      
                                                  for (int i = 0; i < testBatch; i++)
                                                  {
                                                      string test = buffer.Substring(random.Next(buffer.Length - i), i);
                                      
                                                      testCount++;
                                                      if (CheckHash(test))
                                                          succeeded++;
                                                  }
                                      
                                                  // Japanese character (UTF-8) test
                                                  chars = "\u3042\u3044\u3046\u3048\u304a\u304b\u304d\u304f\u3051\u3053\u3055\u3057\u3059\u305b\u305d\u305f\u3061\u3064\u3066\u3068\u306a\u306b\u306c\u306d\u306e\u306f\u3072\u3075\u3078\u307b\u307e\u307f\u3080\u3081\u3082\u3084\u3086\u3088\u3089\u308a\u308b\u308c\u308d\u308f\u3090\u3091\u3092\u3093\u30a2\u30a4\u30a6\u30a8\u30aa\u30ab\u30ad\u30af\u30b1\u30b3\u30b5\u30b7\u30b9\u30bb\u30bd\u30bf\u30c1\u30c4\u30c6\u30c8\u30ca\u30cb\u30cc\u30cd\u30ce\u30cf\u30d2\u30d5\u30d8\u30db\u30de\u30df\u30e0\u30e1\u30e2\u30e4\u30e6\u30e8\u30e9\u30ea\u30eb\u30ec\u30ed\u30ef\u30f0\u30f1\u30f2\u30f3";
                                                  buffer = new string(Enumerable.Repeat(chars, testBatch).Select(s => s[random.Next(s.Length)]).ToArray());
                                      
                                                  Debug.Log($"Buffer generated for JPN/UTF-8 testing: {buffer}");
                                      
                                                  for (int i = 0; i < testBatch; i++)
                                                  {
                                                      string test = buffer.Substring(random.Next(buffer.Length - i), i);
                                      
                                                      testCount++;
                                                      if (CheckHash(test))
                                                          succeeded++;
                                                  }
                                      
                                                  EditorUtility.DisplayDialog("Results", $"{testCount} tests ran, {succeeded} succeeded in all hashes", "OK");
                                              }
                                      
                                              EditorGUI.EndDisabledGroup();
                                          }
                                      
                                          private bool CheckHash(string input, bool showDialog = false, bool showDialogWhenFailed = true)
                                          {
                                              UdonHashLib inspectorBehaviour = (UdonHashLib)target;
                                      
                                              string md5_udon = inspectorBehaviour.MD5_UTF8(input);
                                              string sha1_udon = inspectorBehaviour.SHA1_UTF8(input);
                                              string sha224_udon = inspectorBehaviour.SHA224_UTF8(input);
                                              string sha256_udon = inspectorBehaviour.SHA256_UTF8(input);
                                              string sha384_udon = inspectorBehaviour.SHA384_UTF8(input);
                                              string sha512_udon = inspectorBehaviour.SHA512_UTF8(input);
                                      
                                              string md5_csharp = GenerateNonUdon(input, System.Security.Cryptography.MD5.Create());
                                              string sha1_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA1.Create());
                                              string sha256_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA256.Create());
                                              string sha384_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA384.Create());
                                              string sha512_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA512.Create());
                                      
                                              bool allPass = (
                                                  md5_udon == md5_csharp &&
                                                  sha1_udon == sha1_csharp &&
                                                  sha256_udon == sha256_csharp &&
                                                  sha384_udon == sha384_csharp &&
                                                  sha512_udon == sha512_csharp
                                              );
                                      
                                              if (showDialog || (!allPass && showDialogWhenFailed))
                                                  EditorUtility.DisplayDialog("Hashes", string.Join("\n", new string[] {
                                                      input,
                                                      "",
                                                      $"md5 [{(md5_udon == md5_csharp ? "PASS" : "FAIL")}]: {md5_udon}",
                                                      $"sha1 [{(sha1_udon == sha1_csharp ? "PASS" : "FAIL")}]: {sha1_udon}",
                                                      $"sha224: {sha224_udon}", // No system impl for this
                                                      $"sha256 [{(sha256_udon == sha256_csharp ? "PASS" : "FAIL")}]: {sha256_udon}",
                                                      $"sha384 [{(sha384_udon == sha384_csharp ? "PASS" : "FAIL")}]: {sha384_udon}",
                                                      $"sha512 [{(sha512_udon == sha512_csharp ? "PASS" : "FAIL")}]: {sha512_udon}",
                                                  }), "OK");
                                      
                                              return allPass;
                                          }
                                      
                                          private string GenerateNonUdon(string input, System.Security.Cryptography.HashAlgorithm algorithm)
                                          {
                                              using (var hash = algorithm)
                                              {
                                                  var bytes = hash.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input));
                                      
                                                  string output = "";
                                      
                                                  foreach (byte x in bytes)
                                                  {
                                                      output += string.Format("{0:x2}", x);
                                                  }
                                      
                                                  return output;
                                              }
                                          }
                                      }
                                      #endif
                                      
                                      
                                      RoseVelvetteR 1 Reply Last reply
                                      1
                                      • WorcestershireW Worcestershire

                                        @RedCob If my reading of the code @Lucian pasted here is correct they're using the vrchat-udon-hashlib. Both call the lib using "_hashLibrary".

                                        Here's the code of the hashing it uses if it's of any help:

                                        // -*- coding: utf-8 -*-
                                        /*
                                        MIT License
                                        
                                        Copyright (c) 2021-present Devon (Gorialis) R
                                        
                                        Permission is hereby granted, free of charge, to any person obtaining a copy
                                        of this software and associated documentation files (the "Software"), to deal
                                        in the Software without restriction, including without limitation the rights
                                        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                                        copies of the Software, and to permit persons to whom the Software is
                                        furnished to do so, subject to the following conditions:
                                        
                                        The above copyright notice and this permission notice shall be included in all
                                        copies or substantial portions of the Software.
                                        
                                        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                                        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                                        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                                        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                                        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                                        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
                                        SOFTWARE.
                                        
                                        */
                                        
                                        using System;
                                        using System.Linq;
                                        using UnityEngine;
                                        using UdonSharp;
                                        
                                        #if !COMPILER_UDONSHARP && UNITY_EDITOR
                                        using UnityEditor;
                                        using UdonSharpEditor;
                                        #endif
                                        
                                        
                                        public class UdonHashLib : UdonSharpBehaviour
                                        {
                                            // Udon does not support UTF-8 or expose System.Text.Encoding so we must implement this ourselves
                                            private byte[] ToUTF8(char[] characters)
                                            {
                                                byte[] buffer = new byte[characters.Length * 4];
                                        
                                                int writeIndex = 0;
                                                for (int i = 0; i < characters.Length; i++)
                                                {
                                                    uint character = characters[i];
                                        
                                                    if (character < 0x80)
                                                    {
                                                        buffer[writeIndex++] = (byte)character;
                                                    } else if (character < 0x800)
                                                    {
                                                        buffer[writeIndex++] = (byte)(0b11000000 | ((character >> 6) & 0b11111));
                                                        buffer[writeIndex++] = (byte)(0b10000000 | (character & 0b111111));
                                                    } else if (character < 0x10000)
                                                    {
                                                        buffer[writeIndex++] = (byte)(0b11100000 | ((character >> 12) & 0b1111));
                                                        buffer[writeIndex++] = (byte)(0b10000000 | ((character >> 6) & 0b111111));
                                                        buffer[writeIndex++] = (byte)(0b10000000 | (character & 0b111111));
                                                    } else
                                                    {
                                                        buffer[writeIndex++] = (byte)(0b11110000 | ((character >> 18) & 0b111));
                                                        buffer[writeIndex++] = (byte)(0b10000000 | ((character >> 12) & 0b111111));
                                                        buffer[writeIndex++] = (byte)(0b10000000 | ((character >> 6) & 0b111111));
                                                        buffer[writeIndex++] = (byte)(0b10000000 | (character & 0b111111));
                                                    }
                                                }
                                        
                                                // We do this to truncate off the end of the array
                                                // This would be a lot easier with Array.Resize, but Udon once again does not allow access to it.
                                                byte[] output = new byte[writeIndex];
                                        
                                                for (int i = 0; i < writeIndex; i++)
                                                    output[i] = buffer[i];
                                        
                                                return output;
                                            }
                                        
                                            /*  MD5  */
                                        
                                            private readonly ulong[] md5_init =
                                            {
                                                0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476,
                                            };
                                        
                                            private readonly ulong[] md5_constants = {
                                                0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
                                                0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
                                                0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
                                                0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
                                                0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
                                                0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
                                                0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
                                                0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
                                            };
                                        
                                            private readonly int[] md5_shifts =
                                            {
                                                7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,
                                                5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,
                                                4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,
                                                6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,
                                            };
                                        
                                            private string MD5_Core(byte[] payload_bytes, ulong[] init, ulong[] constants, int[] shifts, ulong size_mask, int word_size, int chunk_modulo, int appended_length, int round_count, string output_format, int output_segments)
                                            {
                                                int word_bytes = word_size / 8;
                                        
                                                // Working variables a0->d0
                                                ulong[] working_variables = new ulong[4];
                                                init.CopyTo(working_variables, 0);
                                        
                                                byte[] input = new byte[chunk_modulo];
                                                ulong[] message_schedule = new ulong[16];
                                        
                                                // Each 64-byte/512-bit chunk
                                                // 64 bits/8 bytes are required at the end for the bit size
                                                for (int chunk_index = 0; chunk_index < payload_bytes.Length + appended_length + 1; chunk_index += chunk_modulo)
                                                {
                                                    int chunk_size = Mathf.Min(chunk_modulo, payload_bytes.Length - chunk_index);
                                                    int schedule_index = 0;
                                        
                                                    // Buffer message
                                                    for (; schedule_index < chunk_size; ++schedule_index)
                                                        input[schedule_index] = payload_bytes[chunk_index + schedule_index];
                                                    // Append a 1-bit if not an even chunk
                                                    if (schedule_index < chunk_modulo && chunk_size >= 0)
                                                        input[schedule_index++] = 0b10000000;
                                                    // Pad with zeros until the end
                                                    for (; schedule_index < chunk_modulo; ++schedule_index)
                                                        input[schedule_index] = 0x00;
                                                    // If the chunk is less than 56 bytes, this will be the final chunk containing the data size in bits
                                                    if (chunk_size < chunk_modulo - appended_length)
                                                    {
                                                        ulong bit_size = (ulong)payload_bytes.Length * 8ul;
                                                        input[chunk_modulo - 8] = Convert.ToByte((bit_size >> 0x00) & 0xFFul);
                                                        input[chunk_modulo - 7] = Convert.ToByte((bit_size >> 0x08) & 0xFFul);
                                                        input[chunk_modulo - 6] = Convert.ToByte((bit_size >> 0x10) & 0xFFul);
                                                        input[chunk_modulo - 5] = Convert.ToByte((bit_size >> 0x18) & 0xFFul);
                                                        input[chunk_modulo - 4] = Convert.ToByte((bit_size >> 0x20) & 0xFFul);
                                                        input[chunk_modulo - 3] = Convert.ToByte((bit_size >> 0x28) & 0xFFul);
                                                        input[chunk_modulo - 2] = Convert.ToByte((bit_size >> 0x30) & 0xFFul);
                                                        input[chunk_modulo - 1] = Convert.ToByte((bit_size >> 0x38) & 0xFFul);
                                                    }
                                        
                                                    // Copy into w[0..15]
                                                    int copy_index = 0;
                                                    for (; copy_index < 16; copy_index++)
                                                    {
                                                        message_schedule[copy_index] = 0ul;
                                                        for (int i = 0; i < word_bytes; i++)
                                                        {
                                                            message_schedule[copy_index] = message_schedule[copy_index] | ((ulong)input[(copy_index * word_bytes) + i] << (i * 8));
                                                        }
                                        
                                                        message_schedule[copy_index] = message_schedule[copy_index] & size_mask;
                                                    }
                                        
                                                    // temp vars
                                                    ulong f, g;
                                                    // work is equivalent to A, B, C, D
                                                    // This copies work from a0, b0, c0, d0
                                                    ulong[] work = new ulong[4];
                                                    working_variables.CopyTo(work, 0);
                                        
                                                    // Compression function main loop
                                                    for (copy_index = 0; copy_index < round_count; copy_index++)
                                                    {
                                                        if (copy_index < 16)
                                                        {
                                                            f = ((work[1] & work[2]) | ((size_mask ^ work[1]) & work[3])) & size_mask;
                                                            g = (ulong)copy_index;
                                                        } else if (copy_index < 32)
                                                        {
                                                            f = ((work[3] & work[1]) | ((size_mask ^ work[3]) & work[2])) & size_mask;
                                                            g = (ulong)(((5 * copy_index) + 1) % 16);
                                                        } else if (copy_index < 48)
                                                        {
                                                            f = work[1] ^ work[2] ^ work[3];
                                                            g = (ulong)(((3 * copy_index) + 5) % 16);
                                                        } else
                                                        {
                                                            f = (work[2] ^ (work[1] | (size_mask ^ work[3]))) & size_mask;
                                                            g = (ulong)(7 * copy_index % 16);
                                                        }
                                        
                                                        f = (f + work[0] + constants[copy_index] + message_schedule[g]) & size_mask;
                                                        work[0] = work[3];
                                                        work[3] = work[2];
                                                        work[2] = work[1];
                                                        work[1] = (work[1] + ((f << shifts[copy_index]) | (f >> word_size - shifts[copy_index]))) & size_mask;
                                                    }
                                        
                                                    for (copy_index = 0; copy_index < 4; copy_index++)
                                                        working_variables[copy_index] = (working_variables[copy_index] + work[copy_index]) & size_mask;
                                                }
                                        
                                                // Finalization
                                                string output = "";
                                        
                                                for (int character_index = 0; character_index < output_segments; character_index++)
                                                {
                                                    ulong value = working_variables[character_index];
                                                    output += string.Format(output_format,
                                                        ((value & 0x000000FFul) << 0x18) |
                                                        ((value & 0x0000FF00ul) << 0x08) |
                                                        ((value & 0x00FF0000ul) >> 0x08) |
                                                        ((value & 0xFF000000ul) >> 0x18)
                                                    );
                                                }
                                        
                                                return output;
                                            }
                                        
                                            public string MD5_Bytes(byte[] data)
                                            {
                                                return MD5_Core(data, md5_init, md5_constants, md5_shifts, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 4);
                                            }
                                        
                                            public string MD5_UTF8(string text)
                                            {
                                                return MD5_Core(ToUTF8(text.ToCharArray()), md5_init, md5_constants, md5_shifts, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 4);
                                            }
                                        
                                            /*  SHA1  */
                                        
                                            private readonly ulong[] sha1_init = {
                                                0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0,
                                            };
                                        
                                            private string SHA1_Core(byte[] payload_bytes, ulong[] init, ulong size_mask, int word_size, int chunk_modulo, int appended_length, int left_rotations, int round_count, string output_format, int output_segments)
                                            {
                                                int word_bytes = word_size / 8;
                                        
                                                // Working variables h0->h4
                                                ulong[] working_variables = new ulong[5];
                                                init.CopyTo(working_variables, 0);
                                        
                                                byte[] input = new byte[chunk_modulo];
                                                ulong[] message_schedule = new ulong[round_count];
                                        
                                                // Each 64-byte/512-bit chunk
                                                // 64 bits/8 bytes are required at the end for the bit size
                                                for (int chunk_index = 0; chunk_index < payload_bytes.Length + appended_length + 1; chunk_index += chunk_modulo)
                                                {
                                                    int chunk_size = Mathf.Min(chunk_modulo, payload_bytes.Length - chunk_index);
                                                    int schedule_index = 0;
                                        
                                                    // Buffer message
                                                    for (; schedule_index < chunk_size; ++schedule_index)
                                                        input[schedule_index] = payload_bytes[chunk_index + schedule_index];
                                                    // Append a 1-bit if not an even chunk
                                                    if (schedule_index < chunk_modulo && chunk_size >= 0)
                                                        input[schedule_index++] = 0b10000000;
                                                    // Pad with zeros until the end
                                                    for (; schedule_index < chunk_modulo; ++schedule_index)
                                                        input[schedule_index] = 0x00;
                                                    // If the chunk is less than 56 bytes, this will be the final chunk containing the data size in bits
                                                    if (chunk_size < chunk_modulo - appended_length)
                                                    {
                                                        ulong bit_size = (ulong)payload_bytes.Length * 8ul;
                                                        input[chunk_modulo - 1] = Convert.ToByte((bit_size >> 0x00) & 0xFFul);
                                                        input[chunk_modulo - 2] = Convert.ToByte((bit_size >> 0x08) & 0xFFul);
                                                        input[chunk_modulo - 3] = Convert.ToByte((bit_size >> 0x10) & 0xFFul);
                                                        input[chunk_modulo - 4] = Convert.ToByte((bit_size >> 0x18) & 0xFFul);
                                                        input[chunk_modulo - 5] = Convert.ToByte((bit_size >> 0x20) & 0xFFul);
                                                        input[chunk_modulo - 6] = Convert.ToByte((bit_size >> 0x28) & 0xFFul);
                                                        input[chunk_modulo - 7] = Convert.ToByte((bit_size >> 0x30) & 0xFFul);
                                                        input[chunk_modulo - 8] = Convert.ToByte((bit_size >> 0x38) & 0xFFul);
                                                    }
                                        
                                                    // Copy into w[0..15]
                                                    int copy_index = 0;
                                                    for (; copy_index < 16; copy_index++)
                                                    {
                                                        message_schedule[copy_index] = 0ul;
                                                        for (int i = 0; i < word_bytes; i++)
                                                        {
                                                            message_schedule[copy_index] = (message_schedule[copy_index] << 8) | input[(copy_index * word_bytes) + i];
                                                        }
                                        
                                                        message_schedule[copy_index] = message_schedule[copy_index] & size_mask;
                                                    }
                                                    // Extend
                                                    for (; copy_index < round_count; copy_index++)
                                                    {
                                                        ulong w = message_schedule[copy_index - 3] ^ message_schedule[copy_index - 8] ^ message_schedule[copy_index - 14] ^ message_schedule[copy_index - 16];
                                                        message_schedule[copy_index] = (
                                                            (w << left_rotations) | (w >> word_size - left_rotations)
                                                        ) & size_mask;
                                                    }
                                        
                                                    // temp vars
                                                    ulong temp, k, f;
                                                    // work is equivalent to a, b, c, d, e
                                                    // This copies work from h0, h1, h2, h3, h4
                                                    ulong[] work = new ulong[5];
                                                    working_variables.CopyTo(work, 0);
                                        
                                                    // Compression function main loop
                                                    for (copy_index = 0; copy_index < round_count; copy_index++)
                                                    {
                                                        if (copy_index < 20)
                                                        {
                                                            f = ((work[1] & work[2]) | ((size_mask ^ work[1]) & work[3])) & size_mask;
                                                            k = 0x5A827999;
                                                        } else if (copy_index < 40)
                                                        {
                                                            f = work[1] ^ work[2] ^ work[3];
                                                            k = 0x6ED9EBA1;
                                                        } else if (copy_index < 60)
                                                        {
                                                            f = (work[1] & work[2]) ^ (work[1] & work[3]) ^ (work[2] & work[3]);
                                                            k = 0x8F1BBCDC;
                                                        } else
                                                        {
                                                            f = work[1] ^ work[2] ^ work[3];
                                                            k = 0xCA62C1D6;
                                                        }
                                        
                                                        temp = (((work[0] << 5) | (work[0] >> word_size - 5)) + f + work[4] + k + message_schedule[copy_index]) & size_mask;
                                                        work[4] = work[3];
                                                        work[3] = work[2];
                                                        work[2] = ((work[1] << 30) | (work[1] >> word_size - 30)) & size_mask;
                                                        work[1] = work[0];
                                                        work[0] = temp;
                                                    }
                                        
                                                    for (copy_index = 0; copy_index < 5; copy_index++)
                                                        working_variables[copy_index] = (working_variables[copy_index] + work[copy_index]) & size_mask;
                                                }
                                        
                                                // Finalization
                                                string output = "";
                                        
                                                for (int character_index = 0; character_index < output_segments; character_index++)
                                                {
                                                    output += string.Format(output_format, working_variables[character_index]);
                                                }
                                        
                                                return output;
                                            }
                                        
                                            /* SHA0 */
                                            /* This algorithm has had documented vulnerabilites since before its formal release. */
                                            /* Near to nothing uses it, and it should not be trusted for real applications under any circumstances */
                                            /* It is only here for completeness, and there may be bugs with it due to the difficulty of finding RFC-complying implementations to test against. */
                                            /*
                                            public string SHA0_Bytes(byte[] data)
                                            {
                                                return SHA1_Core(data, sha1_init, 0xFFFFFFFFul, 32, 64, 8, 0, 80, "{0:x8}", 5);
                                            }
                                        
                                            public string SHA0_UTF8(string text)
                                            {
                                                return SHA1_Core(ToUTF8(text.ToCharArray()), sha1_init, 0xFFFFFFFFul, 32, 64, 8, 0, 80, "{0:x8}", 5);
                                            }
                                            */
                                        
                                            /* SHA1 */
                                            public string SHA1_Bytes(byte[] data)
                                            {
                                                return SHA1_Core(data, sha1_init, 0xFFFFFFFFul, 32, 64, 8, 1, 80, "{0:x8}", 5);
                                            }
                                        
                                            public string SHA1_UTF8(string text)
                                            {
                                                return SHA1_Core(ToUTF8(text.ToCharArray()), sha1_init, 0xFFFFFFFFul, 32, 64, 8, 1, 80, "{0:x8}", 5);
                                            }
                                        
                                            /*  SHA2  */
                                        
                                            private readonly ulong[] sha224_init = {
                                                0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
                                            };
                                        
                                            private readonly ulong[] sha256_init = {
                                                0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
                                            };
                                        
                                            private readonly ulong[] sha256_constants = {
                                                0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                                                0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
                                                0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
                                                0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
                                                0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
                                                0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
                                                0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
                                                0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
                                            };
                                        
                                            private readonly int[] sha256_sums =
                                            {
                                                7, 18, 3,  // s0
                                                17, 19, 10,  // s1
                                            };
                                        
                                            private readonly int[] sha256_sigmas =
                                            {
                                                2, 13, 22,  // S0
                                                6, 11, 25,  // S1
                                            };
                                        
                                            private readonly ulong[] sha384_init = {
                                                0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0x67332667ffc00b31,
                                                0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
                                            };
                                        
                                            private readonly ulong[] sha512_init = {
                                                0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1,
                                                0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
                                            };
                                        
                                            private readonly ulong[] sha512_constants = {
                                                0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538,
                                                0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe,
                                                0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
                                                0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
                                                0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab,
                                                0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
                                                0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,
                                                0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
                                                0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
                                                0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
                                                0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,
                                                0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
                                                0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c,
                                                0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
                                                0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
                                                0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
                                            };
                                        
                                            private readonly int[] sha512_sums =
                                            {
                                                1, 8, 7,  // s0
                                                19, 61, 6,  // s1
                                            };
                                        
                                            private readonly int[] sha512_sigmas =
                                            {
                                                28, 34, 39,  // S0
                                                14, 18, 41,  // S1
                                            };
                                        
                                            private string SHA2_Core(byte[] payload_bytes, ulong[] init, ulong[] constants, int[] sums, int[] sigmas, ulong size_mask, int word_size, int chunk_modulo, int appended_length, int round_count, string output_format, int output_segments)
                                            {
                                                int word_bytes = word_size / 8;
                                        
                                                // Working variables h0->h7
                                                ulong[] working_variables = new ulong[8];
                                                init.CopyTo(working_variables, 0);
                                        
                                                byte[] input = new byte[chunk_modulo];
                                                ulong[] message_schedule = new ulong[round_count];
                                        
                                                // Each 64-byte/512-bit chunk
                                                // 64 bits/8 bytes are required at the end for the bit size
                                                for (int chunk_index = 0; chunk_index < payload_bytes.Length + appended_length + 1; chunk_index += chunk_modulo) {
                                                    int chunk_size = Mathf.Min(chunk_modulo, payload_bytes.Length - chunk_index);
                                                    int schedule_index = 0;
                                        
                                                    // Buffer message
                                                    for (; schedule_index < chunk_size; ++schedule_index)
                                                        input[schedule_index] = payload_bytes[chunk_index + schedule_index];
                                                    // Append a 1-bit if not an even chunk
                                                    if (schedule_index < chunk_modulo && chunk_size >= 0)
                                                        input[schedule_index++] = 0b10000000;
                                                    // Pad with zeros until the end
                                                    for (; schedule_index < chunk_modulo; ++schedule_index)
                                                        input[schedule_index] = 0x00;
                                                    // If the chunk is less than 56 bytes, this will be the final chunk containing the data size in bits
                                                    if (chunk_size < chunk_modulo - appended_length) {
                                                        ulong bit_size = (ulong)payload_bytes.Length * 8ul;
                                                        input[chunk_modulo - 1] = Convert.ToByte((bit_size >> 0x00) & 0xFFul);
                                                        input[chunk_modulo - 2] = Convert.ToByte((bit_size >> 0x08) & 0xFFul);
                                                        input[chunk_modulo - 3] = Convert.ToByte((bit_size >> 0x10) & 0xFFul);
                                                        input[chunk_modulo - 4] = Convert.ToByte((bit_size >> 0x18) & 0xFFul);
                                                        input[chunk_modulo - 5] = Convert.ToByte((bit_size >> 0x20) & 0xFFul);
                                                        input[chunk_modulo - 6] = Convert.ToByte((bit_size >> 0x28) & 0xFFul);
                                                        input[chunk_modulo - 7] = Convert.ToByte((bit_size >> 0x30) & 0xFFul);
                                                        input[chunk_modulo - 8] = Convert.ToByte((bit_size >> 0x38) & 0xFFul);
                                                    }
                                        
                                                    // Copy into w[0..15]
                                                    int copy_index = 0;
                                                    for (; copy_index < 16; copy_index++)
                                                    {
                                                        message_schedule[copy_index] = 0ul;
                                                        for (int i = 0; i < word_bytes; i++)
                                                        {
                                                            message_schedule[copy_index] = (message_schedule[copy_index] << 8) | input[(copy_index * word_bytes) + i];
                                                        }
                                        
                                                        message_schedule[copy_index] = message_schedule[copy_index] & size_mask;
                                                    }
                                                    // Extend
                                                    for(; copy_index < round_count; copy_index++) {
                                                        ulong s0_read = message_schedule[copy_index - 15];
                                                        ulong s1_read = message_schedule[copy_index - 2];
                                        
                                                        message_schedule[copy_index] = (
                                                            message_schedule[copy_index - 16] +
                                                            (((s0_read >> sums[0]) | (s0_read << word_size - sums[0])) ^ ((s0_read >> sums[1]) | (s0_read << word_size - sums[1])) ^ (s0_read >> sums[2])) + // s0
                                                            message_schedule[copy_index - 7] +
                                                            (((s1_read >> sums[3]) | (s1_read << word_size - sums[3])) ^ ((s1_read >> sums[4]) | (s1_read << word_size - sums[4])) ^ (s1_read >> sums[5])) // s1
                                                        ) & size_mask;
                                                    }
                                        
                                                    // temp vars
                                                    ulong temp1, temp2;
                                                    // work is equivalent to a, b, c, d, e, f, g, h
                                                    // This copies work from h0, h1, h2, h3, h4, h5, h6, h7
                                                    ulong[] work = new ulong[8];
                                                    working_variables.CopyTo(work, 0);
                                        
                                                    // Compression function main loop
                                                    for (copy_index = 0; copy_index < round_count; copy_index++)
                                                    {
                                                        ulong ep1 = ((work[4] >> sigmas[3]) | (work[4] << word_size - sigmas[3])) ^ ((work[4] >> sigmas[4]) | (work[4] << word_size - sigmas[4])) ^ ((work[4] >> sigmas[5]) | (work[4] << word_size - sigmas[5]));
                                                        ulong ch = (work[4] & work[5]) ^ ((size_mask ^ work[4]) & work[6]);
                                                        ulong ep0 = ((work[0] >> sigmas[0]) | (work[0] << word_size - sigmas[0])) ^ ((work[0] >> sigmas[1]) | (work[0] << word_size - sigmas[1])) ^ ((work[0] >> sigmas[2]) | (work[0] << word_size - sigmas[2]));
                                                        ulong maj = (work[0] & work[1]) ^ (work[0] & work[2]) ^ (work[1] & work[2]);
                                                        temp1 = work[7] + ep1 + ch + constants[copy_index] + message_schedule[copy_index];
                                                        temp2 = ep0 + maj;
                                                        work[7] = work[6];
                                                        work[6] = work[5];
                                                        work[5] = work[4];
                                                        work[4] = (work[3] + temp1) & size_mask;
                                                        work[3] = work[2];
                                                        work[2] = work[1];
                                                        work[1] = work[0];
                                                        work[0] = (temp1 + temp2) & size_mask;
                                                    }
                                        
                                                    for (copy_index = 0; copy_index < 8; copy_index++)
                                                        working_variables[copy_index] = (working_variables[copy_index] + work[copy_index]) & size_mask;
                                                }
                                        
                                                // Finalization
                                                string output = "";
                                        
                                                for (int character_index = 0; character_index < output_segments; character_index++) {
                                                    output += string.Format(output_format, working_variables[character_index]);
                                                }
                                        
                                                return output;
                                            }
                                        
                                            /* SHA224 */
                                            public string SHA224_Bytes(byte[] data)
                                            {
                                                return SHA2_Core(data, sha224_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 7);
                                            }
                                        
                                            public string SHA224_UTF8(string text)
                                            {
                                                return SHA2_Core(ToUTF8(text.ToCharArray()), sha224_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 7);
                                            }
                                        
                                            /* SHA256 */
                                            public string SHA256_Bytes(byte[] data)
                                            {
                                                return SHA2_Core(data, sha256_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 8);
                                            }
                                        
                                            public string SHA256_UTF8(string text)
                                            {
                                                return SHA2_Core(ToUTF8(text.ToCharArray()), sha256_init, sha256_constants, sha256_sums, sha256_sigmas, 0xFFFFFFFFul, 32, 64, 8, 64, "{0:x8}", 8);
                                            }
                                        
                                            /* SHA384 */
                                            public string SHA384_Bytes(byte[] data)
                                            {
                                                return SHA2_Core(data, sha384_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 6);
                                            }
                                        
                                            public string SHA384_UTF8(string text)
                                            {
                                                return SHA2_Core(ToUTF8(text.ToCharArray()), sha384_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 6);
                                            }
                                        
                                            /* SHA512 */
                                            public string SHA512_Bytes(byte[] data)
                                            {
                                                return SHA2_Core(data, sha512_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 8);
                                            }
                                        
                                            public string SHA512_UTF8(string text)
                                            {
                                                return SHA2_Core(ToUTF8(text.ToCharArray()), sha512_init, sha512_constants, sha512_sums, sha512_sigmas, 0xFFFFFFFFFFFFFFFFul, 64, 128, 16, 80, "{0:x16}", 8);
                                            }
                                        }
                                        
                                        
                                        #if !COMPILER_UDONSHARP && UNITY_EDITOR
                                        
                                        [CustomEditor(typeof(UdonHashLib))]
                                        public class UdonHashLibEditor : Editor
                                        {
                                            private string inputString = "";
                                        
                                            public override void OnInspectorGUI()
                                            {
                                                // Draws the default convert to UdonBehaviour button, program asset field, sync settings, etc.
                                                if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) return;
                                        
                                                UdonHashLib inspectorBehaviour = (UdonHashLib)target;
                                        
                                                if (!EditorApplication.isPlaying)
                                                    EditorGUILayout.HelpBox("Enter play mode to run tests", MessageType.Info);
                                        
                                                EditorGUI.BeginDisabledGroup(!EditorApplication.isPlaying);
                                        
                                                // A simple string field modification with Undo handling
                                                EditorGUILayout.LabelField("Input for hash");
                                                inputString = EditorGUILayout.TextArea(inputString);
                                        
                                                if (GUILayout.Button("Calculate hashes"))
                                                {
                                        
                                                    CheckHash(inputString, true);
                                                }
                                        
                                                if (GUILayout.Button("Run test suite"))
                                                {
                                                    int testBatch = 4096;
                                                    int testCount = 0, succeeded = 0;
                                        
                                                    System.Random random = new System.Random();
                                                    string chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~\n";
                                                    string buffer = new string(Enumerable.Repeat(chars, testBatch).Select(s => s[random.Next(s.Length)]).ToArray());
                                        
                                                    Debug.Log($"Buffer generated for ASCII testing: {buffer}");
                                        
                                                    for (int i = 0; i < testBatch; i++)
                                                    {
                                                        string test = buffer.Substring(random.Next(buffer.Length - i), i);
                                        
                                                        testCount++;
                                                        if (CheckHash(test))
                                                            succeeded++;
                                                    }
                                        
                                                    // Japanese character (UTF-8) test
                                                    chars = "\u3042\u3044\u3046\u3048\u304a\u304b\u304d\u304f\u3051\u3053\u3055\u3057\u3059\u305b\u305d\u305f\u3061\u3064\u3066\u3068\u306a\u306b\u306c\u306d\u306e\u306f\u3072\u3075\u3078\u307b\u307e\u307f\u3080\u3081\u3082\u3084\u3086\u3088\u3089\u308a\u308b\u308c\u308d\u308f\u3090\u3091\u3092\u3093\u30a2\u30a4\u30a6\u30a8\u30aa\u30ab\u30ad\u30af\u30b1\u30b3\u30b5\u30b7\u30b9\u30bb\u30bd\u30bf\u30c1\u30c4\u30c6\u30c8\u30ca\u30cb\u30cc\u30cd\u30ce\u30cf\u30d2\u30d5\u30d8\u30db\u30de\u30df\u30e0\u30e1\u30e2\u30e4\u30e6\u30e8\u30e9\u30ea\u30eb\u30ec\u30ed\u30ef\u30f0\u30f1\u30f2\u30f3";
                                                    buffer = new string(Enumerable.Repeat(chars, testBatch).Select(s => s[random.Next(s.Length)]).ToArray());
                                        
                                                    Debug.Log($"Buffer generated for JPN/UTF-8 testing: {buffer}");
                                        
                                                    for (int i = 0; i < testBatch; i++)
                                                    {
                                                        string test = buffer.Substring(random.Next(buffer.Length - i), i);
                                        
                                                        testCount++;
                                                        if (CheckHash(test))
                                                            succeeded++;
                                                    }
                                        
                                                    EditorUtility.DisplayDialog("Results", $"{testCount} tests ran, {succeeded} succeeded in all hashes", "OK");
                                                }
                                        
                                                EditorGUI.EndDisabledGroup();
                                            }
                                        
                                            private bool CheckHash(string input, bool showDialog = false, bool showDialogWhenFailed = true)
                                            {
                                                UdonHashLib inspectorBehaviour = (UdonHashLib)target;
                                        
                                                string md5_udon = inspectorBehaviour.MD5_UTF8(input);
                                                string sha1_udon = inspectorBehaviour.SHA1_UTF8(input);
                                                string sha224_udon = inspectorBehaviour.SHA224_UTF8(input);
                                                string sha256_udon = inspectorBehaviour.SHA256_UTF8(input);
                                                string sha384_udon = inspectorBehaviour.SHA384_UTF8(input);
                                                string sha512_udon = inspectorBehaviour.SHA512_UTF8(input);
                                        
                                                string md5_csharp = GenerateNonUdon(input, System.Security.Cryptography.MD5.Create());
                                                string sha1_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA1.Create());
                                                string sha256_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA256.Create());
                                                string sha384_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA384.Create());
                                                string sha512_csharp = GenerateNonUdon(input, System.Security.Cryptography.SHA512.Create());
                                        
                                                bool allPass = (
                                                    md5_udon == md5_csharp &&
                                                    sha1_udon == sha1_csharp &&
                                                    sha256_udon == sha256_csharp &&
                                                    sha384_udon == sha384_csharp &&
                                                    sha512_udon == sha512_csharp
                                                );
                                        
                                                if (showDialog || (!allPass && showDialogWhenFailed))
                                                    EditorUtility.DisplayDialog("Hashes", string.Join("\n", new string[] {
                                                        input,
                                                        "",
                                                        $"md5 [{(md5_udon == md5_csharp ? "PASS" : "FAIL")}]: {md5_udon}",
                                                        $"sha1 [{(sha1_udon == sha1_csharp ? "PASS" : "FAIL")}]: {sha1_udon}",
                                                        $"sha224: {sha224_udon}", // No system impl for this
                                                        $"sha256 [{(sha256_udon == sha256_csharp ? "PASS" : "FAIL")}]: {sha256_udon}",
                                                        $"sha384 [{(sha384_udon == sha384_csharp ? "PASS" : "FAIL")}]: {sha384_udon}",
                                                        $"sha512 [{(sha512_udon == sha512_csharp ? "PASS" : "FAIL")}]: {sha512_udon}",
                                                    }), "OK");
                                        
                                                return allPass;
                                            }
                                        
                                            private string GenerateNonUdon(string input, System.Security.Cryptography.HashAlgorithm algorithm)
                                            {
                                                using (var hash = algorithm)
                                                {
                                                    var bytes = hash.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input));
                                        
                                                    string output = "";
                                        
                                                    foreach (byte x in bytes)
                                                    {
                                                        output += string.Format("{0:x2}", x);
                                                    }
                                        
                                                    return output;
                                                }
                                            }
                                        }
                                        #endif
                                        
                                        
                                        RoseVelvetteR
                                        RoseVelvetteR
                                        RoseVelvette
                                        wrote on last edited by
                                        #172

                                        @Worcestershire im sorry but what kind of coding is that??

                                        is there a simple number code to put in the key pad in nero VIP mmd world??

                                        WorcestershireW 1 Reply Last reply
                                        1
                                        • RoseVelvetteR RoseVelvette

                                          @Worcestershire im sorry but what kind of coding is that??

                                          is there a simple number code to put in the key pad in nero VIP mmd world??

                                          WorcestershireW
                                          WorcestershireW
                                          Worcestershire
                                          wrote on last edited by
                                          #173

                                          @VelvetteCakeYT not unless someone programs a code generator ¯\_(ツ)_/¯
                                          The code is generated based on your VRChat user, so there won't be a simple code to put in the keypad.

                                          RoseVelvetteR 1 Reply Last reply
                                          0

                                          Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                                          Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                                          With your input, this post could be even better 💗

                                          Register Login
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular