From d4a54bf4dd52c00a941c394e13d59c02f0a385b0 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Wed, 17 Jun 2026 22:53:09 -0400 Subject: [PATCH 1/4] hashers refactored to use csbindgen --- Directory.Build.props | 5 + cas-core-lib | 2 +- cas-dotnet-sdk/Hashers/Blake2Wrapper.cs | 135 ++++++------------ cas-dotnet-sdk/Hashers/HasherFactory.cs | 14 +- .../Hashers/Linux/Blake2LinuxWrapper.cs | 20 --- .../Hashers/Linux/SHALinuxWrapper.cs | 22 --- cas-dotnet-sdk/Hashers/SHAWrapper.cs | 94 ++++++------ .../Hashers/Types/Blake2HashByteResult.cs | 10 -- .../Hashers/Types/SHAHashByteResult.cs | 10 -- .../Hashers/Windows/Blake2WindowsWrapper.cs | 20 --- .../Hashers/Windows/SHAWindowsWrapper.cs | 22 --- cas-dotnet-sdk/Helpers/NativeByteBuffer.cs | 35 +++++ cas-dotnet-sdk/Helpers/NativePin.cs | 18 +++ cas-dotnet-sdk/cas-dotnet-sdk.csproj | 33 ++++- cas-dotnet-sdk/generated/NativeMethods.g.cs | 74 ++++++++++ 15 files changed, 254 insertions(+), 260 deletions(-) create mode 100644 Directory.Build.props delete mode 100644 cas-dotnet-sdk/Hashers/Linux/Blake2LinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Hashers/Linux/SHALinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Hashers/Types/Blake2HashByteResult.cs delete mode 100644 cas-dotnet-sdk/Hashers/Types/SHAHashByteResult.cs delete mode 100644 cas-dotnet-sdk/Hashers/Windows/Blake2WindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Hashers/Windows/SHAWindowsWrapper.cs create mode 100644 cas-dotnet-sdk/Helpers/NativeByteBuffer.cs create mode 100644 cas-dotnet-sdk/Helpers/NativePin.cs create mode 100644 cas-dotnet-sdk/generated/NativeMethods.g.cs diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..743d72b --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,5 @@ + + + $(NoWarn);1591 + + \ No newline at end of file diff --git a/cas-core-lib b/cas-core-lib index 7932d6e..8f30188 160000 --- a/cas-core-lib +++ b/cas-core-lib @@ -1 +1 @@ -Subproject commit 7932d6e8569f539973b3953b17bdee2b3ff77c19 +Subproject commit 8f301881ed04c7927e0679a0b12036bf39402677 diff --git a/cas-dotnet-sdk/Hashers/Blake2Wrapper.cs b/cas-dotnet-sdk/Hashers/Blake2Wrapper.cs index 2938c86..f7735bf 100644 --- a/cas-dotnet-sdk/Hashers/Blake2Wrapper.cs +++ b/cas-dotnet-sdk/Hashers/Blake2Wrapper.cs @@ -1,134 +1,83 @@ - -using CasDotnetSdk.Hashers.Linux; -using CasDotnetSdk.Hashers.Types; -using CasDotnetSdk.Hashers.Windows; +using CasCoreLib; using CasDotnetSdk.Helpers; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Hashers { - public class Blake2Wrapper : BaseWrapper, IHasherBase + public unsafe class Blake2Wrapper : BaseWrapper, IHasherBase { - /// /// A wrapper class for the Blake2 hashing algorithm. /// public Blake2Wrapper() { - } /// /// Hashes data using the Blake2 512 algorithm. /// - /// - /// - /// - /// - - public byte[] Hash512(byte[] toHash) + public byte[] Hash512(byte[] dataToHash) { - if (toHash == null || toHash.Length == 0) - { - throw new Exception("You must provide data to hash with Blake 2 512"); - } - - - Blake2HashByteResult hashResult = (this._platform == OSPlatform.Linux) ? - Blake2LinuxWrapper.blake2_512_bytes(toHash, toHash.Length) : - Blake2WindowsWrapper.blake2_512_bytes(toHash, toHash.Length); - byte[] result = new byte[hashResult.length]; - Marshal.Copy(hashResult.result_bytes_ptr, result, 0, (int)hashResult.length); - FreeMemoryHelper.FreeBytesMemory(hashResult.result_bytes_ptr); - - - return result; + ThrowIfNull(dataToHash, nameof(dataToHash)); + return Hash(dataToHash, NativeMethods.blake2_512_bytes); } - /// - /// Verifies data using the Blake2 512 algorithm. + /// Hashes data using the Blake2 256 algorithm. /// - /// - /// - /// - /// - /// - - public bool Verify512(byte[] hashedData, byte[] toCompare) + public byte[] Hash256(byte[] dataToHash) { - if (hashedData == null || hashedData.Length == 0) - { - throw new Exception("You must provide previously hashed data to verify with Blake 2 512"); - } - if (toCompare == null || toCompare.Length == 0) - { - throw new Exception("You must provide data to compare to verify with Blake 2 512"); - } - - - bool result = (this._platform == OSPlatform.Linux) ? - Blake2LinuxWrapper.blake2_512_bytes_verify(hashedData, hashedData.Length, toCompare, toCompare.Length) : - Blake2WindowsWrapper.blake2_512_bytes_verify(hashedData, hashedData.Length, toCompare, toCompare.Length); - - - return result; + ThrowIfNull(dataToHash, nameof(dataToHash)); + return Hash(dataToHash, NativeMethods.blake2_256_bytes); } /// - /// Hashes data using the Blake2 256 algorithm. + /// Verifies data using the Blake2 512 algorithm. /// - /// - /// - /// - /// - - public byte[] Hash256(byte[] toHash) + public bool Verify512(byte[] dataToVerify, byte[] hashedData) { - if (toHash == null || toHash.Length == 0) - { - throw new Exception("You must provide an array of allocated data to hash with Blake2 256"); - } - - Blake2HashByteResult hashedResult = (this._platform == OSPlatform.Linux) ? - Blake2LinuxWrapper.blake2_256_bytes(toHash, toHash.Length) : - Blake2WindowsWrapper.blake2_256_bytes(toHash, toHash.Length); - byte[] result = new byte[hashedResult.length]; - Marshal.Copy(hashedResult.result_bytes_ptr, result, 0, result.Length); - FreeMemoryHelper.FreeBytesMemory(hashedResult.result_bytes_ptr); - - - return result; + ThrowIfNull(dataToVerify, nameof(dataToVerify)); + ThrowIfNull(hashedData, nameof(hashedData)); + return Verify(dataToVerify, hashedData, NativeMethods.blake2_512_bytes_verify); } /// /// Verifies data using the Blake2 256 algorithm. /// - /// - /// - /// - /// - /// + public bool Verify256(byte[] dataToVerify, byte[] hashedData) + { + ThrowIfNull(dataToVerify, nameof(dataToVerify)); + ThrowIfNull(hashedData, nameof(hashedData)); + return Verify(dataToVerify, hashedData, NativeMethods.blake2_256_bytes_verify); + } + + private unsafe delegate Blake2HashByteResult HashFn(byte* data, nuint length); + private unsafe delegate bool VerifyFn(byte* data, nuint dataLength, byte* hash, nuint hashLength); - public bool Verify256(byte[] hashedData, byte[] toCompare) + private static unsafe byte[] Hash(byte[] data, HashFn nativeHash) { - if (hashedData == null || hashedData.Length == 0) + fixed (byte* dataPtr = NativePin.Of(data)) { - throw new Exception("You must provide allocated data for the previously hashed data to compare with Blake 2 256"); + Blake2HashByteResult result = nativeHash(dataPtr, (nuint)data.Length); + return NativeByteBuffer.CopyAndFree(result.result_bytes_ptr, result.length); } - if (toCompare == null || toCompare.Length == 0) + } + + private static unsafe bool Verify(byte[] data, byte[] hash, VerifyFn nativeVerify) + { + fixed (byte* dataPtr = NativePin.Of(data)) + fixed (byte* hashPtr = NativePin.Of(hash)) { - throw new Exception("You must provide allocated data for the data to compare with Blake 2 256"); + return nativeVerify(dataPtr, (nuint)data.Length, hashPtr, (nuint)hash.Length); } + } - - bool result = (this._platform == OSPlatform.Linux) ? - Blake2LinuxWrapper.blake2_256_bytes_verify(hashedData, hashedData.Length, toCompare, toCompare.Length) : - Blake2WindowsWrapper.blake2_256_bytes_verify(hashedData, hashedData.Length, toCompare, toCompare.Length); - - - return result; + private static void ThrowIfNull(byte[] value, string paramName) + { + if (value == null) + { + throw new ArgumentNullException(paramName); + } } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/Hashers/HasherFactory.cs b/cas-dotnet-sdk/Hashers/HasherFactory.cs index 5a2a0d1..4f09953 100644 --- a/cas-dotnet-sdk/Hashers/HasherFactory.cs +++ b/cas-dotnet-sdk/Hashers/HasherFactory.cs @@ -1,4 +1,6 @@ -namespace CasDotnetSdk.Hashers +using System; + +namespace CasDotnetSdk.Hashers { public enum IHasherType { @@ -14,17 +16,15 @@ public static class HasherFactory /// public static IHasherBase Get(IHasherType type) { - IHasherBase result = null; switch (type) { case IHasherType.SHA: - result = new SHAWrapper(); - break; + return new SHAWrapper(); case IHasherType.Blake2: - result = new Blake2Wrapper(); - break; + return new Blake2Wrapper(); + default: + throw new ArgumentOutOfRangeException(nameof(type), type, "Unknown hasher type."); } - return result; } } } diff --git a/cas-dotnet-sdk/Hashers/Linux/Blake2LinuxWrapper.cs b/cas-dotnet-sdk/Hashers/Linux/Blake2LinuxWrapper.cs deleted file mode 100644 index dac893d..0000000 --- a/cas-dotnet-sdk/Hashers/Linux/Blake2LinuxWrapper.cs +++ /dev/null @@ -1,20 +0,0 @@ -using CasDotnetSdk.Hashers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hashers.Linux -{ - internal static class Blake2LinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern Blake2HashByteResult blake2_512_bytes(byte[] toHash, int toHashLength); - - [DllImport("libcas_core_lib.so")] - public static extern Blake2HashByteResult blake2_256_bytes(byte[] toHash, int toHashLength); - - [DllImport("libcas_core_lib.so")] - public static extern bool blake2_256_bytes_verify(byte[] hashedData, int hashedDatLength, byte[] toCompare, int toCompareLength); - - [DllImport("libcas_core_lib.so")] - public static extern bool blake2_512_bytes_verify(byte[] hashedData, int hashedDatLength, byte[] toCompare, int toCompareLength); - } -} diff --git a/cas-dotnet-sdk/Hashers/Linux/SHALinuxWrapper.cs b/cas-dotnet-sdk/Hashers/Linux/SHALinuxWrapper.cs deleted file mode 100644 index 0880ee2..0000000 --- a/cas-dotnet-sdk/Hashers/Linux/SHALinuxWrapper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using CasDotnetSdk.Hashers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hashers.Linux -{ - internal static class SHALinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern SHAHashByteResult sha512_bytes(byte[] dataToHash, int dataLength); - - [DllImport("libcas_core_lib.so")] - [return: MarshalAs(UnmanagedType.I1)] - public static extern bool sha512_bytes_verify(byte[] dataToHash, int dataLength, byte[] hashToVerify, int hashToVerifyLength); - - [DllImport("libcas_core_lib.so")] - public static extern SHAHashByteResult sha256_bytes(byte[] dataToHash, int dataLength); - - [DllImport("libcas_core_lib.so")] - [return: MarshalAs(UnmanagedType.I1)] - public static extern bool sha256_bytes_verify(byte[] dataToHash, int dataLength, byte[] hashToVerify, int hashToVerifyLength); - } -} diff --git a/cas-dotnet-sdk/Hashers/SHAWrapper.cs b/cas-dotnet-sdk/Hashers/SHAWrapper.cs index bddce18..c40752e 100644 --- a/cas-dotnet-sdk/Hashers/SHAWrapper.cs +++ b/cas-dotnet-sdk/Hashers/SHAWrapper.cs @@ -1,16 +1,11 @@ - -using CasDotnetSdk.Hashers.Linux; -using CasDotnetSdk.Hashers.Types; -using CasDotnetSdk.Hashers.Windows; +using CasCoreLib; using CasDotnetSdk.Helpers; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Hashers { - public class SHAWrapper : BaseWrapper, IHasherBase + public unsafe class SHAWrapper : BaseWrapper, IHasherBase { - /// /// A wrapper class for the SHA3 256 and 512 hashing algorithms. /// @@ -21,77 +16,68 @@ public SHAWrapper() /// /// Hashes data using the SHA3 512 algorithm. /// - /// - /// - /// - /// - public byte[] Hash512(byte[] dataToHash) { - SHAHashByteResult hashedPtr = (this._platform == OSPlatform.Linux) ? - SHALinuxWrapper.sha512_bytes(dataToHash, dataToHash.Length) : - SHAWindowsWrapper.sha512_bytes(dataToHash, dataToHash.Length); - byte[] result = new byte[hashedPtr.length]; - Marshal.Copy(hashedPtr.result_bytes_ptr, result, 0, (int)hashedPtr.length); - FreeMemoryHelper.FreeBytesMemory(hashedPtr.result_bytes_ptr); - - - return result; + ThrowIfNull(dataToHash, nameof(dataToHash)); + return Hash(dataToHash, NativeMethods.sha512_bytes); } /// /// Hashes data using the SHA3 256 algorithm. /// - /// - /// - /// - /// - public byte[] Hash256(byte[] dataToHash) { - SHAHashByteResult hashedPtr = (this._platform == OSPlatform.Linux) ? - SHALinuxWrapper.sha256_bytes(dataToHash, dataToHash.Length) : - SHAWindowsWrapper.sha256_bytes(dataToHash, dataToHash.Length); - byte[] result = new byte[hashedPtr.length]; - Marshal.Copy(hashedPtr.result_bytes_ptr, result, 0, (int)hashedPtr.length); - FreeMemoryHelper.FreeBytesMemory(hashedPtr.result_bytes_ptr); - return result; + ThrowIfNull(dataToHash, nameof(dataToHash)); + return Hash(dataToHash, NativeMethods.sha256_bytes); } /// /// Verifies data using the SHA3 512 algorithm. /// - /// - /// - /// - /// - /// - public bool Verify512(byte[] dataToVerify, byte[] hashedData) { - bool result = (this._platform == OSPlatform.Linux) ? - SHALinuxWrapper.sha512_bytes_verify(dataToVerify, dataToVerify.Length, hashedData, hashedData.Length) : - SHAWindowsWrapper.sha512_bytes_verify(dataToVerify, dataToVerify.Length, hashedData, hashedData.Length); - return result; + ThrowIfNull(dataToVerify, nameof(dataToVerify)); + ThrowIfNull(hashedData, nameof(hashedData)); + return Verify(dataToVerify, hashedData, NativeMethods.sha512_bytes_verify); } /// /// Verifies data using the SHA3 256 algorithm. /// - /// - /// - /// - /// - /// - public bool Verify256(byte[] dataToVerify, byte[] hashedData) { - bool result = (this._platform == OSPlatform.Linux) ? - SHALinuxWrapper.sha256_bytes_verify(dataToVerify, dataToVerify.Length, hashedData, hashedData.Length) : - SHAWindowsWrapper.sha256_bytes_verify(dataToVerify, dataToVerify.Length, hashedData, hashedData.Length); + ThrowIfNull(dataToVerify, nameof(dataToVerify)); + ThrowIfNull(hashedData, nameof(hashedData)); + return Verify(dataToVerify, hashedData, NativeMethods.sha256_bytes_verify); + } + private unsafe delegate SHAHashByteResult HashFn(byte* data, nuint length); + private unsafe delegate bool VerifyFn(byte* data, nuint dataLength, byte* hash, nuint hashLength); - return result; + private static unsafe byte[] Hash(byte[] data, HashFn nativeHash) + { + fixed (byte* dataPtr = NativePin.Of(data)) + { + SHAHashByteResult result = nativeHash(dataPtr, (nuint)data.Length); + return NativeByteBuffer.CopyAndFree(result.result_bytes_ptr, result.length); + } + } + + private static unsafe bool Verify(byte[] data, byte[] hash, VerifyFn nativeVerify) + { + fixed (byte* dataPtr = NativePin.Of(data)) + fixed (byte* hashPtr = NativePin.Of(hash)) + { + return nativeVerify(dataPtr, (nuint)data.Length, hashPtr, (nuint)hash.Length); + } + } + + private static void ThrowIfNull(byte[] value, string paramName) + { + if (value == null) + { + throw new ArgumentNullException(paramName); + } } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/Hashers/Types/Blake2HashByteResult.cs b/cas-dotnet-sdk/Hashers/Types/Blake2HashByteResult.cs deleted file mode 100644 index 0c8738d..0000000 --- a/cas-dotnet-sdk/Hashers/Types/Blake2HashByteResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Hashers.Types -{ - internal struct Blake2HashByteResult - { - public IntPtr result_bytes_ptr; - public long length; - } -} diff --git a/cas-dotnet-sdk/Hashers/Types/SHAHashByteResult.cs b/cas-dotnet-sdk/Hashers/Types/SHAHashByteResult.cs deleted file mode 100644 index b398598..0000000 --- a/cas-dotnet-sdk/Hashers/Types/SHAHashByteResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Hashers.Types -{ - internal struct SHAHashByteResult - { - public IntPtr result_bytes_ptr; - public long length; - } -} diff --git a/cas-dotnet-sdk/Hashers/Windows/Blake2WindowsWrapper.cs b/cas-dotnet-sdk/Hashers/Windows/Blake2WindowsWrapper.cs deleted file mode 100644 index 094feac..0000000 --- a/cas-dotnet-sdk/Hashers/Windows/Blake2WindowsWrapper.cs +++ /dev/null @@ -1,20 +0,0 @@ -using CasDotnetSdk.Hashers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hashers.Windows -{ - internal static class Blake2WindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern Blake2HashByteResult blake2_512_bytes(byte[] toHash, int toHashLength); - - [DllImport("cas_core_lib.dll")] - public static extern Blake2HashByteResult blake2_256_bytes(byte[] toHash, int toHashLength); - - [DllImport("cas_core_lib.dll")] - public static extern bool blake2_256_bytes_verify(byte[] hashedData, int hashedDatLength, byte[] toCompare, int toCompareLength); - - [DllImport("cas_core_lib.dll")] - public static extern bool blake2_512_bytes_verify(byte[] hashedData, int hashedDatLength, byte[] toCompare, int toCompareLength); - } -} diff --git a/cas-dotnet-sdk/Hashers/Windows/SHAWindowsWrapper.cs b/cas-dotnet-sdk/Hashers/Windows/SHAWindowsWrapper.cs deleted file mode 100644 index 9d76ead..0000000 --- a/cas-dotnet-sdk/Hashers/Windows/SHAWindowsWrapper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using CasDotnetSdk.Hashers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hashers.Windows -{ - internal static class SHAWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern SHAHashByteResult sha512_bytes(byte[] dataToHash, int dataLength); - - [DllImport("cas_core_lib.dll")] - [return: MarshalAs(UnmanagedType.I1)] - public static extern bool sha512_bytes_verify(byte[] dataToHash, int dataLength, byte[] hashToVerify, int hashToVerifyLength); - - [DllImport("cas_core_lib.dll")] - public static extern SHAHashByteResult sha256_bytes(byte[] dataToHash, int dataLength); - - [DllImport("cas_core_lib.dll")] - [return: MarshalAs(UnmanagedType.I1)] - public static extern bool sha256_bytes_verify(byte[] dataToHash, int dataLength, byte[] hashToVerify, int hashToVerifyLength); - } -} diff --git a/cas-dotnet-sdk/Helpers/NativeByteBuffer.cs b/cas-dotnet-sdk/Helpers/NativeByteBuffer.cs new file mode 100644 index 0000000..745bb70 --- /dev/null +++ b/cas-dotnet-sdk/Helpers/NativeByteBuffer.cs @@ -0,0 +1,35 @@ +using CasCoreLib; +using System; +using System.Runtime.InteropServices; + +namespace CasDotnetSdk.Helpers +{ + /// + /// Copies a byte buffer handed back by cas-core-lib into a managed array and + /// then releases the native allocation via the FFI free_bytes. + /// + /// This centralizes the "marshal the bytes out, then free the pointer" + /// invariant that every pointer-returning native call must honor — the single + /// most common source of leaks in the hand-written wrappers. + /// + /// + internal static unsafe class NativeByteBuffer + { + public static byte[] CopyAndFree(byte* ptr, nuint length) + { + if (ptr == null) + { + return Array.Empty(); + } + + int len = checked((int)length); + byte[] managed = new byte[len]; + if (len > 0) + { + Marshal.Copy((IntPtr)ptr, managed, 0, len); + } + NativeMethods.free_bytes(ptr); + return managed; + } + } +} diff --git a/cas-dotnet-sdk/Helpers/NativePin.cs b/cas-dotnet-sdk/Helpers/NativePin.cs new file mode 100644 index 0000000..8177122 --- /dev/null +++ b/cas-dotnet-sdk/Helpers/NativePin.cs @@ -0,0 +1,18 @@ +namespace CasDotnetSdk.Helpers +{ + /// + /// Helper for pinning byte arrays before handing them to the native layer. + /// + internal static class NativePin + { + // A 1-byte array used solely to produce a non-null pointer when an empty + // input is pinned. `fixed (byte* p = emptyArray)` yields a null pointer, + // but the native FFI functions assert their input pointer is non-null + // (even though they read zero bytes when the length is 0). Hashing an empty + // input is legitimate (e.g. NIST's Len=0 vectors), so route it through this + // sentinel and still pass the real length of 0. + private static readonly byte[] _sentinel = new byte[1]; + + public static byte[] Of(byte[] data) => data.Length == 0 ? _sentinel : data; + } +} diff --git a/cas-dotnet-sdk/cas-dotnet-sdk.csproj b/cas-dotnet-sdk/cas-dotnet-sdk.csproj index 400bbef..d56bc04 100644 --- a/cas-dotnet-sdk/cas-dotnet-sdk.csproj +++ b/cas-dotnet-sdk/cas-dotnet-sdk.csproj @@ -3,6 +3,8 @@ net10.0;net9.0;net8.0;net7.0;net6.0 CasDotnetSdk enable + + true True true cas-dotnet-sdk @@ -18,13 +20,21 @@ ..\cas-core-lib $(MSBuildProjectDirectory) $(MSBuildProjectDirectory)\artifacts\native + + $(MSBuildProjectDirectory)\generated\NativeMethods.g.cs true - + @@ -63,6 +73,27 @@ + + + + + + + + + + + + True diff --git a/cas-dotnet-sdk/generated/NativeMethods.g.cs b/cas-dotnet-sdk/generated/NativeMethods.g.cs new file mode 100644 index 0000000..26e5e8b --- /dev/null +++ b/cas-dotnet-sdk/generated/NativeMethods.g.cs @@ -0,0 +1,74 @@ +// +// This code is generated by csbindgen. +// DON'T CHANGE THIS DIRECTLY. +// +#pragma warning disable CS8500 +#pragma warning disable CS8981 +using System; +using System.Runtime.InteropServices; + + +namespace CasCoreLib +{ + internal static unsafe partial class NativeMethods + { + const string __DllName = "cas_core_lib"; + + + + + + [DllImport(__DllName, EntryPoint = "sha512_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern SHAHashByteResult sha512_bytes(byte* data_to_hash, nuint data_len); + + [DllImport(__DllName, EntryPoint = "sha512_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool sha512_bytes_verify(byte* data_to_hash, nuint data_len, byte* data_to_verify, nuint data_to_verify_len); + + [DllImport(__DllName, EntryPoint = "sha256_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern SHAHashByteResult sha256_bytes(byte* data_to_hash, nuint data_len); + + [DllImport(__DllName, EntryPoint = "sha256_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool sha256_bytes_verify(byte* data_to_hash, nuint data_len, byte* data_to_verify, nuint data_to_verify_len); + + [DllImport(__DllName, EntryPoint = "blake2_512_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Blake2HashByteResult blake2_512_bytes(byte* data, nuint data_length); + + [DllImport(__DllName, EntryPoint = "blake2_512_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool blake2_512_bytes_verify(byte* hashed_data, nuint hashed_data_length, byte* to_compare, nuint to_compare_length); + + [DllImport(__DllName, EntryPoint = "blake2_256_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Blake2HashByteResult blake2_256_bytes(byte* data_to_hash, nuint data_to_hash_length); + + [DllImport(__DllName, EntryPoint = "blake2_256_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool blake2_256_bytes_verify(byte* hashed_data, nuint hashed_data_length, byte* to_compare, nuint to_compare_length); + + [DllImport(__DllName, EntryPoint = "free_cstring", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern void free_cstring(byte* s); + + [DllImport(__DllName, EntryPoint = "free_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern void free_bytes(byte* ptr); + + + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct SHAHashByteResult + { + public byte* result_bytes_ptr; + public nuint length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Blake2HashByteResult + { + public byte* result_bytes_ptr; + public nuint length; + } + + + +} From 48811981942a320c0faa44bf51f3a1192ef48b68 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Thu, 18 Jun 2026 18:00:42 -0400 Subject: [PATCH 2/4] refactoring rest of library --- .../Asymmetric/Linux/RSALinuxWrapper.cs | 18 - cas-dotnet-sdk/Asymmetric/RSAWrapper.cs | 75 ++-- .../Asymmetric/Types/RsaDecryptBytesResult.cs | 10 - .../Asymmetric/Types/RsaEncryptBytesResult.cs | 10 - .../Asymmetric/Types/RsaKeyPairStruct.cs | 11 - .../Asymmetric/Types/RsaSignBytesResults.cs | 11 - .../Asymmetric/Types/RsaSignResultStruct.cs | 10 - .../Asymmetric/Windows/RSAWindowsWrapper.cs | 18 - .../Compression/Linux/ZSTDLinuxWrapper.cs | 14 - .../Compression/Types/ZSTDResult.cs | 11 - .../Compression/Windows/ZSTDWindowsWrapper.cs | 14 - cas-dotnet-sdk/Compression/ZSTDWrapper.cs | 54 +-- cas-dotnet-sdk/Hashers/HmacWrapper.cs | 59 +-- .../Hashers/Linux/HmacLinuxWrapper.cs | 15 - .../Hashers/Types/HmacSignByteResult.cs | 11 - .../Hashers/Windows/HmacWindowsWrapper.cs | 15 - cas-dotnet-sdk/Helpers/FreeMemoryHelper.cs | 40 -- .../Linux/FreeMemoryHelperLinuxWrapper.cs | 14 - cas-dotnet-sdk/Helpers/NativeString.cs | 43 ++ .../Helpers/Types/CasStringResult.cs | 18 - .../Helpers/Types/CasVerifyResult.cs | 27 -- .../Windows/FreeMemoryHelperWindowsWrapper.cs | 14 - cas-dotnet-sdk/Hybrid/HpkeWrapper.cs | 98 ++--- .../Hybrid/Linux/HpkeLinuxWrapper.cs | 17 - .../Hybrid/Types/HpkeDecryptResultStruct.cs | 11 - .../Hybrid/Types/HpkeEncryptResultStruct.cs | 15 - .../Hybrid/Types/HpkeKeyPairResultStruct.cs | 14 - .../Hybrid/Windows/HpkeWindowsWrapper.cs | 18 - .../KeyExchange/Linux/X25519LinuxWrapper.cs | 14 - .../Types/X25519SecretPublicKeyResult.cs | 12 - .../Types/X25519SharedSecretResult.cs | 11 - .../Windows/X25519WindowsWrapper.cs | 14 - cas-dotnet-sdk/KeyExchange/X25519Wrapper.cs | 60 +-- .../PQC/Linux/SLHDSALinuxWrapper.cs | 18 - cas-dotnet-sdk/PQC/SLHDSAWrapper.cs | 49 +-- cas-dotnet-sdk/PQC/Types/SLHDSAKeyPair.cs | 10 - cas-dotnet-sdk/PQC/Types/SLHDSASignature.cs | 11 - .../PQC/Windows/SLHDSAWindowsWrapper.cs | 18 - .../PasswordHashers/Argon2Wrapper.cs | 121 ++---- .../PasswordHashers/BcryptWrapper.cs | 71 ++-- .../Linux/Argon2LinuxWrapper.cs | 24 -- .../Linux/BcryptLinuxWrapper.cs | 17 - .../Linux/SCryptLinuxWrapper.cs | 17 - .../PasswordHashers/SCryptWrapper.cs | 57 ++- .../PasswordHashers/Types/Argon2KDFResult.cs | 11 - .../Types/Argon2ThreadResult.cs | 10 - .../Windows/Argon2WindowsWrapper.cs | 24 -- .../Windows/BcryptWindowsWrapper.cs | 17 - .../Windows/SCryptWindowsWrapper.cs | 17 - cas-dotnet-sdk/Signatures/ED25519Wrapper.cs | 114 ++---- .../Signatures/Linux/ED25519LinuxWrapper.cs | 21 - .../Types/Ed25519ByteSignatureResultStruct.cs | 13 - .../Types/Ed25519KeyPairBytesResultStruct.cs | 12 - .../Types/Ed25519SignatureStruct.cs | 10 - .../Windows/ED25519WindowsWrapper.cs | 22 -- cas-dotnet-sdk/Sponges/AsconWrapper.cs | 86 ++-- .../Sponges/Linux/AsconLinuxWrapper.cs | 20 - .../Types/Ascon128DecryptResultStruct.cs | 11 - .../Types/Ascon128EncryptResultStruct.cs | 11 - .../Sponges/Types/Ascon128KeyStruct.cs | 10 - .../Sponges/Types/Ascon128NonceStruct.cs | 10 - .../Sponges/Windows/AsconWindowsWrapper.cs | 20 - cas-dotnet-sdk/Symmetric/AESWrapper.cs | 195 +++------ .../Symmetric/Linux/AESLinuxWrapper.cs | 37 -- .../Symmetric/Types/AesBytesDecrypt.cs | 11 - .../Symmetric/Types/AesBytesEncrypt.cs | 11 - .../Symmetric/Types/AesKeyResult.cs | 10 - .../Symmetric/Types/AesNonceResult.cs | 10 - .../Types/AesX25519DiffieHellmanStruct.cs | 11 - .../Symmetric/Windows/AESWindowsWrapper.cs | 35 -- cas-dotnet-sdk/generated/NativeMethods.g.cs | 373 +++++++++++++++++- 71 files changed, 715 insertions(+), 1626 deletions(-) delete mode 100644 cas-dotnet-sdk/Asymmetric/Linux/RSALinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Asymmetric/Types/RsaDecryptBytesResult.cs delete mode 100644 cas-dotnet-sdk/Asymmetric/Types/RsaEncryptBytesResult.cs delete mode 100644 cas-dotnet-sdk/Asymmetric/Types/RsaKeyPairStruct.cs delete mode 100644 cas-dotnet-sdk/Asymmetric/Types/RsaSignBytesResults.cs delete mode 100644 cas-dotnet-sdk/Asymmetric/Types/RsaSignResultStruct.cs delete mode 100644 cas-dotnet-sdk/Asymmetric/Windows/RSAWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Compression/Linux/ZSTDLinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Compression/Types/ZSTDResult.cs delete mode 100644 cas-dotnet-sdk/Compression/Windows/ZSTDWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Hashers/Linux/HmacLinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Hashers/Types/HmacSignByteResult.cs delete mode 100644 cas-dotnet-sdk/Hashers/Windows/HmacWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Helpers/FreeMemoryHelper.cs delete mode 100644 cas-dotnet-sdk/Helpers/Linux/FreeMemoryHelperLinuxWrapper.cs create mode 100644 cas-dotnet-sdk/Helpers/NativeString.cs delete mode 100644 cas-dotnet-sdk/Helpers/Types/CasStringResult.cs delete mode 100644 cas-dotnet-sdk/Helpers/Types/CasVerifyResult.cs delete mode 100644 cas-dotnet-sdk/Helpers/Windows/FreeMemoryHelperWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Hybrid/Linux/HpkeLinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Hybrid/Types/HpkeDecryptResultStruct.cs delete mode 100644 cas-dotnet-sdk/Hybrid/Types/HpkeEncryptResultStruct.cs delete mode 100644 cas-dotnet-sdk/Hybrid/Types/HpkeKeyPairResultStruct.cs delete mode 100644 cas-dotnet-sdk/Hybrid/Windows/HpkeWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/KeyExchange/Linux/X25519LinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/KeyExchange/Types/X25519SecretPublicKeyResult.cs delete mode 100644 cas-dotnet-sdk/KeyExchange/Types/X25519SharedSecretResult.cs delete mode 100644 cas-dotnet-sdk/KeyExchange/Windows/X25519WindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/PQC/Linux/SLHDSALinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/PQC/Types/SLHDSASignature.cs delete mode 100644 cas-dotnet-sdk/PQC/Windows/SLHDSAWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Linux/Argon2LinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Linux/BcryptLinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Linux/SCryptLinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Types/Argon2KDFResult.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Types/Argon2ThreadResult.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Windows/Argon2WindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Windows/BcryptWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/PasswordHashers/Windows/SCryptWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Signatures/Linux/ED25519LinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Signatures/Types/Ed25519ByteSignatureResultStruct.cs delete mode 100644 cas-dotnet-sdk/Signatures/Types/Ed25519KeyPairBytesResultStruct.cs delete mode 100644 cas-dotnet-sdk/Signatures/Types/Ed25519SignatureStruct.cs delete mode 100644 cas-dotnet-sdk/Signatures/Windows/ED25519WindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Sponges/Linux/AsconLinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Sponges/Types/Ascon128DecryptResultStruct.cs delete mode 100644 cas-dotnet-sdk/Sponges/Types/Ascon128EncryptResultStruct.cs delete mode 100644 cas-dotnet-sdk/Sponges/Types/Ascon128KeyStruct.cs delete mode 100644 cas-dotnet-sdk/Sponges/Types/Ascon128NonceStruct.cs delete mode 100644 cas-dotnet-sdk/Sponges/Windows/AsconWindowsWrapper.cs delete mode 100644 cas-dotnet-sdk/Symmetric/Linux/AESLinuxWrapper.cs delete mode 100644 cas-dotnet-sdk/Symmetric/Types/AesBytesDecrypt.cs delete mode 100644 cas-dotnet-sdk/Symmetric/Types/AesBytesEncrypt.cs delete mode 100644 cas-dotnet-sdk/Symmetric/Types/AesKeyResult.cs delete mode 100644 cas-dotnet-sdk/Symmetric/Types/AesNonceResult.cs delete mode 100644 cas-dotnet-sdk/Symmetric/Types/AesX25519DiffieHellmanStruct.cs delete mode 100644 cas-dotnet-sdk/Symmetric/Windows/AESWindowsWrapper.cs diff --git a/cas-dotnet-sdk/Asymmetric/Linux/RSALinuxWrapper.cs b/cas-dotnet-sdk/Asymmetric/Linux/RSALinuxWrapper.cs deleted file mode 100644 index b75456e..0000000 --- a/cas-dotnet-sdk/Asymmetric/Linux/RSALinuxWrapper.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CasDotnetSdk.Asymmetric.Types; -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Asymmetric.Linux -{ - internal static class RSALinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern RsaKeyPairStruct get_key_pair(int key_size); - - [DllImport("libcas_core_lib.so")] - public static extern RsaSignBytesResults rsa_sign_with_key_bytes(string privateKey, byte[] dataToSign, int dataToSignLength); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult rsa_verify_bytes(string publicKey, byte[] dataToVerify, int dataToVerifyLength, byte[] signature, int signatureLength); - } -} diff --git a/cas-dotnet-sdk/Asymmetric/RSAWrapper.cs b/cas-dotnet-sdk/Asymmetric/RSAWrapper.cs index 5cdd79e..7d867f2 100644 --- a/cas-dotnet-sdk/Asymmetric/RSAWrapper.cs +++ b/cas-dotnet-sdk/Asymmetric/RSAWrapper.cs @@ -1,34 +1,22 @@ -using CasDotnetSdk.Asymmetric.Linux; +using CasCoreLib; using CasDotnetSdk.Asymmetric.Types; -using CasDotnetSdk.Asymmetric.Windows; - using CasDotnetSdk.Helpers; -using CasDotnetSdk.Helpers.Types; - using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Asymmetric { - public class RSAWrapper : BaseWrapper + public unsafe class RSAWrapper : BaseWrapper { /// /// A wrapper class for RSA key creation, encryption, decryption, signing, and verification. /// public RSAWrapper() { - } /// /// Signs data with an RSA private key. /// - /// - /// - /// - /// - /// - public byte[] Sign(string privateKey, byte[] dataToSign) { if (dataToSign == null || dataToSign.Length == 0) @@ -36,29 +24,18 @@ public byte[] Sign(string privateKey, byte[] dataToSign) throw new Exception("You must provide allocated data to sign with RSA"); } - RsaSignBytesResults signResult = (this._platform == OSPlatform.Linux) ? - RSALinuxWrapper.rsa_sign_with_key_bytes(privateKey, dataToSign, dataToSign.Length) : - RSAWindowsWrapper.rsa_sign_with_key_bytes(privateKey, dataToSign, dataToSign.Length); ; - CasErrorHandler.ThrowIfError(signResult.error_code, "RSA sign"); - byte[] result = new byte[signResult.length]; - Marshal.Copy(signResult.signature_raw_ptr, result, 0, (int)signResult.length); - FreeMemoryHelper.FreeBytesMemory(signResult.signature_raw_ptr); - - - return result; + fixed (byte* privateKeyPtr = NativeString.ToCString(privateKey)) + fixed (byte* dataPtr = NativePin.Of(dataToSign)) + { + RsaSignBytesResults signResult = NativeMethods.rsa_sign_with_key_bytes(privateKeyPtr, dataPtr, (nuint)dataToSign.Length); + CasErrorHandler.ThrowIfError(signResult.error_code, "RSA sign"); + return NativeByteBuffer.CopyAndFree(signResult.signature_raw_ptr, signResult.length); + } } - /// /// Verifies data with an RSA public key. /// - /// - /// - /// - /// - /// - /// - public bool Verify(string publicKey, byte[] dataToVerify, byte[] signature) { if (dataToVerify == null || dataToVerify.Length == 0) @@ -70,22 +47,19 @@ public bool Verify(string publicKey, byte[] dataToVerify, byte[] signature) throw new Exception("You must provide an allocated signature to verify with RSA"); } - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? - RSALinuxWrapper.rsa_verify_bytes(publicKey, dataToVerify, dataToVerify.Length, signature, signature.Length) : - RSAWindowsWrapper.rsa_verify_bytes(publicKey, dataToVerify, dataToVerify.Length, signature, signature.Length); - CasErrorHandler.ThrowIfError(result.error_code, "RSA verify"); - - - return result.is_valid; + fixed (byte* publicKeyPtr = NativeString.ToCString(publicKey)) + fixed (byte* dataPtr = NativePin.Of(dataToVerify)) + fixed (byte* signaturePtr = NativePin.Of(signature)) + { + CasVerifyResult result = NativeMethods.rsa_verify_bytes(publicKeyPtr, dataPtr, (nuint)dataToVerify.Length, signaturePtr, (nuint)signature.Length); + CasErrorHandler.ThrowIfError(result.error_code, "RSA verify"); + return result.is_valid; + } } /// /// Generates an RSA key based on the key size provided. (1024, 2048, 4096) /// - /// - /// - /// - public RsaKeyPairResult GetKeyPair(int keySize) { if (keySize != 1024 && keySize != 2048 && keySize != 4096) @@ -93,18 +67,13 @@ public RsaKeyPairResult GetKeyPair(int keySize) throw new Exception("Please pass in a valid key size."); } - RsaKeyPairStruct keyPairStruct = (this._platform == OSPlatform.Linux) ? - RSALinuxWrapper.get_key_pair(keySize) : - RSAWindowsWrapper.get_key_pair(keySize); - CasErrorHandler.ThrowIfError(keyPairStruct.error_code, "RSA key pair generation"); - RsaKeyPairResult result = new RsaKeyPairResult() + RsaKeyPair keyPair = NativeMethods.get_key_pair((nuint)keySize); + CasErrorHandler.ThrowIfError(keyPair.error_code, "RSA key pair generation"); + return new RsaKeyPairResult() { - PrivateKey = Marshal.PtrToStringAnsi(keyPairStruct.priv_key), - PublicKey = Marshal.PtrToStringAnsi(keyPairStruct.pub_key) + PrivateKey = NativeString.ReadAndFree(keyPair.priv_key), + PublicKey = NativeString.ReadAndFree(keyPair.pub_key) }; - FreeMemoryHelper.FreeCStringMemory(keyPairStruct.pub_key); - FreeMemoryHelper.FreeCStringMemory(keyPairStruct.priv_key); - return result; } } } diff --git a/cas-dotnet-sdk/Asymmetric/Types/RsaDecryptBytesResult.cs b/cas-dotnet-sdk/Asymmetric/Types/RsaDecryptBytesResult.cs deleted file mode 100644 index 2a9f78b..0000000 --- a/cas-dotnet-sdk/Asymmetric/Types/RsaDecryptBytesResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Asymmetric.Types -{ - internal struct RsaDecryptBytesResult - { - public IntPtr decrypted_result_ptr; - public long length; - } -} diff --git a/cas-dotnet-sdk/Asymmetric/Types/RsaEncryptBytesResult.cs b/cas-dotnet-sdk/Asymmetric/Types/RsaEncryptBytesResult.cs deleted file mode 100644 index 631e851..0000000 --- a/cas-dotnet-sdk/Asymmetric/Types/RsaEncryptBytesResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Asymmetric.Types -{ - internal struct RsaEncryptBytesResult - { - public IntPtr encrypted_result_ptr; - public long length; - } -} diff --git a/cas-dotnet-sdk/Asymmetric/Types/RsaKeyPairStruct.cs b/cas-dotnet-sdk/Asymmetric/Types/RsaKeyPairStruct.cs deleted file mode 100644 index f124f71..0000000 --- a/cas-dotnet-sdk/Asymmetric/Types/RsaKeyPairStruct.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Asymmetric.Types -{ - internal struct RsaKeyPairStruct - { - public IntPtr pub_key; - public IntPtr priv_key; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Asymmetric/Types/RsaSignBytesResults.cs b/cas-dotnet-sdk/Asymmetric/Types/RsaSignBytesResults.cs deleted file mode 100644 index 31d92d4..0000000 --- a/cas-dotnet-sdk/Asymmetric/Types/RsaSignBytesResults.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Asymmetric.Types -{ - internal struct RsaSignBytesResults - { - public IntPtr signature_raw_ptr; - public long length; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Asymmetric/Types/RsaSignResultStruct.cs b/cas-dotnet-sdk/Asymmetric/Types/RsaSignResultStruct.cs deleted file mode 100644 index a99cd28..0000000 --- a/cas-dotnet-sdk/Asymmetric/Types/RsaSignResultStruct.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Asymmetric.Types -{ - internal struct RsaSignResultStruct - { - public IntPtr signature; - public IntPtr public_key; - } -} diff --git a/cas-dotnet-sdk/Asymmetric/Windows/RSAWindowsWrapper.cs b/cas-dotnet-sdk/Asymmetric/Windows/RSAWindowsWrapper.cs deleted file mode 100644 index fd3ff38..0000000 --- a/cas-dotnet-sdk/Asymmetric/Windows/RSAWindowsWrapper.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CasDotnetSdk.Asymmetric.Types; -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Asymmetric.Windows -{ - internal static class RSAWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern RsaKeyPairStruct get_key_pair(int key_size); - - [DllImport("cas_core_lib.dll")] - public static extern RsaSignBytesResults rsa_sign_with_key_bytes(string privateKey, byte[] dataToSign, int dataToSignLength); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult rsa_verify_bytes(string publicKey, byte[] dataToVerify, int dataToVerifyLength, byte[] signature, int signatureLength); - } -} diff --git a/cas-dotnet-sdk/Compression/Linux/ZSTDLinuxWrapper.cs b/cas-dotnet-sdk/Compression/Linux/ZSTDLinuxWrapper.cs deleted file mode 100644 index e718648..0000000 --- a/cas-dotnet-sdk/Compression/Linux/ZSTDLinuxWrapper.cs +++ /dev/null @@ -1,14 +0,0 @@ -using CasDotnetSdk.Compression.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Compression.Linux -{ - internal static class ZSTDLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern ZSTDResult decompress(byte[] dataToDecompress, int dataToDecompressLength); - - [DllImport("libcas_core_lib.so")] - public static extern ZSTDResult compress(byte[] dataToCompress, int dataToCompressLength, int level); - } -} diff --git a/cas-dotnet-sdk/Compression/Types/ZSTDResult.cs b/cas-dotnet-sdk/Compression/Types/ZSTDResult.cs deleted file mode 100644 index 4c3a477..0000000 --- a/cas-dotnet-sdk/Compression/Types/ZSTDResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Compression.Types -{ - internal struct ZSTDResult - { - public IntPtr data; - public long length; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Compression/Windows/ZSTDWindowsWrapper.cs b/cas-dotnet-sdk/Compression/Windows/ZSTDWindowsWrapper.cs deleted file mode 100644 index 890ada2..0000000 --- a/cas-dotnet-sdk/Compression/Windows/ZSTDWindowsWrapper.cs +++ /dev/null @@ -1,14 +0,0 @@ -using CasDotnetSdk.Compression.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Compression.Windows -{ - internal static class ZSTDWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern ZSTDResult decompress(byte[] dataToDecompress, int dataToDecompressLength); - - [DllImport("cas_core_lib.dll")] - public static extern ZSTDResult compress(byte[] dataToCompress, int dataToCompressLength, int level); - } -} diff --git a/cas-dotnet-sdk/Compression/ZSTDWrapper.cs b/cas-dotnet-sdk/Compression/ZSTDWrapper.cs index 1e9ff90..f0730e3 100644 --- a/cas-dotnet-sdk/Compression/ZSTDWrapper.cs +++ b/cas-dotnet-sdk/Compression/ZSTDWrapper.cs @@ -1,30 +1,20 @@ -using CasDotnetSdk.Compression.Linux; -using CasDotnetSdk.Compression.Types; -using CasDotnetSdk.Compression.Windows; - +using CasCoreLib; using CasDotnetSdk.Helpers; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Compression { - public class ZSTDWrapper : BaseWrapper + public unsafe class ZSTDWrapper : BaseWrapper { public ZSTDWrapper() { - } /// /// Datas to the byte array to compress and the level of encryption. - /// Zstandard (zstd) supports 22 compression levels, ranging from -22 to 22. Lower levels, such as 1–9, + /// Zstandard (zstd) supports 22 compression levels, ranging from -22 to 22. Lower levels, such as 1–9, /// are faster but result in larger file sizes, while higher levels, such as 10–22, provide better compression ratios. /// - /// - /// - /// - /// - public byte[] Compress(byte[] data, int level) { if (data == null || data.Length == 0) @@ -36,27 +26,18 @@ public byte[] Compress(byte[] data, int level) throw new Exception("Please pass in a valid level for ZSTD Compression"); } - - ZSTDResult compressResult = (this._platform == OSPlatform.Linux) ? - ZSTDLinuxWrapper.compress(data, data.Length, level) : - ZSTDWindowsWrapper.compress(data, data.Length, level); - CasErrorHandler.ThrowIfError(compressResult.error_code, "ZSTD compress"); - byte[] result = new byte[compressResult.length]; - Marshal.Copy(compressResult.data, result, 0, (int)compressResult.length); - FreeMemoryHelper.FreeBytesMemory(compressResult.data); - - - return result; + fixed (byte* dataPtr = NativePin.Of(data)) + { + ZstdCompressResult compressResult = NativeMethods.compress(dataPtr, (nuint)data.Length, (nuint)level); + CasErrorHandler.ThrowIfError(compressResult.error_code, "ZSTD compress"); + return NativeByteBuffer.CopyAndFree(compressResult.data, compressResult.length); + } } /// /// Decompresses and previosuly compressed byte array with ZSTD. /// No level is required to decompress. /// - /// - /// - /// - public byte[] Decompress(byte[] data) { if (data == null || data.Length == 0) @@ -64,17 +45,12 @@ public byte[] Decompress(byte[] data) throw new Exception("Must pass in an allocated array of data to decompress"); } - - ZSTDResult decompressResult = (this._platform == OSPlatform.Linux) ? - ZSTDLinuxWrapper.decompress(data, data.Length) : - ZSTDWindowsWrapper.decompress(data, data.Length); - CasErrorHandler.ThrowIfError(decompressResult.error_code, "ZSTD decompress"); - byte[] result = new byte[decompressResult.length]; - Marshal.Copy(decompressResult.data, result, 0, (int)decompressResult.length); - FreeMemoryHelper.FreeBytesMemory(decompressResult.data); - - - return result; + fixed (byte* dataPtr = NativePin.Of(data)) + { + ZstdCompressResult decompressResult = NativeMethods.decompress(dataPtr, (nuint)data.Length); + CasErrorHandler.ThrowIfError(decompressResult.error_code, "ZSTD decompress"); + return NativeByteBuffer.CopyAndFree(decompressResult.data, decompressResult.length); + } } } } diff --git a/cas-dotnet-sdk/Hashers/HmacWrapper.cs b/cas-dotnet-sdk/Hashers/HmacWrapper.cs index e24ec18..3637f1e 100644 --- a/cas-dotnet-sdk/Hashers/HmacWrapper.cs +++ b/cas-dotnet-sdk/Hashers/HmacWrapper.cs @@ -1,35 +1,21 @@ - -using CasDotnetSdk.Hashers.Linux; -using CasDotnetSdk.Hashers.Types; -using CasDotnetSdk.Hashers.Windows; +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Helpers.Types; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Hashers { - public class HmacWrapper : BaseWrapper + public unsafe class HmacWrapper : BaseWrapper { - - /// /// A wrapper class for the HMAC hashing algorithm. /// public HmacWrapper() { - } /// /// Signs a message using the HMAC algorithm. /// - /// - /// - /// - /// - /// - public byte[] HmacSignBytes(byte[] key, byte[] message) { if (key == null || key.Length == 0) @@ -41,28 +27,18 @@ public byte[] HmacSignBytes(byte[] key, byte[] message) throw new Exception("You must provide a message to sign with HMAC"); } - HmacSignByteResult signed = (this._platform == OSPlatform.Linux) ? - HmacLinuxWrapper.hmac_sign_bytes(key, key.Length, message, message.Length) : - HmacWindowsWrapper.hmac_sign_bytes(key, key.Length, message, message.Length); - CasErrorHandler.ThrowIfError(signed.error_code, "HMAC sign"); - byte[] result = new byte[signed.length]; - Marshal.Copy(signed.result_bytes_ptr, result, 0, (int)signed.length); - FreeMemoryHelper.FreeBytesMemory(signed.result_bytes_ptr); - - - return result; + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* messagePtr = NativePin.Of(message)) + { + HmacSignByteResult signed = NativeMethods.hmac_sign_bytes(keyPtr, (nuint)key.Length, messagePtr, (nuint)message.Length); + CasErrorHandler.ThrowIfError(signed.error_code, "HMAC sign"); + return NativeByteBuffer.CopyAndFree(signed.result_bytes_ptr, signed.length); + } } /// /// Verifies a message using the HMAC algorithm. /// - /// - /// - /// - /// - /// - /// - public bool HmacVerifyBytes(byte[] key, byte[] message, byte[] signature) { if (key == null || key.Length == 0) @@ -78,13 +54,14 @@ public bool HmacVerifyBytes(byte[] key, byte[] message, byte[] signature) throw new Exception("You must provide a signature to verify with HMAC"); } - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? - HmacLinuxWrapper.hmac_verify_bytes(key, key.Length, message, message.Length, signature, signature.Length) : - HmacWindowsWrapper.hmac_verify_bytes(key, key.Length, message, message.Length, signature, signature.Length); - CasErrorHandler.ThrowIfError(result.error_code, "HMAC verify"); - - - return result.is_valid; + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* messagePtr = NativePin.Of(message)) + fixed (byte* signaturePtr = NativePin.Of(signature)) + { + CasVerifyResult result = NativeMethods.hmac_verify_bytes(keyPtr, (nuint)key.Length, messagePtr, (nuint)message.Length, signaturePtr, (nuint)signature.Length); + CasErrorHandler.ThrowIfError(result.error_code, "HMAC verify"); + return result.is_valid; + } } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/Hashers/Linux/HmacLinuxWrapper.cs b/cas-dotnet-sdk/Hashers/Linux/HmacLinuxWrapper.cs deleted file mode 100644 index faa77bf..0000000 --- a/cas-dotnet-sdk/Hashers/Linux/HmacLinuxWrapper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using CasDotnetSdk.Hashers.Types; -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hashers.Linux -{ - internal static class HmacLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern HmacSignByteResult hmac_sign_bytes(byte[] key, int keyLength, byte[] message, int messageLength); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult hmac_verify_bytes(byte[] key, int keyLength, byte[] message, int messageLength, byte[] signature, int signatureLength); - } -} diff --git a/cas-dotnet-sdk/Hashers/Types/HmacSignByteResult.cs b/cas-dotnet-sdk/Hashers/Types/HmacSignByteResult.cs deleted file mode 100644 index a294167..0000000 --- a/cas-dotnet-sdk/Hashers/Types/HmacSignByteResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Hashers.Types -{ - internal struct HmacSignByteResult - { - public IntPtr result_bytes_ptr; - public long length; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Hashers/Windows/HmacWindowsWrapper.cs b/cas-dotnet-sdk/Hashers/Windows/HmacWindowsWrapper.cs deleted file mode 100644 index a52f6fc..0000000 --- a/cas-dotnet-sdk/Hashers/Windows/HmacWindowsWrapper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using CasDotnetSdk.Hashers.Types; -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hashers.Windows -{ - internal static class HmacWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern HmacSignByteResult hmac_sign_bytes(byte[] key, int keyLength, byte[] message, int messageLength); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult hmac_verify_bytes(byte[] key, int keyLength, byte[] message, int messageLength, byte[] signature, int signatureLength); - } -} diff --git a/cas-dotnet-sdk/Helpers/FreeMemoryHelper.cs b/cas-dotnet-sdk/Helpers/FreeMemoryHelper.cs deleted file mode 100644 index 033e797..0000000 --- a/cas-dotnet-sdk/Helpers/FreeMemoryHelper.cs +++ /dev/null @@ -1,40 +0,0 @@ -using CasDotnetSdk.Helpers.Linux; -using CasDotnetSdk.Helpers.Windows; - -using System; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Helpers -{ - internal static class FreeMemoryHelper - { - private static readonly OSPlatform _operatingSystem; - static FreeMemoryHelper() - { - _operatingSystem = new OperatingSystemDeterminator().GetOperatingSystem(); - } - public static void FreeCStringMemory(IntPtr memoryToFree) - { - if (_operatingSystem == OSPlatform.Linux) - { - FreeMemoryHelperLinuxWrapper.free_cstring(memoryToFree); - } - else - { - FreeMemoryHelperWindowsWrapper.free_cstring(memoryToFree); - } - } - - public static void FreeBytesMemory(IntPtr memoryToFree) - { - if (_operatingSystem == OSPlatform.Linux) - { - FreeMemoryHelperLinuxWrapper.free_bytes(memoryToFree); - } - else - { - FreeMemoryHelperWindowsWrapper.free_bytes(memoryToFree); - } - } - } -} diff --git a/cas-dotnet-sdk/Helpers/Linux/FreeMemoryHelperLinuxWrapper.cs b/cas-dotnet-sdk/Helpers/Linux/FreeMemoryHelperLinuxWrapper.cs deleted file mode 100644 index 6264f36..0000000 --- a/cas-dotnet-sdk/Helpers/Linux/FreeMemoryHelperLinuxWrapper.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Helpers.Linux -{ - internal static class FreeMemoryHelperLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern void free_cstring(IntPtr stringToFree); - - [DllImport("libcas_core_lib.so")] - public static extern void free_bytes(IntPtr bytesToFree); - } -} diff --git a/cas-dotnet-sdk/Helpers/NativeString.cs b/cas-dotnet-sdk/Helpers/NativeString.cs new file mode 100644 index 0000000..a504e7e --- /dev/null +++ b/cas-dotnet-sdk/Helpers/NativeString.cs @@ -0,0 +1,43 @@ +using CasCoreLib; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace CasDotnetSdk.Helpers +{ + /// + /// Marshals C strings across the cas-core-lib FFI boundary. + /// + internal static unsafe class NativeString + { + /// + /// Reads a null-terminated C string handed back by the native layer into a + /// managed string, then releases it with the FFI free_cstring. + /// + public static string ReadAndFree(byte* ptr) + { + if (ptr == null) + { + return null; + } + string value = Marshal.PtrToStringUTF8((IntPtr)ptr); + NativeMethods.free_cstring(ptr); + return value; + } + + /// + /// Encodes a managed string as a null-terminated UTF-8 buffer suitable for + /// pinning and passing to a native *const c_char parameter. The + /// returned array is always at least one byte (the terminator), so pinning + /// it yields a non-null pointer even for an empty string. + /// + public static byte[] ToCString(string value) + { + value ??= string.Empty; + int count = Encoding.UTF8.GetByteCount(value); + byte[] buffer = new byte[count + 1]; // trailing byte stays 0 = null terminator + Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, 0); + return buffer; + } + } +} diff --git a/cas-dotnet-sdk/Helpers/Types/CasStringResult.cs b/cas-dotnet-sdk/Helpers/Types/CasStringResult.cs deleted file mode 100644 index 855c616..0000000 --- a/cas-dotnet-sdk/Helpers/Types/CasStringResult.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Helpers.Types -{ - /// - /// Mirrors the native CasStringResult struct returned by cas-core-lib FFI - /// calls that hand back a C string (e.g. a password hash). value is null when - /// error_code is non-zero; a non-null value must still be freed with - /// . - /// - [StructLayout(LayoutKind.Sequential)] - internal struct CasStringResult - { - public IntPtr value; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Helpers/Types/CasVerifyResult.cs b/cas-dotnet-sdk/Helpers/Types/CasVerifyResult.cs deleted file mode 100644 index 75a7af0..0000000 --- a/cas-dotnet-sdk/Helpers/Types/CasVerifyResult.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Helpers.Types -{ - /// - /// Mirrors the native CasVerifyResult struct returned by every cas-core-lib - /// verify-style FFI call. is_valid only carries meaning when - /// error_code is zero; a non-zero error_code means the inputs were - /// malformed rather than that the signature simply did not match. - /// - /// The native struct is { bool is_valid; i32 error_code }. We model the - /// boolean as a raw rather than a [MarshalAs] bool so the - /// struct stays blittable. A non-blittable return struct makes .NET's - /// marshaller disagree with the SysV x64 ABI about register-vs-sret return, which - /// shifts the call's argument registers and feeds garbage lengths into the native - /// layer (observed as a multi-terabyte allocation abort on Linux). - /// - /// - [StructLayout(LayoutKind.Sequential)] - internal struct CasVerifyResult - { - public byte is_valid_raw; - public int error_code; - - public bool is_valid => this.is_valid_raw != 0; - } -} diff --git a/cas-dotnet-sdk/Helpers/Windows/FreeMemoryHelperWindowsWrapper.cs b/cas-dotnet-sdk/Helpers/Windows/FreeMemoryHelperWindowsWrapper.cs deleted file mode 100644 index a526f98..0000000 --- a/cas-dotnet-sdk/Helpers/Windows/FreeMemoryHelperWindowsWrapper.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Helpers.Windows -{ - internal static class FreeMemoryHelperWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern void free_cstring(IntPtr stringToFree); - - [DllImport("cas_core_lib.dll")] - public static extern void free_bytes(IntPtr bytesToFree); - } -} diff --git a/cas-dotnet-sdk/Hybrid/HpkeWrapper.cs b/cas-dotnet-sdk/Hybrid/HpkeWrapper.cs index 0bd041d..9582044 100644 --- a/cas-dotnet-sdk/Hybrid/HpkeWrapper.cs +++ b/cas-dotnet-sdk/Hybrid/HpkeWrapper.cs @@ -1,133 +1,93 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Hybrid.Linux; using CasDotnetSdk.Hybrid.Types; -using CasDotnetSdk.Hybrid.Windows; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Hybrid { - public class HpkeWrapper : BaseWrapper + public unsafe class HpkeWrapper : BaseWrapper { public HpkeWrapper() { - } /// /// Generates a Private Key, Public Key, and InfoStr for usage with HPKE /// - /// - /// - public HpkeKeyPairResult GenerateKeyPair() { - - HpkeKeyPairResultStruct keyPair = (this._platform == OSPlatform.Linux) ? - HpkeLinuxWrapper.hpke_generate_keypair() : - HpkeWindowsWrapper.hpke_generate_keypair(); - byte[] privateKeyResult = new byte[keyPair.private_key_ptr_length]; - byte[] publicKeyResult = new byte[keyPair.public_key_ptr_length]; - byte[] infoStrResult = new byte[keyPair.info_str_ptr_length]; - Marshal.Copy(keyPair.private_key_ptr, privateKeyResult, 0, (int)keyPair.private_key_ptr_length); - Marshal.Copy(keyPair.public_key_ptr, publicKeyResult, 0, (int)keyPair.public_key_ptr_length); - Marshal.Copy(keyPair.info_str_ptr, infoStrResult, 0, (int)keyPair.info_str_ptr_length); - FreeMemoryHelper.FreeBytesMemory(keyPair.public_key_ptr); - FreeMemoryHelper.FreeBytesMemory(keyPair.private_key_ptr); - FreeMemoryHelper.FreeBytesMemory(keyPair.info_str_ptr); - HpkeKeyPairResult result = new HpkeKeyPairResult() + HpkeKeyPair keyPair = NativeMethods.hpke_generate_keypair(); + return new HpkeKeyPairResult() { - PrivateKey = privateKeyResult, - PublicKey = publicKeyResult, - InfoStr = infoStrResult + PrivateKey = NativeByteBuffer.CopyAndFree(keyPair.private_key_ptr, keyPair.private_key_ptr_length), + PublicKey = NativeByteBuffer.CopyAndFree(keyPair.public_key_ptr, keyPair.public_key_ptr_length), + InfoStr = NativeByteBuffer.CopyAndFree(keyPair.info_str_ptr, keyPair.info_str_ptr_length) }; - - - return result; } - public HpkeEncryptResult Encrypt(byte[] plaintText, byte[] publicKey, byte[] infoStr) { if (plaintText == null || plaintText.Length == 0) { throw new Exception("Must provide plaint text to encrypt with HPKE"); } - if (publicKey == null || publicKey.Length == 0) { throw new Exception("Must a public key to encrypt with HPKE"); } - if (infoStr == null || infoStr.Length == 0) { throw new Exception("Must a info str to encrypt with HPKE"); } - - HpkeEncryptResultStruct encrypt = (this._platform == OSPlatform.Linux) ? - HpkeLinuxWrapper.hpke_encrypt(plaintText, plaintText.Length, publicKey, publicKey.Length, infoStr, infoStr.Length) : - HpkeWindowsWrapper.hpke_encrypt(plaintText, plaintText.Length, publicKey, publicKey.Length, infoStr, infoStr.Length); - CasErrorHandler.ThrowIfError(encrypt.error_code, "HPKE encrypt"); - byte[] encappedKeyResult = new byte[encrypt.encapped_key_ptr_length]; - byte[] cipherTextResult = new byte[encrypt.ciphertext_ptr_length]; - byte[] tagResult = new byte[encrypt.tag_ptr_length]; - Marshal.Copy(encrypt.encapped_key_ptr, encappedKeyResult, 0, (int)encrypt.encapped_key_ptr_length); - Marshal.Copy(encrypt.ciphertext_ptr, cipherTextResult, 0, (int)encrypt.ciphertext_ptr_length); - Marshal.Copy(encrypt.tag_ptr, tagResult, 0, (int)encrypt.tag_ptr_length); - FreeMemoryHelper.FreeBytesMemory(encrypt.ciphertext_ptr); - FreeMemoryHelper.FreeBytesMemory(encrypt.encapped_key_ptr); - FreeMemoryHelper.FreeBytesMemory(encrypt.tag_ptr); - HpkeEncryptResult result = new HpkeEncryptResult() + fixed (byte* plaintextPtr = NativePin.Of(plaintText)) + fixed (byte* publicKeyPtr = NativePin.Of(publicKey)) + fixed (byte* infoStrPtr = NativePin.Of(infoStr)) { - Ciphertext = cipherTextResult, - Tag = tagResult, - EncappedKey = encappedKeyResult, - }; - - - return result; + HpkeEncrypt encrypt = NativeMethods.hpke_encrypt(plaintextPtr, (nuint)plaintText.Length, publicKeyPtr, (nuint)publicKey.Length, infoStrPtr, (nuint)infoStr.Length); + CasErrorHandler.ThrowIfError(encrypt.error_code, "HPKE encrypt"); + return new HpkeEncryptResult() + { + EncappedKey = NativeByteBuffer.CopyAndFree(encrypt.encapped_key_ptr, encrypt.encapped_key_ptr_length), + Ciphertext = NativeByteBuffer.CopyAndFree(encrypt.ciphertext_ptr, encrypt.ciphertext_ptr_length), + Tag = NativeByteBuffer.CopyAndFree(encrypt.tag_ptr, encrypt.tag_ptr_length) + }; + } } - public byte[] Decrypt(byte[] cipherText, byte[] privateKey, byte[] encappedKey, byte[] tag, byte[] infoStr) { if (cipherText == null || cipherText.Length == 0) { throw new Exception("Must provide ciphertext to decrypt with HPKE"); } - if (privateKey == null || privateKey.Length == 0) { throw new Exception("Must a private key to decrypt with HPKE"); } - if (encappedKey == null || encappedKey.Length == 0) { throw new Exception("Must provide an encapped key to decrypt with HPKE"); } - if (tag == null || tag.Length == 0) { throw new Exception("Must provide a tag to decrypt with HPKE"); } - if (infoStr == null || infoStr.Length == 0) { throw new Exception("Must a info str to decrypt with HPKE"); } - - HpkeDecryptResultStruct decrypt = (this._platform == OSPlatform.Linux) ? - HpkeLinuxWrapper.hpke_decrypt(cipherText, cipherText.Length, privateKey, privateKey.Length, encappedKey, encappedKey.Length, tag, tag.Length, infoStr, infoStr.Length) : - HpkeWindowsWrapper.hpke_decrypt(cipherText, cipherText.Length, privateKey, privateKey.Length, encappedKey, encappedKey.Length, tag, tag.Length, infoStr, infoStr.Length); - CasErrorHandler.ThrowIfError(decrypt.error_code, "HPKE decrypt"); - byte[] result = new byte[decrypt.plaintext_ptr_length]; - Marshal.Copy(decrypt.plaintext_ptr, result, 0, (int)decrypt.plaintext_ptr_length); - FreeMemoryHelper.FreeBytesMemory(decrypt.plaintext_ptr); - - return result; + fixed (byte* cipherTextPtr = NativePin.Of(cipherText)) + fixed (byte* privateKeyPtr = NativePin.Of(privateKey)) + fixed (byte* encappedKeyPtr = NativePin.Of(encappedKey)) + fixed (byte* tagPtr = NativePin.Of(tag)) + fixed (byte* infoStrPtr = NativePin.Of(infoStr)) + { + HpkeDecrypt decrypt = NativeMethods.hpke_decrypt(cipherTextPtr, (nuint)cipherText.Length, privateKeyPtr, (nuint)privateKey.Length, encappedKeyPtr, (nuint)encappedKey.Length, tagPtr, (nuint)tag.Length, infoStrPtr, (nuint)infoStr.Length); + CasErrorHandler.ThrowIfError(decrypt.error_code, "HPKE decrypt"); + return NativeByteBuffer.CopyAndFree(decrypt.plaintext_ptr, decrypt.plaintext_ptr_length); + } } } } diff --git a/cas-dotnet-sdk/Hybrid/Linux/HpkeLinuxWrapper.cs b/cas-dotnet-sdk/Hybrid/Linux/HpkeLinuxWrapper.cs deleted file mode 100644 index e6202dd..0000000 --- a/cas-dotnet-sdk/Hybrid/Linux/HpkeLinuxWrapper.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CasDotnetSdk.Hybrid.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hybrid.Linux -{ - internal static class HpkeLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern HpkeKeyPairResultStruct hpke_generate_keypair(); - - [DllImport("libcas_core_lib.so")] - public static extern HpkeEncryptResultStruct hpke_encrypt(byte[] plaintext, int plainTextLength, byte[] publicKey, int publicKeyLength, byte[] infoStr, int infoStrLength); - - [DllImport("libcas_core_lib.so")] - public static extern HpkeDecryptResultStruct hpke_decrypt(byte[] cipherText, int cipherTextLength, byte[] privateKey, int privateKeyLength, byte[] encappedKey, int encappedKeyLength, byte[] tag, int tagLength, byte[] infoStr, int infoStrLength); - } -} diff --git a/cas-dotnet-sdk/Hybrid/Types/HpkeDecryptResultStruct.cs b/cas-dotnet-sdk/Hybrid/Types/HpkeDecryptResultStruct.cs deleted file mode 100644 index 065bbb8..0000000 --- a/cas-dotnet-sdk/Hybrid/Types/HpkeDecryptResultStruct.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Hybrid.Types -{ - internal struct HpkeDecryptResultStruct - { - public IntPtr plaintext_ptr; - public long plaintext_ptr_length; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Hybrid/Types/HpkeEncryptResultStruct.cs b/cas-dotnet-sdk/Hybrid/Types/HpkeEncryptResultStruct.cs deleted file mode 100644 index 169d65c..0000000 --- a/cas-dotnet-sdk/Hybrid/Types/HpkeEncryptResultStruct.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace CasDotnetSdk.Hybrid.Types -{ - internal struct HpkeEncryptResultStruct - { - public IntPtr encapped_key_ptr; - public long encapped_key_ptr_length; - public IntPtr ciphertext_ptr; - public long ciphertext_ptr_length; - public IntPtr tag_ptr; - public long tag_ptr_length; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Hybrid/Types/HpkeKeyPairResultStruct.cs b/cas-dotnet-sdk/Hybrid/Types/HpkeKeyPairResultStruct.cs deleted file mode 100644 index d25992f..0000000 --- a/cas-dotnet-sdk/Hybrid/Types/HpkeKeyPairResultStruct.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace CasDotnetSdk.Hybrid.Types -{ - internal struct HpkeKeyPairResultStruct - { - public IntPtr private_key_ptr; - public long private_key_ptr_length; - public IntPtr public_key_ptr; - public long public_key_ptr_length; - public IntPtr info_str_ptr; - public long info_str_ptr_length; - } -} diff --git a/cas-dotnet-sdk/Hybrid/Windows/HpkeWindowsWrapper.cs b/cas-dotnet-sdk/Hybrid/Windows/HpkeWindowsWrapper.cs deleted file mode 100644 index a917292..0000000 --- a/cas-dotnet-sdk/Hybrid/Windows/HpkeWindowsWrapper.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CasDotnetSdk.Hybrid.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Hybrid.Windows -{ - internal static class HpkeWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern HpkeKeyPairResultStruct hpke_generate_keypair(); - - - [DllImport("cas_core_lib.dll")] - public static extern HpkeEncryptResultStruct hpke_encrypt(byte[] plaintext, int plainTextLength, byte[] publicKey, int publicKeyLength, byte[] infoStr, int infoStrLength); - - [DllImport("cas_core_lib.dll")] - public static extern HpkeDecryptResultStruct hpke_decrypt(byte[] cipherText, int cipherTextLength, byte[] privateKey, int privateKeyLength, byte[] encappedKey, int encappedKeyLength, byte[] tag, int tagLength, byte[] infoStr, int infoStrLength); - } -} diff --git a/cas-dotnet-sdk/KeyExchange/Linux/X25519LinuxWrapper.cs b/cas-dotnet-sdk/KeyExchange/Linux/X25519LinuxWrapper.cs deleted file mode 100644 index 258c5e2..0000000 --- a/cas-dotnet-sdk/KeyExchange/Linux/X25519LinuxWrapper.cs +++ /dev/null @@ -1,14 +0,0 @@ -using CasDotnetSdk.KeyExchange.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.KeyExchange.Linux -{ - internal static class X25519LinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern X25519SecretPublicKeyResult generate_secret_and_public_key(); - - [DllImport("libcas_core_lib.so")] - public static extern X25519SharedSecretResult diffie_hellman(byte[] secretKey, int secretKeyLength, byte[] otherUserPublicKey, int otherUserPublickKeyLength); - } -} diff --git a/cas-dotnet-sdk/KeyExchange/Types/X25519SecretPublicKeyResult.cs b/cas-dotnet-sdk/KeyExchange/Types/X25519SecretPublicKeyResult.cs deleted file mode 100644 index 9469787..0000000 --- a/cas-dotnet-sdk/KeyExchange/Types/X25519SecretPublicKeyResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace CasDotnetSdk.KeyExchange.Types -{ - internal struct X25519SecretPublicKeyResult - { - public IntPtr secret_key; - public long secret_key_length; - public IntPtr public_key; - public long public_key_length; - } -} diff --git a/cas-dotnet-sdk/KeyExchange/Types/X25519SharedSecretResult.cs b/cas-dotnet-sdk/KeyExchange/Types/X25519SharedSecretResult.cs deleted file mode 100644 index b3ee8cc..0000000 --- a/cas-dotnet-sdk/KeyExchange/Types/X25519SharedSecretResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.KeyExchange.Types -{ - internal struct X25519SharedSecretResult - { - public IntPtr shared_secret; - public long shared_secret_length; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/KeyExchange/Windows/X25519WindowsWrapper.cs b/cas-dotnet-sdk/KeyExchange/Windows/X25519WindowsWrapper.cs deleted file mode 100644 index 3811e98..0000000 --- a/cas-dotnet-sdk/KeyExchange/Windows/X25519WindowsWrapper.cs +++ /dev/null @@ -1,14 +0,0 @@ -using CasDotnetSdk.KeyExchange.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.KeyExchange.Windows -{ - internal static class X25519WindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern X25519SecretPublicKeyResult generate_secret_and_public_key(); - - [DllImport("cas_core_lib.dll")] - public static extern X25519SharedSecretResult diffie_hellman(byte[] secretKey, int secretKeyLength, byte[] otherUserPublicKey, int otherUserPublickKeyLength); - } -} diff --git a/cas-dotnet-sdk/KeyExchange/X25519Wrapper.cs b/cas-dotnet-sdk/KeyExchange/X25519Wrapper.cs index c58a05f..382d64a 100644 --- a/cas-dotnet-sdk/KeyExchange/X25519Wrapper.cs +++ b/cas-dotnet-sdk/KeyExchange/X25519Wrapper.cs @@ -1,14 +1,11 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.KeyExchange.Linux; using CasDotnetSdk.KeyExchange.Types; -using CasDotnetSdk.KeyExchange.Windows; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.KeyExchange { - public class X25519Wrapper : BaseWrapper + public unsafe class X25519Wrapper : BaseWrapper { /// /// A wrapper class for working with X25519 key exchange algorithm. @@ -20,39 +17,19 @@ public X25519Wrapper() /// /// Generates a secret key and a public key using the X25519 algorithm. /// - /// - /// - public X25519SecretPublicKey GenerateSecretAndPublicKey() { - - X25519SecretPublicKeyResult result = (this._platform == OSPlatform.Linux) ? - X25519LinuxWrapper.generate_secret_and_public_key() : - X25519WindowsWrapper.generate_secret_and_public_key(); - byte[] secretKeyResult = new byte[result.secret_key_length]; - Marshal.Copy(result.secret_key, secretKeyResult, 0, secretKeyResult.Length); - byte[] publicKeyResult = new byte[result.public_key_length]; - Marshal.Copy(result.public_key, publicKeyResult, 0, publicKeyResult.Length); - FreeMemoryHelper.FreeBytesMemory(result.public_key); - FreeMemoryHelper.FreeBytesMemory(result.secret_key); - X25519SecretPublicKey res = new X25519SecretPublicKey() + x25519SecretPublicKeyResult result = NativeMethods.generate_secret_and_public_key(); + return new X25519SecretPublicKey() { - PublicKey = publicKeyResult, - SecretKey = secretKeyResult + SecretKey = NativeByteBuffer.CopyAndFree(result.secret_key, result.secret_key_length), + PublicKey = NativeByteBuffer.CopyAndFree(result.public_key, result.public_key_length) }; - - return res; } /// /// Generates a shared secret using the X25519 algorithm Diffie Hellman. /// - /// - /// - /// - /// - /// - public X25519SharedSecret GenerateSharedSecret(byte[] secretKey, byte[] otherUserPublicKey) { if (secretKey == null || secretKey.Length == 0) @@ -64,21 +41,16 @@ public X25519SharedSecret GenerateSharedSecret(byte[] secretKey, byte[] otherUse throw new Exception("You must provide an allocated data array"); } - - X25519SharedSecretResult result = (this._platform == OSPlatform.Linux) ? - X25519LinuxWrapper.diffie_hellman(secretKey, secretKey.Length, otherUserPublicKey, otherUserPublicKey.Length) - : X25519WindowsWrapper.diffie_hellman(secretKey, secretKey.Length, otherUserPublicKey, otherUserPublicKey.Length); - CasErrorHandler.ThrowIfError(result.error_code, "X25519 Diffie-Hellman"); - byte[] sharedSecret = new byte[result.shared_secret_length]; - Marshal.Copy(result.shared_secret, sharedSecret, 0, sharedSecret.Length); - FreeMemoryHelper.FreeBytesMemory(result.shared_secret); - X25519SharedSecret res = new X25519SharedSecret() + fixed (byte* secretPtr = NativePin.Of(secretKey)) + fixed (byte* publicPtr = NativePin.Of(otherUserPublicKey)) { - SharedSecret = sharedSecret - }; - - - return res; + x25519SharedSecretResult result = NativeMethods.diffie_hellman(secretPtr, (nuint)secretKey.Length, publicPtr, (nuint)otherUserPublicKey.Length); + CasErrorHandler.ThrowIfError(result.error_code, "X25519 Diffie-Hellman"); + return new X25519SharedSecret() + { + SharedSecret = NativeByteBuffer.CopyAndFree(result.shared_secret, result.shared_secret_length) + }; + } } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/PQC/Linux/SLHDSALinuxWrapper.cs b/cas-dotnet-sdk/PQC/Linux/SLHDSALinuxWrapper.cs deleted file mode 100644 index 353a321..0000000 --- a/cas-dotnet-sdk/PQC/Linux/SLHDSALinuxWrapper.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PQC.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PQC.Linux -{ - internal class SLHDSALinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern SLHDSAKeyPairStruct slh_dsa_generate_signing_and_verification_key(); - - [DllImport("libcas_core_lib.so")] - public static extern SLHDSASignatureStruct slh_dsa_sign_message(byte[] signingKey, int signingKeyLength, byte[] message, int messageLength); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult slh_dsa_verify_signature(byte[] verificationKey, int verificationKeyLength, byte[] signature, int signatureLength, byte[] message, int messageLength); - } -} diff --git a/cas-dotnet-sdk/PQC/SLHDSAWrapper.cs b/cas-dotnet-sdk/PQC/SLHDSAWrapper.cs index 7b0720c..bc2e0f7 100644 --- a/cas-dotnet-sdk/PQC/SLHDSAWrapper.cs +++ b/cas-dotnet-sdk/PQC/SLHDSAWrapper.cs @@ -1,55 +1,46 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PQC.Linux; using CasDotnetSdk.PQC.Types; -using CasDotnetSdk.PQC.Windows; -using System.Runtime.InteropServices; namespace CasDotnetSdk.PQC { - public class SLHDSAWrapper : BaseWrapper + public unsafe class SLHDSAWrapper : BaseWrapper { public SLHDSAWrapper() { - } - public SLHDSAKeyPair GenerateSigningAndVerificationKey() { - SLHDSAKeyPairStruct result = (this._platform == OSPlatform.Linux) ? SLHDSALinuxWrapper.slh_dsa_generate_signing_and_verification_key() : SLHDSAWindowsWrapper.slh_dsa_generate_signing_and_verification_key(); - byte[] signingKey = new byte[result.signing_key_length]; - Marshal.Copy(result.signing_key_ptr, signingKey, 0, (int)result.signing_key_length); - FreeMemoryHelper.FreeBytesMemory(result.signing_key_ptr); - - byte[] verificationKey = new byte[result.verification_key_length]; - Marshal.Copy(result.verification_key_ptr, verificationKey, 0, (int)result.verification_key_length); - FreeMemoryHelper.FreeBytesMemory(result.verification_key_ptr); + SlhDsaKeyPairResult result = NativeMethods.slh_dsa_generate_signing_and_verification_key(); return new SLHDSAKeyPair { - SigningKey = signingKey, - VerificationKey = verificationKey + SigningKey = NativeByteBuffer.CopyAndFree(result.signing_key_ptr, result.signing_key_length), + VerificationKey = NativeByteBuffer.CopyAndFree(result.verification_key_ptr, result.verification_key_length) }; } - public byte[] Sign(byte[] signingKey, byte[] message) { - SLHDSASignatureStruct result = (this._platform == OSPlatform.Linux) ? SLHDSALinuxWrapper.slh_dsa_sign_message(signingKey, signingKey.Length, message, message.Length) : SLHDSAWindowsWrapper.slh_dsa_sign_message(signingKey, signingKey.Length, message, message.Length); - CasErrorHandler.ThrowIfError(result.error_code, "SLH-DSA sign"); - byte[] signature = new byte[result.signature_length]; - Marshal.Copy(result.signature_ptr, signature, 0, (int)result.signature_length); - FreeMemoryHelper.FreeBytesMemory(result.signature_ptr); - return signature; + fixed (byte* signingKeyPtr = NativePin.Of(signingKey)) + fixed (byte* messagePtr = NativePin.Of(message)) + { + SlhDsaSignature result = NativeMethods.slh_dsa_sign_message(signingKeyPtr, (nuint)signingKey.Length, messagePtr, (nuint)message.Length); + CasErrorHandler.ThrowIfError(result.error_code, "SLH-DSA sign"); + return NativeByteBuffer.CopyAndFree(result.signature_ptr, result.signature_length); + } } - public bool Verify(byte[] verificationKey, byte[] signature, byte[] message) { - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? SLHDSALinuxWrapper.slh_dsa_verify_signature(verificationKey, verificationKey.Length, signature, signature.Length, message, message.Length) : SLHDSAWindowsWrapper.slh_dsa_verify_signature(verificationKey, verificationKey.Length, signature, signature.Length, message, message.Length); - CasErrorHandler.ThrowIfError(result.error_code, "SLH-DSA verify"); - return result.is_valid; + fixed (byte* verificationKeyPtr = NativePin.Of(verificationKey)) + fixed (byte* signaturePtr = NativePin.Of(signature)) + fixed (byte* messagePtr = NativePin.Of(message)) + { + CasVerifyResult result = NativeMethods.slh_dsa_verify_signature(verificationKeyPtr, (nuint)verificationKey.Length, signaturePtr, (nuint)signature.Length, messagePtr, (nuint)message.Length); + CasErrorHandler.ThrowIfError(result.error_code, "SLH-DSA verify"); + return result.is_valid; + } } } } diff --git a/cas-dotnet-sdk/PQC/Types/SLHDSAKeyPair.cs b/cas-dotnet-sdk/PQC/Types/SLHDSAKeyPair.cs index 74f5f0b..aabc74d 100644 --- a/cas-dotnet-sdk/PQC/Types/SLHDSAKeyPair.cs +++ b/cas-dotnet-sdk/PQC/Types/SLHDSAKeyPair.cs @@ -1,15 +1,5 @@ -using System; - namespace CasDotnetSdk.PQC.Types { - internal struct SLHDSAKeyPairStruct - { - public IntPtr signing_key_ptr { get; set; } - public long signing_key_length { get; set; } - public IntPtr verification_key_ptr { get; set; } - public long verification_key_length { get; set; } - } - public class SLHDSAKeyPair { public byte[] SigningKey { get; set; } diff --git a/cas-dotnet-sdk/PQC/Types/SLHDSASignature.cs b/cas-dotnet-sdk/PQC/Types/SLHDSASignature.cs deleted file mode 100644 index e49c13f..0000000 --- a/cas-dotnet-sdk/PQC/Types/SLHDSASignature.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.PQC.Types -{ - internal struct SLHDSASignatureStruct - { - public IntPtr signature_ptr { get; set; } - public long signature_length { get; set; } - public int error_code { get; set; } - } -} diff --git a/cas-dotnet-sdk/PQC/Windows/SLHDSAWindowsWrapper.cs b/cas-dotnet-sdk/PQC/Windows/SLHDSAWindowsWrapper.cs deleted file mode 100644 index 3860140..0000000 --- a/cas-dotnet-sdk/PQC/Windows/SLHDSAWindowsWrapper.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PQC.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PQC.Windows -{ - internal class SLHDSAWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern SLHDSAKeyPairStruct slh_dsa_generate_signing_and_verification_key(); - - [DllImport("cas_core_lib.dll")] - public static extern SLHDSASignatureStruct slh_dsa_sign_message(byte[] signingKey, int signingKeyLength, byte[] message, int messageLength); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult slh_dsa_verify_signature(byte[] verificationKey, int verificationKeyLength, byte[] signature, int signatureLength, byte[] message, int messageLength); - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/Argon2Wrapper.cs b/cas-dotnet-sdk/PasswordHashers/Argon2Wrapper.cs index d7b58e3..dc96b3e 100644 --- a/cas-dotnet-sdk/PasswordHashers/Argon2Wrapper.cs +++ b/cas-dotnet-sdk/PasswordHashers/Argon2Wrapper.cs @@ -1,17 +1,11 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PasswordHashers.Linux; -using CasDotnetSdk.PasswordHashers.Types; -using CasDotnetSdk.PasswordHashers.Windows; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.PasswordHashers { - public class Argon2Wrapper : BaseWrapper, IPasswordHasherBase + public unsafe class Argon2Wrapper : BaseWrapper, IPasswordHasherBase { - /// /// A wrapper class for the Argon2 password hashing algorithm. /// @@ -23,44 +17,24 @@ public Argon2Wrapper() /// Hashes the specified password using the Argon2 algorithm with the provided memory cost, iteration count, and /// parallelism parameters. /// - /// This method selects the appropriate platform-specific implementation of Argon2 based - /// on the current operating system. The choice of memory cost, iterations, and parallelism directly affects the - /// security and performance of the hash. Ensure that the parameters are chosen according to your application's - /// security requirements. - /// The amount of memory, in kilobytes, to use for the hashing operation. Must be a positive integer. Higher - /// values increase security but require more system memory. - /// The number of iterations to perform during hashing. Must be a positive integer. Increasing this value makes - /// hashing slower and more resistant to brute-force attacks. - /// The degree of parallelism, representing the number of threads to use for hashing. Must be a positive - /// integer. Higher values may improve performance on multi-core systems. - /// The password to hash. Cannot be null or empty. - /// A string containing the Argon2-hashed representation of the input password. - /// Thrown if passToHash is null or empty. - public string HashPasswordWithParameters(int memoryCost, int iterations, int parallelism, string passToHash) { if (string.IsNullOrEmpty(passToHash)) { throw new Exception("You must provide a password to hash using argon2"); } - CasStringResult hashResult = (this._platform == OSPlatform.Linux) ? - Argon2LinuxWrapper.argon2_hash_password_parameters(memoryCost, iterations, parallelism, passToHash) : - Argon2WindowsWrapper.argon2_hash_password_parameters(memoryCost, iterations, parallelism, passToHash); - CasErrorHandler.ThrowIfError(hashResult.error_code, "Argon2 hash"); - string hashed = Marshal.PtrToStringAnsi(hashResult.value); - FreeMemoryHelper.FreeCStringMemory(hashResult.value); - return hashed; - } + fixed (byte* passPtr = NativeString.ToCString(passToHash)) + { + CasStringResult hashResult = NativeMethods.argon2_hash_password_parameters((uint)memoryCost, (uint)iterations, (uint)parallelism, passPtr); + CasErrorHandler.ThrowIfError(hashResult.error_code, "Argon2 hash"); + return NativeString.ReadAndFree(hashResult.value); + } + } /// /// Hashes a password using the Argon2 algorithm. /// - /// - /// - /// - /// - public string HashPassword(string passToHash) { if (string.IsNullOrEmpty(passToHash)) @@ -68,26 +42,17 @@ public string HashPassword(string passToHash) throw new Exception("You must provide a password to hash using argon2"); } - - CasStringResult hashResult = (this._platform == OSPlatform.Linux) ? - Argon2LinuxWrapper.argon2_hash(passToHash) : - Argon2WindowsWrapper.argon2_hash(passToHash); - CasErrorHandler.ThrowIfError(hashResult.error_code, "Argon2 hash"); - string hashed = Marshal.PtrToStringAnsi(hashResult.value); - FreeMemoryHelper.FreeCStringMemory(hashResult.value); - - return hashed; + fixed (byte* passPtr = NativeString.ToCString(passToHash)) + { + CasStringResult hashResult = NativeMethods.argon2_hash(passPtr); + CasErrorHandler.ThrowIfError(hashResult.error_code, "Argon2 hash"); + return NativeString.ReadAndFree(hashResult.value); + } } /// /// Verifies that a none hahsed password matches the hashed password using Argon2 algorithm. /// - /// - /// - /// - /// - /// - public bool Verify(string hashedPasswrod, string password) { if (string.IsNullOrEmpty(hashedPasswrod) || string.IsNullOrEmpty(password)) @@ -95,57 +60,39 @@ public bool Verify(string hashedPasswrod, string password) throw new Exception("You must provide a hashed password and password to verify with argon2"); } - - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? - Argon2LinuxWrapper.argon2_verify(hashedPasswrod, password) : - Argon2WindowsWrapper.argon2_verify(hashedPasswrod, password); - CasErrorHandler.ThrowIfError(result.error_code, "Argon2 verify"); - - return result.is_valid; + fixed (byte* hashedPtr = NativeString.ToCString(hashedPasswrod)) + fixed (byte* passwordPtr = NativeString.ToCString(password)) + { + CasVerifyResult result = NativeMethods.argon2_verify(hashedPtr, passwordPtr); + CasErrorHandler.ThrowIfError(result.error_code, "Argon2 verify"); + return result.is_valid; + } } /// /// Derives an 32-byte AES256 key based off the password passed in using Argon2. /// - /// - /// - /// - public byte[] DeriveAES256Key(string password) { - - Argon2KDFResult kdfResult = (this._platform == OSPlatform.Linux) ? - Argon2LinuxWrapper.argon2_derive_aes_256_key(password) : - Argon2WindowsWrapper.argon2_derive_aes_256_key(password); - CasErrorHandler.ThrowIfError(kdfResult.error_code, "Argon2 derive AES-256 key"); - byte[] result = new byte[kdfResult.length]; - Marshal.Copy(kdfResult.key, result, 0, (int)kdfResult.length); - FreeMemoryHelper.FreeBytesMemory(kdfResult.key); - - - return result; + fixed (byte* passwordPtr = NativeString.ToCString(password)) + { + Argon2KDFAes128 kdfResult = NativeMethods.argon2_derive_aes_256_key(passwordPtr); + CasErrorHandler.ThrowIfError(kdfResult.error_code, "Argon2 derive AES-256 key"); + return NativeByteBuffer.CopyAndFree(kdfResult.key, kdfResult.length); + } } /// /// Derives an 16-byte AES128 key based off the password passed in using Argon2. /// - /// - /// - /// - public byte[] DeriveAES128Key(string password) { - - Argon2KDFResult kdfResult = (this._platform == OSPlatform.Linux) ? - Argon2LinuxWrapper.argon2_derive_aes_128_key(password) : - Argon2WindowsWrapper.argon2_derive_aes_128_key(password); - CasErrorHandler.ThrowIfError(kdfResult.error_code, "Argon2 derive AES-128 key"); - byte[] result = new byte[kdfResult.length]; - Marshal.Copy(kdfResult.key, result, 0, (int)kdfResult.length); - FreeMemoryHelper.FreeBytesMemory(kdfResult.key); - - - return result; + fixed (byte* passwordPtr = NativeString.ToCString(password)) + { + Argon2KDFAes128 kdfResult = NativeMethods.argon2_derive_aes_128_key(passwordPtr); + CasErrorHandler.ThrowIfError(kdfResult.error_code, "Argon2 derive AES-128 key"); + return NativeByteBuffer.CopyAndFree(kdfResult.key, kdfResult.length); + } } } } diff --git a/cas-dotnet-sdk/PasswordHashers/BcryptWrapper.cs b/cas-dotnet-sdk/PasswordHashers/BcryptWrapper.cs index 659faac..9a7e273 100644 --- a/cas-dotnet-sdk/PasswordHashers/BcryptWrapper.cs +++ b/cas-dotnet-sdk/PasswordHashers/BcryptWrapper.cs @@ -1,81 +1,56 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PasswordHashers.Linux; -using CasDotnetSdk.PasswordHashers.Windows; -using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.PasswordHashers { - public class BcryptWrapper : BaseWrapper, IPasswordHasherBase + public unsafe class BcryptWrapper : BaseWrapper, IPasswordHasherBase { - /// /// A wrapper class that uses the BCrypt algorithm to hash passwords. /// public BcryptWrapper() { - } /// /// Hashes a password using the BCrypt algorithm. /// - /// - /// - /// - public string HashPassword(string passwordToHash) { - - - CasStringResult hashResult = (this._platform == OSPlatform.Linux) ? - BcryptLinuxWrapper.bcrypt_hash(passwordToHash) : - BcryptWindowsWrapper.bcrypt_hash(passwordToHash); - CasErrorHandler.ThrowIfError(hashResult.error_code, "BCrypt hash"); - string hashed = Marshal.PtrToStringAnsi(hashResult.value); - FreeMemoryHelper.FreeCStringMemory(hashResult.value); - return hashed; + fixed (byte* passPtr = NativeString.ToCString(passwordToHash)) + { + CasStringResult hashResult = NativeMethods.bcrypt_hash(passPtr); + CasErrorHandler.ThrowIfError(hashResult.error_code, "BCrypt hash"); + return NativeString.ReadAndFree(hashResult.value); + } } + /// /// Hashes a password using the BCrypt algorithm with specified parameters. /// Max cost is 31. /// - /// - /// - /// - - public string HashPasswordWithParameters(string passToHash, uint cost = 12) { - CasStringResult hashResult = (this._platform == OSPlatform.Linux) ? - BcryptLinuxWrapper.bcrypt_hash_with_parameters(passToHash, cost) : - BcryptWindowsWrapper.bcrypt_hash_with_parameters(passToHash, cost); - CasErrorHandler.ThrowIfError(hashResult.error_code, "BCrypt hash"); - string hashed = Marshal.PtrToStringAnsi(hashResult.value); - FreeMemoryHelper.FreeCStringMemory(hashResult.value); - return hashed; + fixed (byte* passPtr = NativeString.ToCString(passToHash)) + { + CasStringResult hashResult = NativeMethods.bcrypt_hash_with_parameters(passPtr, cost); + CasErrorHandler.ThrowIfError(hashResult.error_code, "BCrypt hash"); + return NativeString.ReadAndFree(hashResult.value); + } } /// /// Verifies a hashed password against an unhashed password using the BCrypt algorithm. /// - /// - /// - /// - /// - public bool Verify(string hashedPassword, string unhashed) { - - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? - BcryptLinuxWrapper.bcrypt_verify(unhashed, hashedPassword) : - BcryptWindowsWrapper.bcrypt_verify(unhashed, hashedPassword); ; - CasErrorHandler.ThrowIfError(result.error_code, "BCrypt verify"); - - - return result.is_valid; + fixed (byte* passPtr = NativeString.ToCString(unhashed)) + fixed (byte* hashPtr = NativeString.ToCString(hashedPassword)) + { + CasVerifyResult result = NativeMethods.bcrypt_verify(passPtr, hashPtr); + CasErrorHandler.ThrowIfError(result.error_code, "BCrypt verify"); + return result.is_valid; + } } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/PasswordHashers/Linux/Argon2LinuxWrapper.cs b/cas-dotnet-sdk/PasswordHashers/Linux/Argon2LinuxWrapper.cs deleted file mode 100644 index c784497..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Linux/Argon2LinuxWrapper.cs +++ /dev/null @@ -1,24 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PasswordHashers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PasswordHashers.Linux -{ - internal static class Argon2LinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern Argon2KDFResult argon2_derive_aes_128_key(string password); - - [DllImport("libcas_core_lib.so")] - public static extern Argon2KDFResult argon2_derive_aes_256_key(string password); - - [DllImport("libcas_core_lib.so")] - public static extern CasStringResult argon2_hash(string passToHash); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult argon2_verify(string hashedPassword, string passToVerify); - - [DllImport("libcas_core_lib.so")] - public static extern CasStringResult argon2_hash_password_parameters(int memoryCost, int iterations, int parallelism, string passToHash); - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/Linux/BcryptLinuxWrapper.cs b/cas-dotnet-sdk/PasswordHashers/Linux/BcryptLinuxWrapper.cs deleted file mode 100644 index 27b64cc..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Linux/BcryptLinuxWrapper.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PasswordHashers.Linux -{ - internal static class BcryptLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern CasStringResult bcrypt_hash(string passToHash); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult bcrypt_verify(string password, string hash); - - [DllImport("libcas_core_lib.so")] - public static extern CasStringResult bcrypt_hash_with_parameters(string passToHash, uint cost); - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/Linux/SCryptLinuxWrapper.cs b/cas-dotnet-sdk/PasswordHashers/Linux/SCryptLinuxWrapper.cs deleted file mode 100644 index 8cc2f3e..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Linux/SCryptLinuxWrapper.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PasswordHashers.Linux -{ - internal static class SCryptLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern CasStringResult scrypt_hash(string passToHash); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult scrypt_verify(string hashedPassword, string password); - - [DllImport("libcas_core_lib.so")] - public static extern CasStringResult scrypt_hash_with_parameters(string passToHash, int cpuCost, int blockSize, int paralelism); - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/SCryptWrapper.cs b/cas-dotnet-sdk/PasswordHashers/SCryptWrapper.cs index a0da2e3..e0ff17e 100644 --- a/cas-dotnet-sdk/PasswordHashers/SCryptWrapper.cs +++ b/cas-dotnet-sdk/PasswordHashers/SCryptWrapper.cs @@ -1,14 +1,10 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PasswordHashers.Linux; -using CasDotnetSdk.PasswordHashers.Windows; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.PasswordHashers { - public class SCryptWrapper : BaseWrapper, IPasswordHasherBase + public unsafe class SCryptWrapper : BaseWrapper, IPasswordHasherBase { /// /// A wrapper class that uses the SCrypt algorithm to hash passwords. @@ -20,11 +16,6 @@ public SCryptWrapper() /// /// Hashes a password using the SCrypt algorithm. /// - /// - /// - /// - /// - public string HashPassword(string passToHash) { if (string.IsNullOrEmpty(passToHash)) @@ -32,14 +23,14 @@ public string HashPassword(string passToHash) throw new Exception("Please provide a password to hash"); } - CasStringResult hashResult = (this._platform == OSPlatform.Linux) ? SCryptLinuxWrapper.scrypt_hash(passToHash) : SCryptWindowsWrapper.scrypt_hash(passToHash); - CasErrorHandler.ThrowIfError(hashResult.error_code, "SCrypt hash"); - string hashed = Marshal.PtrToStringAnsi(hashResult.value); - FreeMemoryHelper.FreeCStringMemory(hashResult.value); - return hashed; + fixed (byte* passPtr = NativeString.ToCString(passToHash)) + { + CasStringResult hashResult = NativeMethods.scrypt_hash(passPtr); + CasErrorHandler.ThrowIfError(hashResult.error_code, "SCrypt hash"); + return NativeString.ReadAndFree(hashResult.value); + } } - public string HashPasswordWithParameters(string passToHash, int cpuCost = 17, int blockSize = 8, int parallelism = 1) { if (string.IsNullOrEmpty(passToHash)) @@ -47,22 +38,17 @@ public string HashPasswordWithParameters(string passToHash, int cpuCost = 17, in throw new Exception("Please provide a password to hash"); } - CasStringResult hashResult = (this._platform == OSPlatform.Linux) ? SCryptLinuxWrapper.scrypt_hash_with_parameters(passToHash, cpuCost, blockSize, parallelism) : SCryptWindowsWrapper.scrypt_hash_with_parameters(passToHash, cpuCost, blockSize, parallelism); - CasErrorHandler.ThrowIfError(hashResult.error_code, "SCrypt hash"); - string hashed = Marshal.PtrToStringAnsi(hashResult.value); - FreeMemoryHelper.FreeCStringMemory(hashResult.value); - return hashed; + fixed (byte* passPtr = NativeString.ToCString(passToHash)) + { + CasStringResult hashResult = NativeMethods.scrypt_hash_with_parameters(passPtr, (byte)cpuCost, (uint)blockSize, (uint)parallelism); + CasErrorHandler.ThrowIfError(hashResult.error_code, "SCrypt hash"); + return NativeString.ReadAndFree(hashResult.value); + } } /// /// Verifies an unhashed password against a hashed password using the SCrypt algorithm. /// - /// - /// - /// - /// - /// - public bool Verify(string hashedPassword, string password) { if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(hashedPassword)) @@ -70,12 +56,13 @@ public bool Verify(string hashedPassword, string password) throw new Exception("Please provide a password and a hash to verify"); } - - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? SCryptLinuxWrapper.scrypt_verify(hashedPassword, password) : SCryptWindowsWrapper.scrypt_verify(hashedPassword, password); - CasErrorHandler.ThrowIfError(result.error_code, "SCrypt verify"); - - - return result.is_valid; + fixed (byte* hashPtr = NativeString.ToCString(hashedPassword)) + fixed (byte* passPtr = NativeString.ToCString(password)) + { + CasVerifyResult result = NativeMethods.scrypt_verify(hashPtr, passPtr); + CasErrorHandler.ThrowIfError(result.error_code, "SCrypt verify"); + return result.is_valid; + } } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/PasswordHashers/Types/Argon2KDFResult.cs b/cas-dotnet-sdk/PasswordHashers/Types/Argon2KDFResult.cs deleted file mode 100644 index 4d4e5d4..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Types/Argon2KDFResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.PasswordHashers.Types -{ - internal struct Argon2KDFResult - { - public IntPtr key { get; set; } - public long length { get; set; } - public int error_code { get; set; } - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/Types/Argon2ThreadResult.cs b/cas-dotnet-sdk/PasswordHashers/Types/Argon2ThreadResult.cs deleted file mode 100644 index 7fae77d..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Types/Argon2ThreadResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.PasswordHashers.Types -{ - internal struct Argon2ThreadResult - { - public IntPtr passwords { get; set; } - public int length { get; set; } - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/Windows/Argon2WindowsWrapper.cs b/cas-dotnet-sdk/PasswordHashers/Windows/Argon2WindowsWrapper.cs deleted file mode 100644 index ba37dbe..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Windows/Argon2WindowsWrapper.cs +++ /dev/null @@ -1,24 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.PasswordHashers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PasswordHashers.Windows -{ - internal static class Argon2WindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern Argon2KDFResult argon2_derive_aes_128_key(string password); - - [DllImport("cas_core_lib.dll")] - public static extern Argon2KDFResult argon2_derive_aes_256_key(string password); - - [DllImport("cas_core_lib.dll")] - public static extern CasStringResult argon2_hash(string passToHash); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult argon2_verify(string hashedPassword, string passToVerify); - - [DllImport("cas_core_lib.dll")] - public static extern CasStringResult argon2_hash_password_parameters(int memoryCost, int iterations, int parallelism, string passToHash); - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/Windows/BcryptWindowsWrapper.cs b/cas-dotnet-sdk/PasswordHashers/Windows/BcryptWindowsWrapper.cs deleted file mode 100644 index 737264e..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Windows/BcryptWindowsWrapper.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PasswordHashers.Windows -{ - internal static class BcryptWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern CasStringResult bcrypt_hash(string passToHash); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult bcrypt_verify(string password, string hash); - - [DllImport("cas_core_lib.dll")] - public static extern CasStringResult bcrypt_hash_with_parameters(string passToHash, uint cost); - } -} diff --git a/cas-dotnet-sdk/PasswordHashers/Windows/SCryptWindowsWrapper.cs b/cas-dotnet-sdk/PasswordHashers/Windows/SCryptWindowsWrapper.cs deleted file mode 100644 index 08c9a1c..0000000 --- a/cas-dotnet-sdk/PasswordHashers/Windows/SCryptWindowsWrapper.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.PasswordHashers.Windows -{ - internal static class SCryptWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern CasStringResult scrypt_hash(string passToHash); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult scrypt_verify(string hashedPassword, string password); - - [DllImport("cas_core_lib.dll")] - public static extern CasStringResult scrypt_hash_with_parameters(string passToHash, int cpuCost, int blockSize, int paralelism); - } -} diff --git a/cas-dotnet-sdk/Signatures/ED25519Wrapper.cs b/cas-dotnet-sdk/Signatures/ED25519Wrapper.cs index 855c988..1d665bd 100644 --- a/cas-dotnet-sdk/Signatures/ED25519Wrapper.cs +++ b/cas-dotnet-sdk/Signatures/ED25519Wrapper.cs @@ -1,17 +1,17 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.Signatures.Linux; using CasDotnetSdk.Signatures.Types; -using CasDotnetSdk.Signatures.Windows; using System; -using System.Runtime.InteropServices; + +// Both CasCoreLib (native) and CasDotnetSdk.Signatures.Types (public) define a +// type named Ed25519ByteSignatureResult. Pin the unqualified name to the public +// one; the native struct is referenced fully-qualified below. +using Ed25519ByteSignatureResult = CasDotnetSdk.Signatures.Types.Ed25519ByteSignatureResult; namespace CasDotnetSdk.Signatures { - public class ED25519Wrapper : BaseWrapper + public unsafe class ED25519Wrapper : BaseWrapper { - public ED25519Wrapper() { } @@ -19,39 +19,19 @@ public ED25519Wrapper() /// /// Generates and public and private key pair non split in bytes for ED25519-Dalek. /// - /// - /// - public Ed25519KeyPairResult GetKeyPair() { - - Ed25519KeyPairBytesResultStruct resultStruct = (this._platform == OSPlatform.Linux) ? - ED25519LinuxWrapper.get_ed25519_key_pair_bytes() : - ED25519WindowsWrapper.get_ed25519_key_pair_bytes(); - byte[] signingKey = new byte[resultStruct.signing_key_length]; - Marshal.Copy(resultStruct.signing_key, signingKey, 0, (int)resultStruct.signing_key_length); - byte[] verifyingKey = new byte[resultStruct.verifying_key_length]; - Marshal.Copy(resultStruct.verifying_key, verifyingKey, 0, (int)resultStruct.verifying_key_length); - FreeMemoryHelper.FreeBytesMemory(resultStruct.verifying_key); - FreeMemoryHelper.FreeBytesMemory(resultStruct.signing_key); - - + Ed25519KeyPairBytesResult result = NativeMethods.get_ed25519_key_pair_bytes(); return new Ed25519KeyPairResult() { - SigningKey = signingKey, - VerifyingKey = verifyingKey + SigningKey = NativeByteBuffer.CopyAndFree(result.signing_key, result.signing_key_length), + VerifyingKey = NativeByteBuffer.CopyAndFree(result.verifying_key, result.verifying_key_length) }; } /// /// Signs data with a key pair in bytes for ED25519-Dalek. /// - /// - /// - /// - /// - /// - public Ed25519ByteSignatureResult SignBytes(byte[] keyBytes, byte[] dataToSign) { if (keyBytes == null || keyBytes.Length == 0) @@ -63,36 +43,22 @@ public Ed25519ByteSignatureResult SignBytes(byte[] keyBytes, byte[] dataToSign) throw new Exception("You must provide an array allocated with data to Sign with ED25519-Dalek"); } - - Ed25519ByteSignatureResultStruct resultStruct = (this._platform == OSPlatform.Linux) ? - ED25519LinuxWrapper.sign_with_key_pair_bytes(keyBytes, keyBytes.Length, dataToSign, dataToSign.Length) : - ED25519WindowsWrapper.sign_with_key_pair_bytes(keyBytes, keyBytes.Length, dataToSign, dataToSign.Length); - CasErrorHandler.ThrowIfError(resultStruct.error_code, "ED25519 sign"); - byte[] publicKeyResult = new byte[resultStruct.public_key_length]; - Marshal.Copy(resultStruct.public_key, publicKeyResult, 0, (int)resultStruct.public_key_length); - FreeMemoryHelper.FreeBytesMemory(resultStruct.public_key); - byte[] signatureResult = new byte[resultStruct.signature_length]; - Marshal.Copy(resultStruct.signature_byte_ptr, signatureResult, 0, (int)resultStruct.signature_length); - FreeMemoryHelper.FreeBytesMemory(resultStruct.signature_byte_ptr); - - - return new Ed25519ByteSignatureResult() + fixed (byte* keyPtr = NativePin.Of(keyBytes)) + fixed (byte* dataPtr = NativePin.Of(dataToSign)) { - PublicKey = publicKeyResult, - Signature = signatureResult - }; + CasCoreLib.Ed25519ByteSignatureResult result = NativeMethods.sign_with_key_pair_bytes(keyPtr, (nuint)keyBytes.Length, dataPtr, (nuint)dataToSign.Length); + CasErrorHandler.ThrowIfError(result.error_code, "ED25519 sign"); + return new CasDotnetSdk.Signatures.Types.Ed25519ByteSignatureResult() + { + PublicKey = NativeByteBuffer.CopyAndFree(result.public_key, result.public_key_length), + Signature = NativeByteBuffer.CopyAndFree(result.signature_byte_ptr, result.signature_length) + }; + } } /// /// Verifys data with a key pair in bytes for ED25519-Dalek. /// - /// - /// - /// - /// - /// - /// - public bool VerifyBytes(byte[] keyPair, byte[] signature, byte[] dataToVerify) { if (keyPair?.Length == 0) @@ -108,26 +74,19 @@ public bool VerifyBytes(byte[] keyPair, byte[] signature, byte[] dataToVerify) throw new Exception("You must provide allocated data to Verify with ED25519-Dalek"); } - - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? - ED25519LinuxWrapper.verify_with_key_pair_bytes(keyPair, keyPair.Length, signature, signature.Length, dataToVerify, dataToVerify.Length) : - ED25519WindowsWrapper.verify_with_key_pair_bytes(keyPair, keyPair.Length, signature, signature.Length, dataToVerify, dataToVerify.Length); - CasErrorHandler.ThrowIfError(result.error_code, "ED25519 verify"); - - - return result.is_valid; + fixed (byte* keyPtr = NativePin.Of(keyPair)) + fixed (byte* signaturePtr = NativePin.Of(signature)) + fixed (byte* dataPtr = NativePin.Of(dataToVerify)) + { + CasVerifyResult result = NativeMethods.verify_with_key_pair_bytes(keyPtr, (nuint)keyPair.Length, signaturePtr, (nuint)signature.Length, dataPtr, (nuint)dataToVerify.Length); + CasErrorHandler.ThrowIfError(result.error_code, "ED25519 verify"); + return result.is_valid; + } } /// /// Verifies with a public key in bytes for ED25519-Dalek. /// - /// - /// - /// - /// - /// - /// - public bool VerifyWithPublicKeyBytes(byte[] publicKey, byte[] signature, byte[] dataToVerify) { if (publicKey?.Length == 0) @@ -143,13 +102,14 @@ public bool VerifyWithPublicKeyBytes(byte[] publicKey, byte[] signature, byte[] throw new Exception("You must provide allocated data to verify for the signature to verify with ED25519-Dalek"); } - CasVerifyResult result = (this._platform == OSPlatform.Linux) ? - ED25519LinuxWrapper.verify_with_public_key_bytes(publicKey, publicKey.Length, signature, signature.Length, dataToVerify, dataToVerify.Length) : - ED25519WindowsWrapper.verify_with_public_key_bytes(publicKey, publicKey.Length, signature, signature.Length, dataToVerify, dataToVerify.Length); - CasErrorHandler.ThrowIfError(result.error_code, "ED25519 verify"); - - - return result.is_valid; + fixed (byte* publicPtr = NativePin.Of(publicKey)) + fixed (byte* signaturePtr = NativePin.Of(signature)) + fixed (byte* dataPtr = NativePin.Of(dataToVerify)) + { + CasVerifyResult result = NativeMethods.verify_with_public_key_bytes(publicPtr, (nuint)publicKey.Length, signaturePtr, (nuint)signature.Length, dataPtr, (nuint)dataToVerify.Length); + CasErrorHandler.ThrowIfError(result.error_code, "ED25519 verify"); + return result.is_valid; + } } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/Signatures/Linux/ED25519LinuxWrapper.cs b/cas-dotnet-sdk/Signatures/Linux/ED25519LinuxWrapper.cs deleted file mode 100644 index 5f15e1b..0000000 --- a/cas-dotnet-sdk/Signatures/Linux/ED25519LinuxWrapper.cs +++ /dev/null @@ -1,21 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.Signatures.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Signatures.Linux -{ - internal static class ED25519LinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern Ed25519KeyPairBytesResultStruct get_ed25519_key_pair_bytes(); - - [DllImport("libcas_core_lib.so")] - public static extern Ed25519ByteSignatureResultStruct sign_with_key_pair_bytes(byte[] keyPair, int keyPairLength, byte[] message, int messageLength); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult verify_with_key_pair_bytes(byte[] keyPair, int keyPairLength, byte[] signature, int signatureLength, byte[] message, int messageLength); - - [DllImport("libcas_core_lib.so")] - public static extern CasVerifyResult verify_with_public_key_bytes(byte[] publicKey, int publicKeyLength, byte[] signature, int signatureLength, byte[] dataToVerify, int dataToVerifyLength); - } -} diff --git a/cas-dotnet-sdk/Signatures/Types/Ed25519ByteSignatureResultStruct.cs b/cas-dotnet-sdk/Signatures/Types/Ed25519ByteSignatureResultStruct.cs deleted file mode 100644 index d881378..0000000 --- a/cas-dotnet-sdk/Signatures/Types/Ed25519ByteSignatureResultStruct.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace CasDotnetSdk.Signatures.Types -{ - internal struct Ed25519ByteSignatureResultStruct - { - public IntPtr signature_byte_ptr { get; set; } - public long signature_length { get; set; } - public IntPtr public_key { get; set; } - public long public_key_length { get; set; } - public int error_code { get; set; } - } -} diff --git a/cas-dotnet-sdk/Signatures/Types/Ed25519KeyPairBytesResultStruct.cs b/cas-dotnet-sdk/Signatures/Types/Ed25519KeyPairBytesResultStruct.cs deleted file mode 100644 index eece108..0000000 --- a/cas-dotnet-sdk/Signatures/Types/Ed25519KeyPairBytesResultStruct.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace CasDotnetSdk.Signatures.Types -{ - internal struct Ed25519KeyPairBytesResultStruct - { - public IntPtr signing_key { get; set; } - public long signing_key_length { get; set; } - public IntPtr verifying_key { get; set; } - public long verifying_key_length { get; set; } - } -} diff --git a/cas-dotnet-sdk/Signatures/Types/Ed25519SignatureStruct.cs b/cas-dotnet-sdk/Signatures/Types/Ed25519SignatureStruct.cs deleted file mode 100644 index 8a9728f..0000000 --- a/cas-dotnet-sdk/Signatures/Types/Ed25519SignatureStruct.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Signatures.Types -{ - internal struct Ed25519SignatureStruct - { - public IntPtr Signature { get; set; } - public IntPtr Public_Key { get; set; } - } -} diff --git a/cas-dotnet-sdk/Signatures/Windows/ED25519WindowsWrapper.cs b/cas-dotnet-sdk/Signatures/Windows/ED25519WindowsWrapper.cs deleted file mode 100644 index 0865c72..0000000 --- a/cas-dotnet-sdk/Signatures/Windows/ED25519WindowsWrapper.cs +++ /dev/null @@ -1,22 +0,0 @@ -using CasDotnetSdk.Helpers.Types; -using CasDotnetSdk.Signatures.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Signatures.Windows -{ - internal static class ED25519WindowsWrapper - { - - [DllImport("cas_core_lib.dll")] - public static extern Ed25519KeyPairBytesResultStruct get_ed25519_key_pair_bytes(); - - [DllImport("cas_core_lib.dll")] - public static extern Ed25519ByteSignatureResultStruct sign_with_key_pair_bytes(byte[] keyPair, int keyPairLength, byte[] message, int messageLength); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult verify_with_key_pair_bytes(byte[] keyPair, int keyPairLength, byte[] signature, int signatureLength, byte[] message, int messageLength); - - [DllImport("cas_core_lib.dll")] - public static extern CasVerifyResult verify_with_public_key_bytes(byte[] publicKey, int publicKeyLength, byte[] signature, int signatureLength, byte[] dataToVerify, int dataToVerifyLength); - } -} diff --git a/cas-dotnet-sdk/Sponges/AsconWrapper.cs b/cas-dotnet-sdk/Sponges/AsconWrapper.cs index ca00abd..ab8004d 100644 --- a/cas-dotnet-sdk/Sponges/AsconWrapper.cs +++ b/cas-dotnet-sdk/Sponges/AsconWrapper.cs @@ -1,14 +1,10 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Sponges.Linux; -using CasDotnetSdk.Sponges.Types; -using CasDotnetSdk.Sponges.Windows; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Sponges { - public class AsconWrapper : BaseWrapper + public unsafe class AsconWrapper : BaseWrapper { public AsconWrapper() { @@ -17,49 +13,24 @@ public AsconWrapper() /// /// Generates a key for Ascon 128 /// - /// - /// - public byte[] Ascon128Key() { - - Ascon128KeyStruct keyPtr = (this._platform == OSPlatform.Linux) ? AsconLinuxWrapper.ascon_128_key() : AsconWindowsWrapper.ascon_128_key(); - byte[] key = new byte[keyPtr.length]; - Marshal.Copy(keyPtr.key, key, 0, (int)keyPtr.length); - FreeMemoryHelper.FreeBytesMemory(keyPtr.key); - - - return key; + CasCoreLib.Ascon128Key keyResult = NativeMethods.ascon_128_key(); + return NativeByteBuffer.CopyAndFree(keyResult.key, keyResult.length); } /// /// Generates a nonce for Ascon 128 /// - /// - /// - public byte[] Ascon128Nonce() { - - Ascon128NonceStruct noncePtr = (this._platform == OSPlatform.Linux) ? AsconLinuxWrapper.ascon_128_nonce() : AsconWindowsWrapper.ascon_128_nonce(); - byte[] nonce = new byte[noncePtr.length]; - Marshal.Copy(noncePtr.nonce, nonce, 0, (int)noncePtr.length); - FreeMemoryHelper.FreeBytesMemory(noncePtr.nonce); - - - return nonce; + CasCoreLib.Ascon128Nonce nonceResult = NativeMethods.ascon_128_nonce(); + return NativeByteBuffer.CopyAndFree(nonceResult.nonce, nonceResult.length); } /// /// Encrypts with Ascond 128 /// - /// - /// - /// - /// - /// - /// - public byte[] Ascon128Encrypt(byte[] nonce, byte[] key, byte[] toEncrypt) { if (nonce?.Length == 0) @@ -75,29 +46,19 @@ public byte[] Ascon128Encrypt(byte[] nonce, byte[] key, byte[] toEncrypt) throw new Exception("You must provide data to encrypt with Ascon 128"); } - - Ascon128EncryptResultStruct encryptResult = (this._platform == OSPlatform.Linux) ? - AsconLinuxWrapper.ascon_128_encrypt(nonce, nonce.Length, key, key.Length, toEncrypt, toEncrypt.Length) : - AsconWindowsWrapper.ascon_128_encrypt(nonce, nonce.Length, key, key.Length, toEncrypt, toEncrypt.Length); - CasErrorHandler.ThrowIfError(encryptResult.error_code, "Ascon-128 encrypt"); - byte[] result = new byte[encryptResult.length]; - Marshal.Copy(encryptResult.ciphertext, result, 0, (int)encryptResult.length); - FreeMemoryHelper.FreeBytesMemory(encryptResult.ciphertext); - - - return result; + fixed (byte* noncePtr = NativePin.Of(nonce)) + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* dataPtr = NativePin.Of(toEncrypt)) + { + Ascon128EncryptResult encryptResult = NativeMethods.ascon_128_encrypt(noncePtr, (nuint)nonce.Length, keyPtr, (nuint)key.Length, dataPtr, (nuint)toEncrypt.Length); + CasErrorHandler.ThrowIfError(encryptResult.error_code, "Ascon-128 encrypt"); + return NativeByteBuffer.CopyAndFree(encryptResult.ciphertext, encryptResult.length); + } } /// /// Decrypts with Ascond 128 /// - /// - /// - /// - /// - /// - /// - public byte[] Ascon128Decrypt(byte[] nonce, byte[] key, byte[] toDecrypt) { if (nonce?.Length == 0) @@ -113,17 +74,14 @@ public byte[] Ascon128Decrypt(byte[] nonce, byte[] key, byte[] toDecrypt) throw new Exception("You must provide data to decrypt with Ascon 128"); } - - Ascon128DecryptResultStruct decryptResult = (this._platform == OSPlatform.Linux) ? - AsconLinuxWrapper.ascon_128_decrypt(nonce, nonce.Length, key, key.Length, toDecrypt, toDecrypt.Length) : - AsconWindowsWrapper.ascon_128_decrypt(nonce, nonce.Length, key, key.Length, toDecrypt, toDecrypt.Length); - CasErrorHandler.ThrowIfError(decryptResult.error_code, "Ascon-128 decrypt"); - byte[] result = new byte[decryptResult.length]; - Marshal.Copy(decryptResult.plaintext, result, 0, (int)decryptResult.length); - FreeMemoryHelper.FreeBytesMemory(decryptResult.plaintext); - - - return result; + fixed (byte* noncePtr = NativePin.Of(nonce)) + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* dataPtr = NativePin.Of(toDecrypt)) + { + Ascon128DecryptResult decryptResult = NativeMethods.ascon_128_decrypt(noncePtr, (nuint)nonce.Length, keyPtr, (nuint)key.Length, dataPtr, (nuint)toDecrypt.Length); + CasErrorHandler.ThrowIfError(decryptResult.error_code, "Ascon-128 decrypt"); + return NativeByteBuffer.CopyAndFree(decryptResult.plaintext, decryptResult.length); + } } } } diff --git a/cas-dotnet-sdk/Sponges/Linux/AsconLinuxWrapper.cs b/cas-dotnet-sdk/Sponges/Linux/AsconLinuxWrapper.cs deleted file mode 100644 index 6034a6c..0000000 --- a/cas-dotnet-sdk/Sponges/Linux/AsconLinuxWrapper.cs +++ /dev/null @@ -1,20 +0,0 @@ -using CasDotnetSdk.Sponges.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Sponges.Linux -{ - internal static class AsconLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern Ascon128KeyStruct ascon_128_key(); - - [DllImport("libcas_core_lib.so")] - public static extern Ascon128NonceStruct ascon_128_nonce(); - - [DllImport("libcas_core_lib.so")] - public static extern Ascon128EncryptResultStruct ascon_128_encrypt(byte[] nonce, int NonceLength, byte[] key, int keyLength, byte[] toEncrypt, int toEncryptLength); - - [DllImport("libcas_core_lib.so")] - public static extern Ascon128DecryptResultStruct ascon_128_decrypt(byte[] nonce, int nonceLength, byte[] key, int keyLength, byte[] toDecrypt, int toDecryptLength); - } -} diff --git a/cas-dotnet-sdk/Sponges/Types/Ascon128DecryptResultStruct.cs b/cas-dotnet-sdk/Sponges/Types/Ascon128DecryptResultStruct.cs deleted file mode 100644 index 0f8e5e2..0000000 --- a/cas-dotnet-sdk/Sponges/Types/Ascon128DecryptResultStruct.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Sponges.Types -{ - internal struct Ascon128DecryptResultStruct - { - public IntPtr plaintext { get; set; } - public long length { get; set; } - public int error_code { get; set; } - } -} diff --git a/cas-dotnet-sdk/Sponges/Types/Ascon128EncryptResultStruct.cs b/cas-dotnet-sdk/Sponges/Types/Ascon128EncryptResultStruct.cs deleted file mode 100644 index 8ac77f2..0000000 --- a/cas-dotnet-sdk/Sponges/Types/Ascon128EncryptResultStruct.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Sponges.Types -{ - internal struct Ascon128EncryptResultStruct - { - public IntPtr ciphertext { get; set; } - public long length { get; set; } - public int error_code { get; set; } - } -} diff --git a/cas-dotnet-sdk/Sponges/Types/Ascon128KeyStruct.cs b/cas-dotnet-sdk/Sponges/Types/Ascon128KeyStruct.cs deleted file mode 100644 index 446f3ae..0000000 --- a/cas-dotnet-sdk/Sponges/Types/Ascon128KeyStruct.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Sponges.Types -{ - internal struct Ascon128KeyStruct - { - public IntPtr key; - public long length; - } -} diff --git a/cas-dotnet-sdk/Sponges/Types/Ascon128NonceStruct.cs b/cas-dotnet-sdk/Sponges/Types/Ascon128NonceStruct.cs deleted file mode 100644 index dba6d33..0000000 --- a/cas-dotnet-sdk/Sponges/Types/Ascon128NonceStruct.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Sponges.Types -{ - internal struct Ascon128NonceStruct - { - public IntPtr nonce; - public long length; - } -} diff --git a/cas-dotnet-sdk/Sponges/Windows/AsconWindowsWrapper.cs b/cas-dotnet-sdk/Sponges/Windows/AsconWindowsWrapper.cs deleted file mode 100644 index b638ef5..0000000 --- a/cas-dotnet-sdk/Sponges/Windows/AsconWindowsWrapper.cs +++ /dev/null @@ -1,20 +0,0 @@ -using CasDotnetSdk.Sponges.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Sponges.Windows -{ - internal static class AsconWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern Ascon128KeyStruct ascon_128_key(); - - [DllImport("cas_core_lib.dll")] - public static extern Ascon128NonceStruct ascon_128_nonce(); - - [DllImport("cas_core_lib.dll")] - public static extern Ascon128EncryptResultStruct ascon_128_encrypt(byte[] nonce, int nonceLength, byte[] key, int keyLength, byte[] toEncrypt, int toEncryptLength); - - [DllImport("cas_core_lib.dll")] - public static extern Ascon128DecryptResultStruct ascon_128_decrypt(byte[] nonce, int nonceLength, byte[] key, int keyLength, byte[] toDecrypt, int toDecryptLength); - } -} diff --git a/cas-dotnet-sdk/Symmetric/AESWrapper.cs b/cas-dotnet-sdk/Symmetric/AESWrapper.cs index c4cdb32..b92e78a 100644 --- a/cas-dotnet-sdk/Symmetric/AESWrapper.cs +++ b/cas-dotnet-sdk/Symmetric/AESWrapper.cs @@ -1,66 +1,39 @@ - +using CasCoreLib; using CasDotnetSdk.Helpers; -using CasDotnetSdk.Symmetric.Linux; -using CasDotnetSdk.Symmetric.Types; -using CasDotnetSdk.Symmetric.Windows; using System; -using System.Runtime.InteropServices; namespace CasDotnetSdk.Symmetric { - public class AESWrapper : BaseWrapper + public unsafe class AESWrapper : BaseWrapper { - /// /// A wrapper class for AES-GCM 128 and 256 bit encryption and decryption. /// public AESWrapper() { - } /// /// Generates an AES 128 bit key. /// - /// - /// - public byte[] Aes128Key() { - - AesKeyResult keyResult = (this._platform == OSPlatform.Linux) ? AESLinuxWrapper.aes_128_key() : AESWindowsWrapper.aes_128_key(); - byte[] key = new byte[keyResult.length]; - Marshal.Copy(keyResult.key, key, 0, (int)keyResult.length); - FreeMemoryHelper.FreeBytesMemory(keyResult.key); - - return key; + AesKeyResult keyResult = NativeMethods.aes_128_key(); + return NativeByteBuffer.CopyAndFree(keyResult.key, keyResult.length); } /// /// Generates an AES 256 bit key. /// - /// - /// - public byte[] Aes256Key() { - - AesKeyResult keyResult = (this._platform == OSPlatform.Linux) ? AESLinuxWrapper.aes_256_key() : AESWindowsWrapper.aes_256_key(); - byte[] key = new byte[keyResult.length]; - Marshal.Copy(keyResult.key, key, 0, (int)keyResult.length); - FreeMemoryHelper.FreeBytesMemory(keyResult.key); - - - return key; + AesKeyResult keyResult = NativeMethods.aes_256_key(); + return NativeByteBuffer.CopyAndFree(keyResult.key, keyResult.length); } /// /// Generates an AES 256 bit key and nonce based off a X25519 Diffie Hellman shared secret. /// - /// - /// - /// - public byte[] Aes256KeyNonceX25519DiffieHellman(byte[] sharedSecret) { if (sharedSecret == null || sharedSecret.Length == 0) @@ -68,27 +41,17 @@ public byte[] Aes256KeyNonceX25519DiffieHellman(byte[] sharedSecret) throw new Exception("You must provide allocated data for X25519 shared secret to generate an AES Key"); } - - AesKeyX25519DiffieHellmanStruct result = (this._platform == OSPlatform.Linux) ? - AESLinuxWrapper.aes_256_key_from_x25519_diffie_hellman_shared_secret(sharedSecret, sharedSecret.Length) : - AESWindowsWrapper.aes_256_key_from_x25519_diffie_hellman_shared_secret(sharedSecret, sharedSecret.Length); - CasErrorHandler.ThrowIfError(result.error_code, "AES-256 key from X25519 shared secret"); - byte[] aesKey = new byte[result.aes_key_ptr_length]; - Marshal.Copy(result.aes_key_ptr, aesKey, 0, (int)result.aes_key_ptr_length); - FreeMemoryHelper.FreeBytesMemory(result.aes_key_ptr); - - - return aesKey; + fixed (byte* secretPtr = NativePin.Of(sharedSecret)) + { + AesNonceAndKeyFromX25519DiffieHellman result = NativeMethods.aes_256_key_from_x25519_diffie_hellman_shared_secret(secretPtr, (nuint)sharedSecret.Length); + CasErrorHandler.ThrowIfError(result.error_code, "AES-256 key from X25519 shared secret"); + return NativeByteBuffer.CopyAndFree(result.aes_key_ptr, result.aes_key_ptr_length); + } } /// /// Generates an AES 128 bit key and nonce based off a X25519 Diffie Hellman shared secret. /// - /// - /// - /// - /// - public byte[] Aes128KeyNonceX25519DiffieHellman(byte[] sharedSecret) { if (sharedSecret == null || sharedSecret.Length == 0) @@ -96,133 +59,81 @@ public byte[] Aes128KeyNonceX25519DiffieHellman(byte[] sharedSecret) throw new Exception("You must provide allocated data for X25519 shared secret to generate an AES Key"); } - - AesKeyX25519DiffieHellmanStruct result = (this._platform == OSPlatform.Linux) ? - AESLinuxWrapper.aes_128_key_from_x25519_diffie_hellman_shared_secret(sharedSecret, sharedSecret.Length) : - AESWindowsWrapper.aes_128_key_from_x25519_diffie_hellman_shared_secret(sharedSecret, sharedSecret.Length); - CasErrorHandler.ThrowIfError(result.error_code, "AES-128 key from X25519 shared secret"); - byte[] aesKey = new byte[result.aes_key_ptr_length]; - Marshal.Copy(result.aes_key_ptr, aesKey, 0, (int)result.aes_key_ptr_length); - FreeMemoryHelper.FreeCStringMemory(result.aes_key_ptr); - - - return aesKey; + fixed (byte* secretPtr = NativePin.Of(sharedSecret)) + { + AesNonceAndKeyFromX25519DiffieHellman result = NativeMethods.aes_128_key_from_x25519_diffie_hellman_shared_secret(secretPtr, (nuint)sharedSecret.Length); + CasErrorHandler.ThrowIfError(result.error_code, "AES-128 key from X25519 shared secret"); + return NativeByteBuffer.CopyAndFree(result.aes_key_ptr, result.aes_key_ptr_length); + } } /// /// Encrypts with AES-256-GCM. /// - /// - /// - /// - /// - /// - /// - /// - public byte[] Aes256Encrypt(byte[] nonceKey, byte[] key, byte[] toEncrypt) { - AesBytesEncrypt encryptResult = (this._platform == OSPlatform.Linux) ? - AESLinuxWrapper.aes_256_encrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, toEncrypt, toEncrypt.Length) : - AESWindowsWrapper.aes_256_encrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, toEncrypt, toEncrypt.Length); - CasErrorHandler.ThrowIfError(encryptResult.error_code, "AES-256 encrypt"); - byte[] result = new byte[encryptResult.length]; - Marshal.Copy(encryptResult.ciphertext, result, 0, (int)encryptResult.length); - FreeMemoryHelper.FreeBytesMemory(encryptResult.ciphertext); - - - return result; + fixed (byte* noncePtr = NativePin.Of(nonceKey)) + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* dataPtr = NativePin.Of(toEncrypt)) + { + AesBytesEncrypt encryptResult = NativeMethods.aes_256_encrypt_bytes_with_key(noncePtr, (nuint)nonceKey.Length, keyPtr, (nuint)key.Length, dataPtr, (nuint)toEncrypt.Length); + CasErrorHandler.ThrowIfError(encryptResult.error_code, "AES-256 encrypt"); + return NativeByteBuffer.CopyAndFree(encryptResult.ciphertext, encryptResult.length); + } } - - /// /// Decrypts with AES-256-GCM. /// - /// - /// - /// - /// - /// - /// - public byte[] Aes256Decrypt(byte[] nonceKey, byte[] key, byte[] toDecrypt) { - AesBytesDecrypt encryptResult = (this._platform == OSPlatform.Linux) ? - AESLinuxWrapper.aes_256_decrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, toDecrypt, toDecrypt.Length) : - AESWindowsWrapper.aes_256_decrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, toDecrypt, toDecrypt.Length); - CasErrorHandler.ThrowIfError(encryptResult.error_code, "AES-256 decrypt"); - byte[] result = new byte[encryptResult.length]; - Marshal.Copy(encryptResult.plaintext, result, 0, (int)encryptResult.length); - FreeMemoryHelper.FreeBytesMemory(encryptResult.plaintext); - - - return result; + fixed (byte* noncePtr = NativePin.Of(nonceKey)) + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* dataPtr = NativePin.Of(toDecrypt)) + { + AesBytesDecrypt decryptResult = NativeMethods.aes_256_decrypt_bytes_with_key(noncePtr, (nuint)nonceKey.Length, keyPtr, (nuint)key.Length, dataPtr, (nuint)toDecrypt.Length); + CasErrorHandler.ThrowIfError(decryptResult.error_code, "AES-256 decrypt"); + return NativeByteBuffer.CopyAndFree(decryptResult.plaintext, decryptResult.length); + } } /// /// Encrypts with AES-128-GCM. /// - /// - /// - /// - /// - /// - /// public byte[] Aes128Encrypt(byte[] nonceKey, byte[] key, byte[] dataToEncrypt) { - AesBytesEncrypt encryptResult = (this._platform == OSPlatform.Linux) ? - AESLinuxWrapper.aes_128_encrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, dataToEncrypt, dataToEncrypt.Length) : - AESWindowsWrapper.aes_128_encrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, dataToEncrypt, dataToEncrypt.Length); - CasErrorHandler.ThrowIfError(encryptResult.error_code, "AES-128 encrypt"); - byte[] result = new byte[encryptResult.length]; - Marshal.Copy(encryptResult.ciphertext, result, 0, (int)encryptResult.length); - FreeMemoryHelper.FreeBytesMemory(encryptResult.ciphertext); - - - return result; + fixed (byte* noncePtr = NativePin.Of(nonceKey)) + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* dataPtr = NativePin.Of(dataToEncrypt)) + { + AesBytesEncrypt encryptResult = NativeMethods.aes_128_encrypt_bytes_with_key(noncePtr, (nuint)nonceKey.Length, keyPtr, (nuint)key.Length, dataPtr, (nuint)dataToEncrypt.Length); + CasErrorHandler.ThrowIfError(encryptResult.error_code, "AES-128 encrypt"); + return NativeByteBuffer.CopyAndFree(encryptResult.ciphertext, encryptResult.length); + } } /// /// Decrypts with AES-128-GCM. /// - /// - /// - /// - /// - /// - /// - public byte[] Aes128Decrypt(byte[] nonceKey, byte[] key, byte[] dataToDecrypt) { - AesBytesDecrypt decryptResult = (this._platform == OSPlatform.Linux) ? - AESLinuxWrapper.aes_128_decrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, dataToDecrypt, dataToDecrypt.Length) : - AESWindowsWrapper.aes_128_decrypt_bytes_with_key(nonceKey, nonceKey.Length, key, key.Length, dataToDecrypt, dataToDecrypt.Length); - CasErrorHandler.ThrowIfError(decryptResult.error_code, "AES-128 decrypt"); - byte[] result = new byte[decryptResult.length]; - Marshal.Copy(decryptResult.plaintext, result, 0, (int)decryptResult.length); - FreeMemoryHelper.FreeBytesMemory(decryptResult.plaintext); - - - return result; + fixed (byte* noncePtr = NativePin.Of(nonceKey)) + fixed (byte* keyPtr = NativePin.Of(key)) + fixed (byte* dataPtr = NativePin.Of(dataToDecrypt)) + { + AesBytesDecrypt decryptResult = NativeMethods.aes_128_decrypt_bytes_with_key(noncePtr, (nuint)nonceKey.Length, keyPtr, (nuint)key.Length, dataPtr, (nuint)dataToDecrypt.Length); + CasErrorHandler.ThrowIfError(decryptResult.error_code, "AES-128 decrypt"); + return NativeByteBuffer.CopyAndFree(decryptResult.plaintext, decryptResult.length); + } } /// /// Generates a AES Nonce usuable for AES-128-GCM and AES-256-GCM. /// - /// - /// - public byte[] GenerateAESNonce() { - - AesNonceResult nonceResult = (this._platform == OSPlatform.Linux) ? AESLinuxWrapper.aes_nonce() : AESWindowsWrapper.aes_nonce(); - byte[] result = new byte[nonceResult.length]; - Marshal.Copy(nonceResult.nonce, result, 0, (int)nonceResult.length); - FreeMemoryHelper.FreeBytesMemory(nonceResult.nonce); - - - return result; + AesNonce nonceResult = NativeMethods.aes_nonce(); + return NativeByteBuffer.CopyAndFree(nonceResult.nonce, nonceResult.length); } } -} \ No newline at end of file +} diff --git a/cas-dotnet-sdk/Symmetric/Linux/AESLinuxWrapper.cs b/cas-dotnet-sdk/Symmetric/Linux/AESLinuxWrapper.cs deleted file mode 100644 index e54f56c..0000000 --- a/cas-dotnet-sdk/Symmetric/Linux/AESLinuxWrapper.cs +++ /dev/null @@ -1,37 +0,0 @@ -using CasDotnetSdk.Symmetric.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Symmetric.Linux -{ - internal static class AESLinuxWrapper - { - [DllImport("libcas_core_lib.so")] - public static extern AesNonceResult aes_nonce(); - - - [DllImport("libcas_core_lib.so")] - public static extern AesKeyResult aes_256_key(); - - [DllImport("libcas_core_lib.so")] - public static extern AesKeyResult aes_128_key(); - - - [DllImport("libcas_core_lib.so")] - public static extern AesBytesEncrypt aes_128_encrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToEncrypt, int dataToEncryptLength); - - [DllImport("libcas_core_lib.so")] - public static extern AesBytesDecrypt aes_128_decrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToDecrypt, int dataToDecryptLength); - - [DllImport("libcas_core_lib.so")] - public static extern AesBytesEncrypt aes_256_encrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToEncrypt, int dataToEncryptLength); - - [DllImport("libcas_core_lib.so")] - public static extern AesBytesDecrypt aes_256_decrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToDecrypt, int dataToDecryptLength); - - [DllImport("libcas_core_lib.so")] - public static extern AesKeyX25519DiffieHellmanStruct aes_256_key_from_x25519_diffie_hellman_shared_secret(byte[] sharedSecret, int sharedSecretLength); - - [DllImport("libcas_core_lib.so")] - public static extern AesKeyX25519DiffieHellmanStruct aes_128_key_from_x25519_diffie_hellman_shared_secret(byte[] sharedSecret, int sharedSecretLength); - } -} diff --git a/cas-dotnet-sdk/Symmetric/Types/AesBytesDecrypt.cs b/cas-dotnet-sdk/Symmetric/Types/AesBytesDecrypt.cs deleted file mode 100644 index efcf852..0000000 --- a/cas-dotnet-sdk/Symmetric/Types/AesBytesDecrypt.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Symmetric.Types -{ - internal struct AesBytesDecrypt - { - public IntPtr plaintext { get; set; } - public long length { get; set; } - public int error_code { get; set; } - } -} diff --git a/cas-dotnet-sdk/Symmetric/Types/AesBytesEncrypt.cs b/cas-dotnet-sdk/Symmetric/Types/AesBytesEncrypt.cs deleted file mode 100644 index fa2bbb8..0000000 --- a/cas-dotnet-sdk/Symmetric/Types/AesBytesEncrypt.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Symmetric.Types -{ - internal struct AesBytesEncrypt - { - public IntPtr ciphertext { get; set; } - public long length { get; set; } - public int error_code { get; set; } - } -} diff --git a/cas-dotnet-sdk/Symmetric/Types/AesKeyResult.cs b/cas-dotnet-sdk/Symmetric/Types/AesKeyResult.cs deleted file mode 100644 index 2cf9073..0000000 --- a/cas-dotnet-sdk/Symmetric/Types/AesKeyResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Symmetric.Types -{ - internal struct AesKeyResult - { - public IntPtr key; - public long length; - } -} diff --git a/cas-dotnet-sdk/Symmetric/Types/AesNonceResult.cs b/cas-dotnet-sdk/Symmetric/Types/AesNonceResult.cs deleted file mode 100644 index f1f80b7..0000000 --- a/cas-dotnet-sdk/Symmetric/Types/AesNonceResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace CasDotnetSdk.Symmetric.Types -{ - internal struct AesNonceResult - { - public IntPtr nonce { get; set; } - public long length { get; set; } - } -} diff --git a/cas-dotnet-sdk/Symmetric/Types/AesX25519DiffieHellmanStruct.cs b/cas-dotnet-sdk/Symmetric/Types/AesX25519DiffieHellmanStruct.cs deleted file mode 100644 index 33d1a41..0000000 --- a/cas-dotnet-sdk/Symmetric/Types/AesX25519DiffieHellmanStruct.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace CasDotnetSdk.Symmetric.Types -{ - internal struct AesKeyX25519DiffieHellmanStruct - { - public IntPtr aes_key_ptr; - public long aes_key_ptr_length; - public int error_code; - } -} diff --git a/cas-dotnet-sdk/Symmetric/Windows/AESWindowsWrapper.cs b/cas-dotnet-sdk/Symmetric/Windows/AESWindowsWrapper.cs deleted file mode 100644 index 41a543a..0000000 --- a/cas-dotnet-sdk/Symmetric/Windows/AESWindowsWrapper.cs +++ /dev/null @@ -1,35 +0,0 @@ -using CasDotnetSdk.Symmetric.Types; -using System.Runtime.InteropServices; - -namespace CasDotnetSdk.Symmetric.Windows -{ - internal static class AESWindowsWrapper - { - [DllImport("cas_core_lib.dll")] - public static extern AesNonceResult aes_nonce(); - - [DllImport("cas_core_lib.dll")] - public static extern AesKeyResult aes_256_key(); - - [DllImport("cas_core_lib.dll")] - public static extern AesKeyResult aes_128_key(); - - [DllImport("cas_core_lib.dll")] - public static extern AesBytesEncrypt aes_128_encrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToEncrypt, int dataToEncryptLength); - - [DllImport("cas_core_lib.dll")] - public static extern AesBytesDecrypt aes_128_decrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToDecrypt, int dataToDecryptLength); - - [DllImport("cas_core_lib.dll")] - public static extern AesBytesEncrypt aes_256_encrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToEncrypt, int dataToEncryptLength); - - [DllImport("cas_core_lib.dll")] - public static extern AesBytesDecrypt aes_256_decrypt_bytes_with_key(byte[] nonceKey, int nonceKeyLength, byte[] key, int keyLength, byte[] dataToDecrypt, int dataToDecryptLength); - - [DllImport("cas_core_lib.dll")] - public static extern AesKeyX25519DiffieHellmanStruct aes_256_key_from_x25519_diffie_hellman_shared_secret(byte[] sharedSecret, int sharedSecretLength); - - [DllImport("cas_core_lib.dll")] - public static extern AesKeyX25519DiffieHellmanStruct aes_128_key_from_x25519_diffie_hellman_shared_secret(byte[] sharedSecret, int sharedSecretLength); - } -} diff --git a/cas-dotnet-sdk/generated/NativeMethods.g.cs b/cas-dotnet-sdk/generated/NativeMethods.g.cs index 26e5e8b..47bcd7d 100644 --- a/cas-dotnet-sdk/generated/NativeMethods.g.cs +++ b/cas-dotnet-sdk/generated/NativeMethods.g.cs @@ -18,19 +18,44 @@ internal static unsafe partial class NativeMethods - [DllImport(__DllName, EntryPoint = "sha512_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - internal static extern SHAHashByteResult sha512_bytes(byte* data_to_hash, nuint data_len); + [DllImport(__DllName, EntryPoint = "aes_256_key_from_x25519_diffie_hellman_shared_secret", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesNonceAndKeyFromX25519DiffieHellman aes_256_key_from_x25519_diffie_hellman_shared_secret(byte* shared_secret, nuint shared_secret_length); - [DllImport(__DllName, EntryPoint = "sha512_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - [return: MarshalAs(UnmanagedType.U1)] - internal static extern bool sha512_bytes_verify(byte* data_to_hash, nuint data_len, byte* data_to_verify, nuint data_to_verify_len); + [DllImport(__DllName, EntryPoint = "aes_128_key_from_x25519_diffie_hellman_shared_secret", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesNonceAndKeyFromX25519DiffieHellman aes_128_key_from_x25519_diffie_hellman_shared_secret(byte* shared_secret, nuint shared_secret_length); - [DllImport(__DllName, EntryPoint = "sha256_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - internal static extern SHAHashByteResult sha256_bytes(byte* data_to_hash, nuint data_len); + [DllImport(__DllName, EntryPoint = "aes_nonce", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesNonce aes_nonce(); - [DllImport(__DllName, EntryPoint = "sha256_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - [return: MarshalAs(UnmanagedType.U1)] - internal static extern bool sha256_bytes_verify(byte* data_to_hash, nuint data_len, byte* data_to_verify, nuint data_to_verify_len); + [DllImport(__DllName, EntryPoint = "aes_256_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesKeyResult aes_256_key(); + + [DllImport(__DllName, EntryPoint = "aes_128_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesKeyResult aes_128_key(); + + [DllImport(__DllName, EntryPoint = "aes_128_encrypt_bytes_with_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesBytesEncrypt aes_128_encrypt_bytes_with_key(byte* nonce_key, nuint nonce_key_length, byte* key, nuint key_length, byte* to_encrypt, nuint to_encrypt_length); + + [DllImport(__DllName, EntryPoint = "aes_256_encrypt_bytes_with_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesBytesEncrypt aes_256_encrypt_bytes_with_key(byte* nonce_key, nuint nonce_key_length, byte* key, nuint key_length, byte* to_encrypt, nuint to_encrypt_length); + + [DllImport(__DllName, EntryPoint = "aes_128_decrypt_bytes_with_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesBytesDecrypt aes_128_decrypt_bytes_with_key(byte* nonce_key, nuint nonce_key_length, byte* key, nuint key_length, byte* to_decrypt, nuint to_decrypt_length); + + [DllImport(__DllName, EntryPoint = "aes_256_decrypt_bytes_with_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern AesBytesDecrypt aes_256_decrypt_bytes_with_key(byte* nonce_key, nuint nonce_key_length, byte* key, nuint key_length, byte* to_decrypt, nuint to_decrypt_length); + + [DllImport(__DllName, EntryPoint = "ascon_128_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Ascon128Key ascon_128_key(); + + [DllImport(__DllName, EntryPoint = "ascon_128_nonce", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Ascon128Nonce ascon_128_nonce(); + + [DllImport(__DllName, EntryPoint = "ascon_128_encrypt", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Ascon128EncryptResult ascon_128_encrypt(byte* nonce_key, nuint nonce_key_length, byte* key, nuint key_length, byte* to_encrypt, nuint to_encrypt_length); + + [DllImport(__DllName, EntryPoint = "ascon_128_decrypt", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Ascon128DecryptResult ascon_128_decrypt(byte* nonce_key, nuint nonce_key_length, byte* key, nuint key_length, byte* to_decrypt, nuint to_decrypt_length); [DllImport(__DllName, EntryPoint = "blake2_512_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern Blake2HashByteResult blake2_512_bytes(byte* data, nuint data_length); @@ -46,19 +71,184 @@ internal static unsafe partial class NativeMethods [return: MarshalAs(UnmanagedType.U1)] internal static extern bool blake2_256_bytes_verify(byte* hashed_data, nuint hashed_data_length, byte* to_compare, nuint to_compare_length); + [DllImport(__DllName, EntryPoint = "get_ed25519_key_pair_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Ed25519KeyPairBytesResult get_ed25519_key_pair_bytes(); + + [DllImport(__DllName, EntryPoint = "sign_with_key_pair_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Ed25519ByteSignatureResult sign_with_key_pair_bytes(byte* key_pair, nuint key_pair_length, byte* message_to_sign, nuint message_to_sign_length); + + [DllImport(__DllName, EntryPoint = "verify_with_key_pair_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult verify_with_key_pair_bytes(byte* key_pair, nuint key_pair_length, byte* signature, nuint signature_length, byte* message, nuint message_length); + + [DllImport(__DllName, EntryPoint = "verify_with_public_key_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult verify_with_public_key_bytes(byte* public_key, nuint public_key_length, byte* signature, nuint signature_length, byte* message, nuint message_length); + [DllImport(__DllName, EntryPoint = "free_cstring", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern void free_cstring(byte* s); [DllImport(__DllName, EntryPoint = "free_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern void free_bytes(byte* ptr); + [DllImport(__DllName, EntryPoint = "hmac_sign_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern HmacSignByteResult hmac_sign_bytes(byte* key, nuint key_length, byte* message, nuint message_length); + + [DllImport(__DllName, EntryPoint = "hmac_verify_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult hmac_verify_bytes(byte* key, nuint key_length, byte* message, nuint message_length, byte* signature, nuint signature_length); + + [DllImport(__DllName, EntryPoint = "hpke_generate_keypair", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern HpkeKeyPair hpke_generate_keypair(); + + [DllImport(__DllName, EntryPoint = "hpke_encrypt", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern HpkeEncrypt hpke_encrypt(byte* plaintext, nuint plaintext_length, byte* public_key, nuint public_keylength, byte* info_str, nuint info_str_length); + + [DllImport(__DllName, EntryPoint = "hpke_decrypt", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern HpkeDecrypt hpke_decrypt(byte* ciphertext, nuint ciphertext_length, byte* private_key, nuint private_keylength, byte* encapped_key, nuint encapped_key_length, byte* tag, nuint tag_length, byte* info_str, nuint info_str_length); + + [DllImport(__DllName, EntryPoint = "argon2_hash_password_parameters", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasStringResult argon2_hash_password_parameters(uint memory_cost, uint iterations, uint parallelism, byte* password_to_hash); + + [DllImport(__DllName, EntryPoint = "argon2_derive_aes_128_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Argon2KDFAes128 argon2_derive_aes_128_key(byte* hashed_password); + + [DllImport(__DllName, EntryPoint = "argon2_derive_aes_256_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern Argon2KDFAes128 argon2_derive_aes_256_key(byte* hashed_password); + + [DllImport(__DllName, EntryPoint = "argon2_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult argon2_verify(byte* hashed_pass, byte* password); + + [DllImport(__DllName, EntryPoint = "argon2_hash", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasStringResult argon2_hash(byte* pass_to_hash); + + [DllImport(__DllName, EntryPoint = "bcrypt_hash_with_parameters", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasStringResult bcrypt_hash_with_parameters(byte* pass_to_hash, uint cost); + + [DllImport(__DllName, EntryPoint = "bcrypt_hash", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasStringResult bcrypt_hash(byte* pass_to_hash); + + [DllImport(__DllName, EntryPoint = "bcrypt_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult bcrypt_verify(byte* pass, byte* hash); + + [DllImport(__DllName, EntryPoint = "scrypt_hash_with_parameters", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasStringResult scrypt_hash_with_parameters(byte* pass_to_hash, byte cpu_memory_cost, uint block_size, uint parallelism); + + [DllImport(__DllName, EntryPoint = "scrypt_hash", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasStringResult scrypt_hash(byte* pass_to_hash); + + [DllImport(__DllName, EntryPoint = "scrypt_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult scrypt_verify(byte* hash_to_check, byte* pass_to_check); + + [DllImport(__DllName, EntryPoint = "slh_dsa_generate_signing_and_verification_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern SlhDsaKeyPairResult slh_dsa_generate_signing_and_verification_key(); + + [DllImport(__DllName, EntryPoint = "slh_dsa_sign_message", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern SlhDsaSignature slh_dsa_sign_message(byte* signing_key, nuint signing_key_length, byte* message, nuint message_length); + + [DllImport(__DllName, EntryPoint = "slh_dsa_verify_signature", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult slh_dsa_verify_signature(byte* verification_key, nuint verification_key_length, byte* signature, nuint signature_length, byte* message, nuint message_length); + + [DllImport(__DllName, EntryPoint = "get_key_pair", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern RsaKeyPair get_key_pair(nuint key_size); + + [DllImport(__DllName, EntryPoint = "rsa_sign_with_key_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern RsaSignBytesResults rsa_sign_with_key_bytes(byte* private_key, byte* data_to_sign, nuint data_to_sign_length); + + [DllImport(__DllName, EntryPoint = "rsa_verify_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern CasVerifyResult rsa_verify_bytes(byte* public_key, byte* data_to_verify, nuint data_to_verify_length, byte* signature, nuint signature_length); + + [DllImport(__DllName, EntryPoint = "sha512_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern SHAHashByteResult sha512_bytes(byte* data_to_hash, nuint data_len); + + [DllImport(__DllName, EntryPoint = "sha512_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool sha512_bytes_verify(byte* data_to_hash, nuint data_len, byte* data_to_verify, nuint data_to_verify_len); + + [DllImport(__DllName, EntryPoint = "sha256_bytes", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern SHAHashByteResult sha256_bytes(byte* data_to_hash, nuint data_len); + + [DllImport(__DllName, EntryPoint = "sha256_bytes_verify", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: MarshalAs(UnmanagedType.U1)] + internal static extern bool sha256_bytes_verify(byte* data_to_hash, nuint data_len, byte* data_to_verify, nuint data_to_verify_len); + + [DllImport(__DllName, EntryPoint = "generate_secret_and_public_key", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern x25519SecretPublicKeyResult generate_secret_and_public_key(); + + [DllImport(__DllName, EntryPoint = "diffie_hellman", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern x25519SharedSecretResult diffie_hellman(byte* secret_key, nuint secret_key_length, byte* other_user_public_key, nuint other_user_public_key_length); + + [DllImport(__DllName, EntryPoint = "decompress", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern ZstdCompressResult decompress(byte* data_to_decompress, nuint data_to_decompress_length); + + [DllImport(__DllName, EntryPoint = "compress", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern ZstdCompressResult compress(byte* data_to_compress, nuint data_to_compress_length, nuint level); + } [StructLayout(LayoutKind.Sequential)] - internal unsafe partial struct SHAHashByteResult + internal unsafe partial struct AesNonce { - public byte* result_bytes_ptr; + public byte* nonce; + public nuint length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct AesKeyResult + { + public byte* key; + public nuint length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct AesBytesEncrypt + { + public byte* ciphertext; + public nuint length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct AesBytesDecrypt + { + public byte* plaintext; + public nuint length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct AesNonceAndKeyFromX25519DiffieHellman + { + public byte* aes_key_ptr; + public nuint aes_key_ptr_length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Ascon128EncryptResult + { + public byte* ciphertext; + public nuint length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Ascon128DecryptResult + { + public byte* plaintext; + public nuint length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Ascon128Key + { + public byte* key; + public nuint length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Ascon128Nonce + { + public byte* nonce; public nuint length; } @@ -69,6 +259,165 @@ internal unsafe partial struct Blake2HashByteResult public nuint length; } + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Ed25519KeyPairBytesResult + { + public byte* signing_key; + public nuint signing_key_length; + public byte* verifying_key; + public nuint verifying_key_length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Ed25519ByteSignatureResult + { + public byte* signature_byte_ptr; + public nuint signature_length; + public byte* public_key; + public nuint public_key_length; + public int error_code; + } + + /// + /// Result of a verification (`verify`-style) FFI call. + /// + /// cas-lib's verify operations now return `CasResult<bool>`, so a plain `bool` + /// can no longer distinguish "signature did not match" (`is_valid == false`, + /// `error_code == 0`) from "the inputs were malformed" (`is_valid == false`, + /// `error_code != 0`). This struct carries both across the boundary. + /// + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct CasVerifyResult + { + [MarshalAs(UnmanagedType.U1)] public bool is_valid; + public int error_code; + } + + /// + /// Result of an FFI call that hands back a C string (e.g. a password hash). + /// + /// `value` is null when `error_code` is non-zero. The caller still frees a + /// non-null `value` with [`free_cstring`]. + /// + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct CasStringResult + { + public byte* value; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct HmacSignByteResult + { + public byte* result_bytes_ptr; + public nuint length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct HpkeKeyPair + { + public byte* private_key_ptr; + public nuint private_key_ptr_length; + public byte* public_key_ptr; + public nuint public_key_ptr_length; + public byte* info_str_ptr; + public nuint info_str_ptr_length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct HpkeEncrypt + { + public byte* encapped_key_ptr; + public nuint encapped_key_ptr_length; + public byte* ciphertext_ptr; + public nuint ciphertext_ptr_length; + public byte* tag_ptr; + public nuint tag_ptr_length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct HpkeDecrypt + { + public byte* plaintext_ptr; + public nuint plaintext_ptr_length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct Argon2KDFAes128 + { + public byte* key; + public nuint length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct SlhDsaKeyPairResult + { + public byte* signing_key_ptr; + public nuint signing_key_length; + public byte* verification_key_ptr; + public nuint verification_key_length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct SlhDsaSignature + { + public byte* signature_ptr; + public nuint signature_length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct RsaKeyPair + { + public byte* pub_key; + public byte* priv_key; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct RsaSignBytesResults + { + public byte* signature_raw_ptr; + public nuint length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct SHAHashByteResult + { + public byte* result_bytes_ptr; + public nuint length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct x25519SecretPublicKeyResult + { + public byte* secret_key; + public nuint secret_key_length; + public byte* public_key; + public nuint public_key_length; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct x25519SharedSecretResult + { + public byte* shared_secret; + public nuint shared_secret_length; + public int error_code; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct ZstdCompressResult + { + public byte* data; + public nuint length; + public int error_code; + } + } From 6a6b18ce37f13db7f501b6de67102c58f1c14877 Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Thu, 18 Jun 2026 18:04:56 -0400 Subject: [PATCH 3/4] upgrade cas-core-lib version --- cas-core-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cas-core-lib b/cas-core-lib index 8f30188..5f2db99 160000 --- a/cas-core-lib +++ b/cas-core-lib @@ -1 +1 @@ -Subproject commit 8f301881ed04c7927e0679a0b12036bf39402677 +Subproject commit 5f2db993e8b213bddd391029f7862c4c5eec1a6a From d8e03a3d3405919b197413e4f5de0e3376cc553d Mon Sep 17 00:00:00 2001 From: Mike Mulchrone Date: Thu, 18 Jun 2026 18:06:19 -0400 Subject: [PATCH 4/4] version bump --- cas-dotnet-sdk/cas-dotnet-sdk.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cas-dotnet-sdk/cas-dotnet-sdk.csproj b/cas-dotnet-sdk/cas-dotnet-sdk.csproj index d56bc04..6d3c061 100644 --- a/cas-dotnet-sdk/cas-dotnet-sdk.csproj +++ b/cas-dotnet-sdk/cas-dotnet-sdk.csproj @@ -9,7 +9,7 @@ true cas-dotnet-sdk icon.jpeg - 1.9.73 + 1.9.74 Mike Mulchrone A Nuget package that provides a implementation of the RustCrypto suite of cryptographic algorithms. https://github.com/Cryptographic-API-Services/cas-dotnet-sdk