Пример #1
0
        /// <summary>
        /// Creates a new qryptext instance. <para> </para>
        /// Make sure to create one only once and cache it as needed, since loading the DLLs into memory can negatively affect the performance.
        /// <param name="sharedLibPathOverride">[OPTIONAL] Don't look for a <c>lib/</c> folder and directly use this path as a pre-resolved, platform-specific shared lib/DLL file path. Pass this if you want to manually handle the various platform's paths yourself.</param>
        /// </summary>
        public QryptextSharpContext(string sharedLibPathOverride = null)
        {
            string os;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                os        = "windows";
                loadUtils = new SharedLibLoadUtilsWindows();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                os        = "linux";
                loadUtils = new SharedLibLoadUtilsLinux();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                os        = "mac";
                loadUtils = new SharedLibLoadUtilsMac();
            }
            else
            {
                throw new PlatformNotSupportedException("Unsupported OS");
            }

            if (string.IsNullOrEmpty(sharedLibPathOverride))
            {
                StringBuilder pathBuilder = new StringBuilder(256);
                pathBuilder.Append("lib/");

                switch (RuntimeInformation.ProcessArchitecture)
                {
                case Architecture.X64:
                    pathBuilder.Append("x64/");
                    break;

                case Architecture.X86:
                    pathBuilder.Append("x86/");
                    break;

                case Architecture.Arm:
                    pathBuilder.Append("armeabi-v7a/");
                    break;

                case Architecture.Arm64:
                    pathBuilder.Append("arm64-v8a/");
                    break;
                }

                if (!Directory.Exists(pathBuilder.ToString()))
                {
                    throw new PlatformNotSupportedException($"Qryptext shared library not found in {pathBuilder} and/or unsupported CPU architecture. Please don't forget to copy the Qryptext shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory.  https://github.com/GlitchedPolygons/qryptext/tree/master/csharp/lib/");
                }

                pathBuilder.Append(os);
                pathBuilder.Append('/');

                string[] l = Directory.GetFiles(pathBuilder.ToString());
                if (l == null || l.Length != 1)
                {
                    throw new FileLoadException("There should only be exactly one shared library file per supported platform!");
                }

                pathBuilder.Append(Path.GetFileName(l[0]));
                LoadedLibraryPath = Path.GetFullPath(pathBuilder.ToString());
                pathBuilder.Clear();
            }
            else
            {
                LoadedLibraryPath = sharedLibPathOverride;
            }

            lib = loadUtils.LoadLibrary(LoadedLibraryPath);
            if (lib == IntPtr.Zero)
            {
                goto hell;
            }


            IntPtr enableFprintf = loadUtils.GetProcAddress(lib, "qryptext_enable_fprintf");

            if (enableFprintf == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr disableFprintf = loadUtils.GetProcAddress(lib, "qryptext_disable_fprintf");

            if (disableFprintf == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr isFprintfEnabled = loadUtils.GetProcAddress(lib, "qryptext_is_fprintf_enabled");

            if (isFprintfEnabled == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getVersionNumber = loadUtils.GetProcAddress(lib, "qryptext_get_version_number");

            if (getVersionNumber == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getVersionNumberString = loadUtils.GetProcAddress(lib, "qryptext_get_version_number_string");

            if (getVersionNumberString == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr devUrandom = loadUtils.GetProcAddress(lib, "qryptext_dev_urandom");

            if (devUrandom == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr calcEncryptionOutputLength = loadUtils.GetProcAddress(lib, "qryptext_calc_encryption_output_length");

            if (calcEncryptionOutputLength == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr calcBase64Length = loadUtils.GetProcAddress(lib, "qryptext_calc_base64_length");

            if (calcBase64Length == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr genKyber1K = loadUtils.GetProcAddress(lib, "qryptext_kyber1024_generate_keypair");

            if (genKyber1K == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr genFalcon1K = loadUtils.GetProcAddress(lib, "qryptext_falcon1024_generate_keypair");

            if (genFalcon1K == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr encrypt = loadUtils.GetProcAddress(lib, "qryptext_encrypt");

            if (encrypt == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr decrypt = loadUtils.GetProcAddress(lib, "qryptext_decrypt");

            if (decrypt == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr sign = loadUtils.GetProcAddress(lib, "qryptext_sign");

            if (sign == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr verify = loadUtils.GetProcAddress(lib, "qryptext_verify");

            if (verify == IntPtr.Zero)
            {
                goto hell;
            }

            enableFprintfDelegate              = Marshal.GetDelegateForFunctionPointer <EnableFprintfDelegate>(enableFprintf);
            disableFprintfDelegate             = Marshal.GetDelegateForFunctionPointer <DisableFprintfDelegate>(disableFprintf);
            isFprintfEnabledDelegate           = Marshal.GetDelegateForFunctionPointer <IsFprintfEnabledDelegate>(isFprintfEnabled);
            getVersionNumberDelegate           = Marshal.GetDelegateForFunctionPointer <GetVersionNumberDelegate>(getVersionNumber);
            getVersionNumberStringDelegate     = Marshal.GetDelegateForFunctionPointer <GetVersionNumberStringDelegate>(getVersionNumberString);
            devUrandomDelegate                 = Marshal.GetDelegateForFunctionPointer <DevUrandomDelegate>(devUrandom);
            calcEncryptionOutputLengthDelegate = Marshal.GetDelegateForFunctionPointer <CalcEncryptionOutputLengthDelegate>(calcEncryptionOutputLength);
            calcBase64LengthDelegate           = Marshal.GetDelegateForFunctionPointer <CalcBase64LengthDelegate>(calcBase64Length);
            generateKyber1024KeyPairDelegate   = Marshal.GetDelegateForFunctionPointer <GenerateKyber1024KeyPairDelegate>(genKyber1K);
            generateFalcon1024KeyPairDelegate  = Marshal.GetDelegateForFunctionPointer <GenerateFalcon1024KeyPairDelegate>(genFalcon1K);
            encryptDelegate = Marshal.GetDelegateForFunctionPointer <EncryptDelegate>(encrypt);
            decryptDelegate = Marshal.GetDelegateForFunctionPointer <DecryptDelegate>(decrypt);
            signDelegate    = Marshal.GetDelegateForFunctionPointer <SignDelegate>(sign);
            verifyDelegate  = Marshal.GetDelegateForFunctionPointer <VerifyDelegate>(verify);

            return;

hell:
            throw new Exception($"Failed to load one or more functions from the shared library \"{LoadedLibraryPath}\"!");
        }
Пример #2
0
        /// <summary>
        /// Creates a new ccrush# instance. <para> </para>
        /// Make sure to create one only once and cache it as needed, since loading the DLLs into memory can negatively affect the performance.
        /// <param name="sharedLibPathOverride">[OPTIONAL] Don't look for a <c>lib/</c> folder and directly use this path as a pre-resolved, platform-specific shared lib/DLL file path. Pass this if you want to handle the various platform's paths yourself.</param>
        /// </summary>
        public CcrushSharpContext(string sharedLibPathOverride = null)
        {
            string os;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                os        = "windows";
                loadUtils = new SharedLibLoadUtilsWindows();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                os        = "linux";
                loadUtils = new SharedLibLoadUtilsLinux();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                os        = "mac";
                loadUtils = new SharedLibLoadUtilsMac();
            }
            else
            {
                throw new PlatformNotSupportedException("Unsupported OS");
            }

            if (!string.IsNullOrEmpty(sharedLibPathOverride))
            {
                LoadedLibraryPath = sharedLibPathOverride;
            }
            else
            {
                string cpu;

                switch (RuntimeInformation.ProcessArchitecture)
                {
                case Architecture.X64:
                    cpu = "x64";
                    break;

                case Architecture.X86:
                    cpu = "x86";
                    break;

                case Architecture.Arm:
                    cpu = "armeabi-v7a";
                    break;

                case Architecture.Arm64:
                    cpu = "arm64-v8a";
                    break;

                default:
                    throw new PlatformNotSupportedException("CPU Architecture not supported!");
                }

                string path = Path.Combine(Path.GetFullPath(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location) ?? "."), "lib", cpu, os);

                if (!Directory.Exists(path))
                {
                    throw new PlatformNotSupportedException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }

                bool found = false;
                foreach (string file in Directory.GetFiles(path))
                {
                    if (file.ToLower().Contains("ccrush"))
                    {
                        LoadedLibraryPath = Path.GetFullPath(Path.Combine(path, file));
                        found             = true;
                        break;
                    }
                }

                if (!found)
                {
                    throw new FileLoadException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }
            }

            lib = loadUtils.LoadLibrary(LoadedLibraryPath);
            if (lib == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr compress = loadUtils.GetProcAddress(lib, "ccrush_compress");

            if (compress == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr decompress = loadUtils.GetProcAddress(lib, "ccrush_decompress");

            if (decompress == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr free = loadUtils.GetProcAddress(lib, "ccrush_free");

            if (free == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getVersionNumber = loadUtils.GetProcAddress(lib, "ccrush_get_version_nr");

            if (getVersionNumber == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getVersionNumberString = loadUtils.GetProcAddress(lib, "ccrush_get_version_nr_string");

            if (getVersionNumberString == IntPtr.Zero)
            {
                goto hell;
            }

            compressDelegate   = Marshal.GetDelegateForFunctionPointer <CompressDelegate>(compress);
            decompressDelegate = Marshal.GetDelegateForFunctionPointer <DecompressDelegate>(decompress);
            freeDelegate       = Marshal.GetDelegateForFunctionPointer <FreeDelegate>(free);

            var getVersionNumberDelegate       = Marshal.GetDelegateForFunctionPointer <GetVersionNumberDelegate>(getVersionNumber);
            var getVersionNumberStringDelegate = Marshal.GetDelegateForFunctionPointer <GetVersionNumberStringDelegate>(getVersionNumberString);

            Version       = getVersionNumberDelegate.Invoke();
            VersionString = Marshal.PtrToStringAnsi(getVersionNumberStringDelegate.Invoke());

            return;

hell:
            throw new Exception($"Failed to load one or more functions from the shared library \"{LoadedLibraryPath}\"!");
        }
Пример #3
0
        public OrlpEd25519Context(string sharedLibPathOverride = null)
        {
            string os;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                os        = "windows";
                loadUtils = new SharedLibLoadUtilsWindows();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                os        = "linux";
                loadUtils = new SharedLibLoadUtilsLinux();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                os        = "mac";
                loadUtils = new SharedLibLoadUtilsMac();
            }
            else
            {
                throw new PlatformNotSupportedException("Unsupported OS");
            }

            if (!string.IsNullOrEmpty(sharedLibPathOverride))
            {
                LoadedLibraryPath = sharedLibPathOverride;
            }
            else
            {
                string cpu = RuntimeInformation.ProcessArchitecture switch
                {
                    Architecture.X64 => "x64",
                    Architecture.X86 => "x86",
                    Architecture.Arm => "armeabi-v7a",
                    Architecture.Arm64 => "arm64-v8a",
                    _ => throw new PlatformNotSupportedException("CPU Architecture not supported!")
                };

                string path = Path.Combine(Path.GetFullPath(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location) ?? "."), "lib", cpu, os);

                if (!Directory.Exists(path))
                {
                    throw new PlatformNotSupportedException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }

                bool found = false;
                foreach (string file in Directory.GetFiles(path))
                {
                    if (file.ToLower().Contains("ed25519"))
                    {
                        LoadedLibraryPath = Path.GetFullPath(Path.Combine(path, file));
                        found             = true;
                        break;
                    }
                }

                if (!found)
                {
                    throw new FileLoadException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }
            }

            lib = loadUtils.LoadLibrary(LoadedLibraryPath);
            if (lib == IntPtr.Zero)
            {
                goto hell; // The gates of hell opened, and out came the beginning of marshalling, DLL hell and C# interop...
            }

            IntPtr createSeed = loadUtils.GetProcAddress(lib, "ed25519_create_seed");

            if (createSeed == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr createKeypair = loadUtils.GetProcAddress(lib, "ed25519_create_keypair");

            if (createKeypair == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr sign = loadUtils.GetProcAddress(lib, "ed25519_sign");

            if (sign == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr verify = loadUtils.GetProcAddress(lib, "ed25519_verify");

            if (verify == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr addScalar = loadUtils.GetProcAddress(lib, "ed25519_add_scalar");

            if (addScalar == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr keyExchange = loadUtils.GetProcAddress(lib, "ed25519_key_exchange");

            if (keyExchange == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr keyConvert = loadUtils.GetProcAddress(lib, "ed25519_key_convert_ref10_to_orlp");

            if (keyConvert == IntPtr.Zero)
            {
                goto hell;
            }

            createSeedDelegate         = Marshal.GetDelegateForFunctionPointer <CreateSeedDelegate>(createSeed);
            createKeypairDelegate      = Marshal.GetDelegateForFunctionPointer <CreateKeypairDelegate>(createKeypair);
            signDelegate               = Marshal.GetDelegateForFunctionPointer <SignDelegate>(sign);
            verifyDelegate             = Marshal.GetDelegateForFunctionPointer <VerifyDelegate>(verify);
            addScalarDelegate          = Marshal.GetDelegateForFunctionPointer <AddScalarDelegate>(addScalar);
            keyExchangeDelegate        = Marshal.GetDelegateForFunctionPointer <KeyExchangeDelegate>(keyExchange);
            ref10KeyConversionDelegate = Marshal.GetDelegateForFunctionPointer <Ref10KeyConversionDelegate>(keyConvert);

            return;

hell:
            throw new Exception($"Failed to load one or more functions from the orlp-ed25519 shared library \"{LoadedLibraryPath}\"!");
        }
Пример #4
0
        /// <summary>
        /// Creates a new pwcrypt instance. <para> </para>
        /// Make sure to create one only once and cache it as needed, since loading the DLLs into memory can negatively affect the performance.
        /// <param name="sharedLibPathOverride">[OPTIONAL] Don't look for a <c>lib/</c> folder and directly use this path as a pre-resolved, platform-specific shared lib/DLL file path. Pass this if you want to handle the various platform's paths yourself.</param>
        /// </summary>
        public PwcryptSharpContext(string sharedLibPathOverride = null)
        {
            string os;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                os        = "windows";
                loadUtils = new SharedLibLoadUtilsWindows();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                os        = "linux";
                loadUtils = new SharedLibLoadUtilsLinux();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                os        = "mac";
                loadUtils = new SharedLibLoadUtilsMac();
            }
            else
            {
                throw new PlatformNotSupportedException("Unsupported OS");
            }

            if (!string.IsNullOrEmpty(sharedLibPathOverride))
            {
                LoadedLibraryPath = sharedLibPathOverride;
            }
            else
            {
                string cpu = RuntimeInformation.ProcessArchitecture switch
                {
                    Architecture.X64 => "x64",
                    Architecture.X86 => "x86",
                    Architecture.Arm => "armeabi-v7a",
                    Architecture.Arm64 => "arm64-v8a",
                    _ => throw new PlatformNotSupportedException("CPU Architecture not supported!")
                };

                string path = Path.Combine(Path.GetFullPath(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location) ?? "."), "lib", cpu, os);

                if (!Directory.Exists(path))
                {
                    throw new PlatformNotSupportedException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }

                bool found = false;
                foreach (string file in Directory.GetFiles(path))
                {
                    if (file.ToLower().Contains("pwcrypt"))
                    {
                        LoadedLibraryPath = Path.GetFullPath(Path.Combine(path, file));
                        found             = true;
                        break;
                    }
                }

                if (!found)
                {
                    throw new FileLoadException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }
            }

            lib = loadUtils.LoadLibrary(LoadedLibraryPath);
            if (lib == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr enableFprintf = loadUtils.GetProcAddress(lib, "pwcrypt_enable_fprintf");

            if (enableFprintf == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr disableFprintf = loadUtils.GetProcAddress(lib, "pwcrypt_disable_fprintf");

            if (disableFprintf == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr isFprintfEnabled = loadUtils.GetProcAddress(lib, "pwcrypt_is_fprintf_enabled");

            if (isFprintfEnabled == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getVersionNumber = loadUtils.GetProcAddress(lib, "pwcrypt_get_version_nr");

            if (getVersionNumber == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getVersionNumberString = loadUtils.GetProcAddress(lib, "pwcrypt_get_version_nr_string");

            if (getVersionNumberString == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getArgon2VersionNumber = loadUtils.GetProcAddress(lib, "pwcrypt_get_argon2_version_nr");

            if (getArgon2VersionNumber == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr devUrandom = loadUtils.GetProcAddress(lib, "dev_urandom");

            if (devUrandom == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr getFilesize = loadUtils.GetProcAddress(lib, "pwcrypt_get_filesize");

            if (getFilesize == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr assessPasswordStrength = loadUtils.GetProcAddress(lib, "pwcrypt_assess_password_strength");

            if (assessPasswordStrength == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr encrypt = loadUtils.GetProcAddress(lib, "pwcrypt_encrypt");

            if (encrypt == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr decrypt = loadUtils.GetProcAddress(lib, "pwcrypt_decrypt");

            if (decrypt == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr free = loadUtils.GetProcAddress(lib, "pwcrypt_free");

            if (free == IntPtr.Zero)
            {
                goto hell;
            }

            enableFprintfDelegate          = Marshal.GetDelegateForFunctionPointer <EnableFprintfDelegate>(enableFprintf);
            disableFprintfDelegate         = Marshal.GetDelegateForFunctionPointer <DisableFprintfDelegate>(disableFprintf);
            isFprintfEnabledDelegate       = Marshal.GetDelegateForFunctionPointer <IsFprintfEnabledDelegate>(isFprintfEnabled);
            getVersionNumberDelegate       = Marshal.GetDelegateForFunctionPointer <GetVersionNumberDelegate>(getVersionNumber);
            getVersionNumberStringDelegate = Marshal.GetDelegateForFunctionPointer <GetVersionNumberStringDelegate>(getVersionNumberString);
            getArgon2VersionNumberDelegate = Marshal.GetDelegateForFunctionPointer <GetArgon2VersionNumberDelegate>(getArgon2VersionNumber);
            devUrandomDelegate             = Marshal.GetDelegateForFunctionPointer <DevUrandomDelegate>(devUrandom);
            getFilesizeDelegate            = Marshal.GetDelegateForFunctionPointer <GetFilesizeDelegate>(getFilesize);
            assessPasswordStrengthDelegate = Marshal.GetDelegateForFunctionPointer <AssessPasswordStrengthDelegate>(assessPasswordStrength);
            encryptDelegate = Marshal.GetDelegateForFunctionPointer <EncryptDelegate>(encrypt);
            decryptDelegate = Marshal.GetDelegateForFunctionPointer <DecryptDelegate>(decrypt);
            freeDelegate    = Marshal.GetDelegateForFunctionPointer <FreeDelegate>(free);

            return;

hell:
            throw new Exception($"Failed to load one or more functions from the shared library \"{LoadedLibraryPath}\"!");
        }
Пример #5
0
        /// <summary>
        /// Creates a new Argon2Sharp instance. <para> </para>
        /// Make sure to create one only once and cache it as needed, since loading the DLLs into memory could be, well, not so performant.
        /// <param name="sharedLibPathOverride">[OPTIONAL] Don't look for a <c>lib/</c> folder and directly use this path as a pre-resolved, platform-specific shared lib/DLL file path. Pass this if you want to handle the various platform's paths yourself.</param>
        /// </summary>
        public Argon2SharpContext(string sharedLibPathOverride = null)
        {
            string os;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                os        = "windows";
                loadUtils = new SharedLibLoadUtilsWindows();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                os        = "linux";
                loadUtils = new SharedLibLoadUtilsLinux();
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                os        = "mac";
                loadUtils = new SharedLibLoadUtilsMac();
            }
            else
            {
                throw new PlatformNotSupportedException("Unsupported OS");
            }

            if (!string.IsNullOrEmpty(sharedLibPathOverride))
            {
                LoadedLibraryPath = sharedLibPathOverride;
            }
            else
            {
                string cpu = RuntimeInformation.ProcessArchitecture switch
                {
                    Architecture.X64 => "x64",
                    Architecture.X86 => "x86",
                    Architecture.Arm => "armeabi-v7a",
                    Architecture.Arm64 => "arm64-v8a",
                    _ => throw new PlatformNotSupportedException("CPU Architecture not supported!")
                };

                string path = Path.Combine(Path.GetFullPath(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location) ?? "."), "lib", cpu, os);

                if (!Directory.Exists(path))
                {
                    throw new PlatformNotSupportedException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }

                bool found = false;
                foreach (string file in Directory.GetFiles(path))
                {
                    if (file.ToLower().Contains("argon2"))
                    {
                        LoadedLibraryPath = Path.GetFullPath(Path.Combine(path, file));
                        found             = true;
                        break;
                    }
                }

                if (!found)
                {
                    throw new FileLoadException($"Shared library not found in {path} and/or unsupported CPU architecture. Please don't forget to copy the shared libraries/DLL into the 'lib/{{CPU_ARCHITECTURE}}/{{OS}}/{{SHARED_LIB_FILE}}' folder of your output build directory. ");
                }
            }

            lib = loadUtils.LoadLibrary(LoadedLibraryPath);
            if (lib == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2i_hash_encoded = loadUtils.GetProcAddress(lib, "argon2i_hash_encoded");

            if (argon2i_hash_encoded == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2d_hash_encoded = loadUtils.GetProcAddress(lib, "argon2d_hash_encoded");

            if (argon2d_hash_encoded == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2id_hash_encoded = loadUtils.GetProcAddress(lib, "argon2id_hash_encoded");

            if (argon2id_hash_encoded == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2i_hash_raw = loadUtils.GetProcAddress(lib, "argon2i_hash_raw");

            if (argon2i_hash_raw == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2d_hash_raw = loadUtils.GetProcAddress(lib, "argon2d_hash_raw");

            if (argon2d_hash_raw == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2id_hash_raw = loadUtils.GetProcAddress(lib, "argon2id_hash_raw");

            if (argon2id_hash_raw == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2i_verify = loadUtils.GetProcAddress(lib, "argon2i_verify");

            if (argon2i_verify == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2d_verify = loadUtils.GetProcAddress(lib, "argon2d_verify");

            if (argon2d_verify == IntPtr.Zero)
            {
                goto hell;
            }

            IntPtr argon2id_verify = loadUtils.GetProcAddress(lib, "argon2id_verify");

            if (argon2id_verify == IntPtr.Zero)
            {
                goto hell;
            }

            argon2i_HashEncoded_Delegate  = Marshal.GetDelegateForFunctionPointer <Argon2_HashEncoded_Delegate>(argon2i_hash_encoded);
            argon2d_HashEncoded_Delegate  = Marshal.GetDelegateForFunctionPointer <Argon2_HashEncoded_Delegate>(argon2d_hash_encoded);
            argon2id_HashEncoded_Delegate = Marshal.GetDelegateForFunctionPointer <Argon2_HashEncoded_Delegate>(argon2id_hash_encoded);
            argon2i_HashRaw_Delegate      = Marshal.GetDelegateForFunctionPointer <Argon2_HashRaw_Delegate>(argon2i_hash_raw);
            argon2d_HashRaw_Delegate      = Marshal.GetDelegateForFunctionPointer <Argon2_HashRaw_Delegate>(argon2d_hash_raw);
            argon2id_HashRaw_Delegate     = Marshal.GetDelegateForFunctionPointer <Argon2_HashRaw_Delegate>(argon2id_hash_raw);
            argon2i_Verify_Delegate       = Marshal.GetDelegateForFunctionPointer <Argon2_Verify_Delegate>(argon2i_verify);
            argon2d_Verify_Delegate       = Marshal.GetDelegateForFunctionPointer <Argon2_Verify_Delegate>(argon2d_verify);
            argon2id_Verify_Delegate      = Marshal.GetDelegateForFunctionPointer <Argon2_Verify_Delegate>(argon2id_verify);

            return;

hell:
            throw new Exception($"Failed to load one or more functions from the shared library \"{LoadedLibraryPath}\"!");
        }