diff --git a/README.md b/README.md index 8c1d572..bc11e68 100644 --- a/README.md +++ b/README.md @@ -113,8 +113,8 @@ finally ## Features -- **Key Encapsulation Mechanisms (KEMs)**: ML-KEM, Kyber, FrodoKEM, and more -- **Digital Signatures**: ML-DSA, Dilithium, Falcon, SPHINCS+, and more +- **Key Encapsulation Mechanisms (KEMs)**: ML-KEM, Kyber, BIKE, HQC, Classic McEliece, NTRU Prime, FrodoKEM +- **Digital Signatures**: ML-DSA, Dilithium, Falcon, SPHINCS+, MAYO, CROSS, UOV - **Type-safe API**: Strong typing with enums for algorithms and proper resource management - **Memory management**: Automatic cleanup of native resources using IDisposable pattern - **Cross-platform**: Supports Windows x64, Windows ARM64, macOS ARM64, Linux x64, and Linux ARM64 @@ -126,14 +126,21 @@ finally - **ML-KEM** (NIST standardized): ML-KEM-512, ML-KEM-768, ML-KEM-1024 - **Kyber**: Kyber512, Kyber768, Kyber1024 +- **BIKE**: BIKE-L1, BIKE-L3, BIKE-L5 +- **HQC**: HQC-128, HQC-192, HQC-256 +- **Classic McEliece**: All 10 variants (e.g., 348864, 460896, 6688128, 6960119, 8192128 with fast variants) +- **NTRU Prime**: sntrup761 - **FrodoKEM**: FrodoKEM-640-AES, FrodoKEM-640-SHAKE, FrodoKEM-976-AES, FrodoKEM-976-SHAKE, FrodoKEM-1344-AES, FrodoKEM-1344-SHAKE ### Digital Signatures - **ML-DSA** (NIST standardized): ML-DSA-44, ML-DSA-65, ML-DSA-87 - **Dilithium**: Dilithium2, Dilithium3, Dilithium5 -- **Falcon**: Falcon-512, Falcon-1024 -- **SPHINCS+**: Various parameter sets +- **Falcon**: Falcon-512, Falcon-1024, Falcon-Padded-512, Falcon-Padded-1024 +- **SPHINCS+**: All "simple" variants (SHA2 and SHAKE, 128/192/256, fast/small) +- **MAYO**: MAYO-1, MAYO-2, MAYO-3, MAYO-5 +- **CROSS**: All 18 variants (RSDP/RSDPG, Balanced/Fast/Small) +- **UOV**: All 12 variants (Ip, Is, III, V; with pkc/skc variants) ## Algorithm Availability @@ -222,7 +229,7 @@ git submodule update This will: - Configure and build liboqs as a shared library - Copy the resulting DLL/so/dylib to the appropriate directories - - Enable common quantum-resistant algorithms (ML-KEM, ML-DSA, Kyber, Dilithium, Falcon, FrodoKEM) + - Enable all common quantum-resistant algorithms (ML-KEM, ML-DSA, Kyber, Dilithium, Falcon, FrodoKEM, BIKE, HQC, SPHINCS+, etc.) 2. **Build the .NET libraries:** diff --git a/build-dotnet-liboqs-linux.sh b/build-dotnet-liboqs-linux.sh index 464ebff..1c3df5f 100755 --- a/build-dotnet-liboqs-linux.sh +++ b/build-dotnet-liboqs-linux.sh @@ -40,9 +40,17 @@ CMAKE_ARGS="$CMAKE_ARGS -DOQS_PERMIT_UNSUPPORTED_ARCHITECTURE=ON" CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_ML_KEM=ON" CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_KYBER=ON" CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_FRODOKEM=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_BIKE=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_HQC=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_NTRUPRIME=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_CLASSIC_MCELIECE=ON" CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_ML_DSA=ON" CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_DILITHIUM=ON" CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_FALCON=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_SPHINCS=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_MAYO=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_CROSS=ON" +CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_UOV=ON" # Add toolchain file if specified if [ -n "$CMAKE_TOOLCHAIN_FILE" ]; then diff --git a/build-dotnet-liboqs-macos.sh b/build-dotnet-liboqs-macos.sh index 65f6820..218c0f3 100644 --- a/build-dotnet-liboqs-macos.sh +++ b/build-dotnet-liboqs-macos.sh @@ -42,9 +42,17 @@ cmake .. \ -DOQS_ENABLE_KEM_ML_KEM=ON \ -DOQS_ENABLE_KEM_KYBER=ON \ -DOQS_ENABLE_KEM_FRODOKEM=ON \ + -DOQS_ENABLE_KEM_BIKE=ON \ + -DOQS_ENABLE_KEM_HQC=ON \ + -DOQS_ENABLE_KEM_NTRUPRIME=ON \ + -DOQS_ENABLE_KEM_CLASSIC_MCELIECE=ON \ -DOQS_ENABLE_SIG_ML_DSA=ON \ -DOQS_ENABLE_SIG_DILITHIUM=ON \ - -DOQS_ENABLE_SIG_FALCON=ON + -DOQS_ENABLE_SIG_FALCON=ON \ + -DOQS_ENABLE_SIG_SPHINCS=ON \ + -DOQS_ENABLE_SIG_MAYO=ON \ + -DOQS_ENABLE_SIG_CROSS=ON \ + -DOQS_ENABLE_SIG_UOV=ON echo "Building liboqs..." cmake --build . --config "$CONFIGURATION" diff --git a/build-dotnet-liboqs.ps1 b/build-dotnet-liboqs.ps1 index 19787aa..89169b8 100644 --- a/build-dotnet-liboqs.ps1 +++ b/build-dotnet-liboqs.ps1 @@ -50,9 +50,16 @@ try { "-DOQS_ENABLE_KEM_ML_KEM=ON" "-DOQS_ENABLE_KEM_KYBER=ON" "-DOQS_ENABLE_KEM_FRODOKEM=ON" + "-DOQS_ENABLE_KEM_HQC=ON" + "-DOQS_ENABLE_KEM_NTRUPRIME=ON" + "-DOQS_ENABLE_KEM_CLASSIC_MCELIECE=ON" "-DOQS_ENABLE_SIG_ML_DSA=ON" "-DOQS_ENABLE_SIG_DILITHIUM=ON" "-DOQS_ENABLE_SIG_FALCON=ON" + "-DOQS_ENABLE_SIG_SPHINCS=ON" + "-DOQS_ENABLE_SIG_MAYO=ON" + "-DOQS_ENABLE_SIG_CROSS=ON" + "-DOQS_ENABLE_SIG_UOV=ON" ) & cmake @cmakeArgs diff --git a/samples/Examples/Program.cs b/samples/Examples/Program.cs index 2fef068..8374166 100644 --- a/samples/Examples/Program.cs +++ b/samples/Examples/Program.cs @@ -1,6 +1,6 @@ +using System.Text; using LibOQS.NET; using Spectre.Console; -using System.Text; namespace Examples; @@ -22,8 +22,8 @@ static void Main(string[] args) new SelectionPrompt() .Title("Choose the [green]demo[/] to run?") .AddChoices([ - "ML-KEM (Key Encapsulation)", - "ML-DSA (Digital Signature)", + "KEM (Key Encapsulation)", + "DSA (Digital Signature)", "Signed Key Exchange", "Algorithm Comparison", "Exit" @@ -31,10 +31,10 @@ static void Main(string[] args) switch (demo) { - case "ML-KEM (Key Encapsulation)": + case "KEM (Key Encapsulation)": LibOqsDemo.RunMlKem(); break; - case "ML-DSA (Digital Signature)": + case "DSA (Digital Signature)": LibOqsDemo.RunMlDsa(); break; case "Signed Key Exchange": @@ -55,23 +55,27 @@ public static class LibOqsDemo { public static void RunMlDsa() { - AnsiConsole.Write(new Rule("[blue]ML-DSA Digital Signature Demo[/]").RuleStyle("blue")); + AnsiConsole.Write(new Rule("[blue]Digital Signature Demo[/]").RuleStyle("blue")); + + var enabledAlgorithms = Enum.GetValues() + .Where(a => a.IsEnabled()) + .ToList(); + + var algorithm = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a [green]Signature Algorithm[/] to demo:") + .PageSize(10) + .AddChoices(enabledAlgorithms)); - var raw = "Hello, ML-DSA from LibOQS.NET!"; + var raw = $"Hello, {algorithm} from LibOQS.NET!"; var data = Encoding.UTF8.GetBytes(raw); - + PrintPanel("Message", [ $"Raw: {raw}", $"Encoded: {data.PrettyPrint()}" ]); - if (!SigAlgorithm.MlDsa65.IsEnabled()) - { - PrintPanel("Error", ["ML-DSA-65 is not enabled in this build"]); - return; - } - - using var sig = new SigInstance(SigAlgorithm.MlDsa65); + using var sig = new SigInstance(algorithm); // Generate key pair var (publicKey, secretKey) = sig.GenerateKeypair(); @@ -103,15 +107,19 @@ public static void RunMlDsa() public static void RunMlKem() { - AnsiConsole.Write(new Rule("[green]ML-KEM Key Encapsulation Demo[/]").RuleStyle("green")); + AnsiConsole.Write(new Rule("[green]Key Encapsulation Demo[/]").RuleStyle("green")); - if (!KemAlgorithm.MlKem768.IsEnabled()) - { - PrintPanel("Error", ["ML-KEM-768 is not enabled in this build"]); - return; - } + var enabledAlgorithms = Enum.GetValues() + .Where(a => a.IsEnabled()) + .ToList(); + + var algorithm = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select a [green]KEM Algorithm[/] to demo:") + .PageSize(10) + .AddChoices(enabledAlgorithms)); - using var kem = new KemInstance(KemAlgorithm.MlKem768); + using var kem = new KemInstance(algorithm); // Generate Alice's key pair var (alicePublicKey, aliceSecretKey) = kem.GenerateKeypair(); @@ -251,9 +259,9 @@ public static void RunAlgorithmComparison() var secLevel = kemAlg switch { - KemAlgorithm.MlKem512 or KemAlgorithm.Kyber512 => "Level 1", - KemAlgorithm.MlKem768 or KemAlgorithm.Kyber768 => "Level 3", - KemAlgorithm.MlKem1024 or KemAlgorithm.Kyber1024 => "Level 5", + KemAlgorithm.MlKem512 or KemAlgorithm.Kyber512 or KemAlgorithm.BikeL1 or KemAlgorithm.Hqc128 or KemAlgorithm.ClassicMcEliece348864 => "Level 1", + KemAlgorithm.MlKem768 or KemAlgorithm.Kyber768 or KemAlgorithm.BikeL3 or KemAlgorithm.Hqc192 or KemAlgorithm.NtruPrimeSntrup761 or KemAlgorithm.ClassicMcEliece460896 => "Level 3", + KemAlgorithm.MlKem1024 or KemAlgorithm.Kyber1024 or KemAlgorithm.BikeL5 or KemAlgorithm.Hqc256 or KemAlgorithm.ClassicMcEliece6688128 or KemAlgorithm.ClassicMcEliece6960119 or KemAlgorithm.ClassicMcEliece8192128 => "Level 5", _ when kemAlg.ToString().Contains("640") => "Level 1", _ when kemAlg.ToString().Contains("976") => "Level 3", _ when kemAlg.ToString().Contains("1344") => "Level 5", @@ -289,10 +297,18 @@ _ when kemAlg.ToString().Contains("1344") => "Level 5", var secLevel = sigAlg switch { - SigAlgorithm.MlDsa44 or SigAlgorithm.Dilithium2 or SigAlgorithm.Falcon512 => "Level 1", + SigAlgorithm.MlDsa44 or SigAlgorithm.Dilithium2 or SigAlgorithm.Falcon512 or SigAlgorithm.FalconPadded512 => "Level 1", SigAlgorithm.MlDsa65 or SigAlgorithm.Dilithium3 => "Level 3", - SigAlgorithm.MlDsa87 or SigAlgorithm.Dilithium5 or SigAlgorithm.Falcon1024 => "Level 5", + SigAlgorithm.MlDsa87 or SigAlgorithm.Dilithium5 or SigAlgorithm.Falcon1024 or SigAlgorithm.FalconPadded1024 => "Level 5", _ when sigAlg.ToString().Contains("128") => "Level 1", + _ when sigAlg.ToString().Contains("192") => "Level 3", + _ when sigAlg.ToString().Contains("256") => "Level 5", + _ when sigAlg.ToString().Contains("Mayo1") || sigAlg.ToString().Contains("Mayo2") => "Level 1", + _ when sigAlg.ToString().Contains("Mayo3") => "Level 3", + _ when sigAlg.ToString().Contains("Mayo5") => "Level 5", + _ when sigAlg.ToString().Contains("OvIs") || sigAlg.ToString().Contains("OvIp") => "Level 1", + _ when sigAlg.ToString().Contains("OvIii") => "Level 3", + _ when sigAlg.ToString().Contains("OvV") => "Level 5", _ => "Various" }; diff --git a/src/LibOQS.NET.Native/Kem.cs b/src/LibOQS.NET.Native/Kem.cs index d251e71..cf8ed13 100644 --- a/src/LibOQS.NET.Native/Kem.cs +++ b/src/LibOQS.NET.Native/Kem.cs @@ -81,6 +81,23 @@ public struct OqsKem public static readonly string OQS_KEM_alg_kyber_512 = "Kyber512"; public static readonly string OQS_KEM_alg_kyber_768 = "Kyber768"; public static readonly string OQS_KEM_alg_kyber_1024 = "Kyber1024"; + public static readonly string OQS_KEM_alg_bike_l1 = "BIKE-L1"; + public static readonly string OQS_KEM_alg_bike_l3 = "BIKE-L3"; + public static readonly string OQS_KEM_alg_bike_l5 = "BIKE-L5"; + public static readonly string OQS_KEM_alg_hqc_128 = "HQC-128"; + public static readonly string OQS_KEM_alg_hqc_192 = "HQC-192"; + public static readonly string OQS_KEM_alg_hqc_256 = "HQC-256"; + public static readonly string OQS_KEM_alg_ntruprime_sntrup761 = "sntrup761"; + public static readonly string OQS_KEM_alg_classic_mceliece_348864 = "Classic-McEliece-348864"; + public static readonly string OQS_KEM_alg_classic_mceliece_348864f = "Classic-McEliece-348864f"; + public static readonly string OQS_KEM_alg_classic_mceliece_460896 = "Classic-McEliece-460896"; + public static readonly string OQS_KEM_alg_classic_mceliece_460896f = "Classic-McEliece-460896f"; + public static readonly string OQS_KEM_alg_classic_mceliece_6688128 = "Classic-McEliece-6688128"; + public static readonly string OQS_KEM_alg_classic_mceliece_6688128f = "Classic-McEliece-6688128f"; + public static readonly string OQS_KEM_alg_classic_mceliece_6960119 = "Classic-McEliece-6960119"; + public static readonly string OQS_KEM_alg_classic_mceliece_6960119f = "Classic-McEliece-6960119f"; + public static readonly string OQS_KEM_alg_classic_mceliece_8192128 = "Classic-McEliece-8192128"; + public static readonly string OQS_KEM_alg_classic_mceliece_8192128f = "Classic-McEliece-8192128f"; public static readonly string OQS_KEM_alg_frodokem_640_aes = "FrodoKEM-640-AES"; public static readonly string OQS_KEM_alg_frodokem_640_shake = "FrodoKEM-640-SHAKE"; public static readonly string OQS_KEM_alg_frodokem_976_aes = "FrodoKEM-976-AES"; diff --git a/src/LibOQS.NET.Native/LibOQS.NET.Native.csproj b/src/LibOQS.NET.Native/LibOQS.NET.Native.csproj index 02f06e7..9bb7e32 100644 --- a/src/LibOQS.NET.Native/LibOQS.NET.Native.csproj +++ b/src/LibOQS.NET.Native/LibOQS.NET.Native.csproj @@ -7,7 +7,7 @@ enable true LibOQS.NET.Native - 0.1.3 + 0.2.0 filipw Native P/Invoke bindings for liboqs - a C library for quantum-resistant cryptographic algorithms https://github.com/filipw/maybe-liboqs-dotnet diff --git a/src/LibOQS.NET.Native/Sig.cs b/src/LibOQS.NET.Native/Sig.cs index 30be095..17ce279 100644 --- a/src/LibOQS.NET.Native/Sig.cs +++ b/src/LibOQS.NET.Native/Sig.cs @@ -47,14 +47,14 @@ public struct OqsSig /// Sign a message /// [DllImport(Common.LibraryName, CallingConvention = CallingConvention.Cdecl)] - public static extern Common.OqsStatus OQS_SIG_sign(IntPtr sig, IntPtr signature, ref UIntPtr signature_len, + public static extern Common.OqsStatus OQS_SIG_sign(IntPtr sig, IntPtr signature, ref UIntPtr signature_len, IntPtr message, UIntPtr message_len, IntPtr secret_key); /// /// Verify a signature /// [DllImport(Common.LibraryName, CallingConvention = CallingConvention.Cdecl)] - public static extern Common.OqsStatus OQS_SIG_verify(IntPtr sig, IntPtr message, UIntPtr message_len, + public static extern Common.OqsStatus OQS_SIG_verify(IntPtr sig, IntPtr message, UIntPtr message_len, IntPtr signature, UIntPtr signature_len, IntPtr public_key); /// @@ -84,8 +84,52 @@ public static extern Common.OqsStatus OQS_SIG_verify(IntPtr sig, IntPtr message, public static readonly string OQS_SIG_alg_dilithium5 = "Dilithium5"; public static readonly string OQS_SIG_alg_falcon_512 = "Falcon-512"; public static readonly string OQS_SIG_alg_falcon_1024 = "Falcon-1024"; - public static readonly string OQS_SIG_alg_sphincs_haraka_128f_robust = "SPHINCS+-Haraka-128f-robust"; - public static readonly string OQS_SIG_alg_sphincs_haraka_128f_simple = "SPHINCS+-Haraka-128f-simple"; - public static readonly string OQS_SIG_alg_sphincs_haraka_128s_robust = "SPHINCS+-Haraka-128s-robust"; - public static readonly string OQS_SIG_alg_sphincs_haraka_128s_simple = "SPHINCS+-Haraka-128s-simple"; + public static readonly string OQS_SIG_alg_falcon_padded_512 = "Falcon-padded-512"; + public static readonly string OQS_SIG_alg_falcon_padded_1024 = "Falcon-padded-1024"; + public static readonly string OQS_SIG_alg_sphincs_sha2_128f_simple = "SPHINCS+-SHA2-128f-simple"; + public static readonly string OQS_SIG_alg_sphincs_sha2_128s_simple = "SPHINCS+-SHA2-128s-simple"; + public static readonly string OQS_SIG_alg_sphincs_sha2_192f_simple = "SPHINCS+-SHA2-192f-simple"; + public static readonly string OQS_SIG_alg_sphincs_sha2_192s_simple = "SPHINCS+-SHA2-192s-simple"; + public static readonly string OQS_SIG_alg_sphincs_sha2_256f_simple = "SPHINCS+-SHA2-256f-simple"; + public static readonly string OQS_SIG_alg_sphincs_sha2_256s_simple = "SPHINCS+-SHA2-256s-simple"; + public static readonly string OQS_SIG_alg_sphincs_shake_128f_simple = "SPHINCS+-SHAKE-128f-simple"; + public static readonly string OQS_SIG_alg_sphincs_shake_128s_simple = "SPHINCS+-SHAKE-128s-simple"; + public static readonly string OQS_SIG_alg_sphincs_shake_192f_simple = "SPHINCS+-SHAKE-192f-simple"; + public static readonly string OQS_SIG_alg_sphincs_shake_192s_simple = "SPHINCS+-SHAKE-192s-simple"; + public static readonly string OQS_SIG_alg_sphincs_shake_256f_simple = "SPHINCS+-SHAKE-256f-simple"; + public static readonly string OQS_SIG_alg_sphincs_shake_256s_simple = "SPHINCS+-SHAKE-256s-simple"; + public static readonly string OQS_SIG_alg_mayo_1 = "MAYO-1"; + public static readonly string OQS_SIG_alg_mayo_2 = "MAYO-2"; + public static readonly string OQS_SIG_alg_mayo_3 = "MAYO-3"; + public static readonly string OQS_SIG_alg_mayo_5 = "MAYO-5"; + public static readonly string OQS_SIG_alg_cross_rsdp_128_balanced = "cross-rsdp-128-balanced"; + public static readonly string OQS_SIG_alg_cross_rsdp_128_fast = "cross-rsdp-128-fast"; + public static readonly string OQS_SIG_alg_cross_rsdp_128_small = "cross-rsdp-128-small"; + public static readonly string OQS_SIG_alg_cross_rsdp_192_balanced = "cross-rsdp-192-balanced"; + public static readonly string OQS_SIG_alg_cross_rsdp_192_fast = "cross-rsdp-192-fast"; + public static readonly string OQS_SIG_alg_cross_rsdp_192_small = "cross-rsdp-192-small"; + public static readonly string OQS_SIG_alg_cross_rsdp_256_balanced = "cross-rsdp-256-balanced"; + public static readonly string OQS_SIG_alg_cross_rsdp_256_fast = "cross-rsdp-256-fast"; + public static readonly string OQS_SIG_alg_cross_rsdp_256_small = "cross-rsdp-256-small"; + public static readonly string OQS_SIG_alg_cross_rsdpg_128_balanced = "cross-rsdpg-128-balanced"; + public static readonly string OQS_SIG_alg_cross_rsdpg_128_fast = "cross-rsdpg-128-fast"; + public static readonly string OQS_SIG_alg_cross_rsdpg_128_small = "cross-rsdpg-128-small"; + public static readonly string OQS_SIG_alg_cross_rsdpg_192_balanced = "cross-rsdpg-192-balanced"; + public static readonly string OQS_SIG_alg_cross_rsdpg_192_fast = "cross-rsdpg-192-fast"; + public static readonly string OQS_SIG_alg_cross_rsdpg_192_small = "cross-rsdpg-192-small"; + public static readonly string OQS_SIG_alg_cross_rsdpg_256_balanced = "cross-rsdpg-256-balanced"; + public static readonly string OQS_SIG_alg_cross_rsdpg_256_fast = "cross-rsdpg-256-fast"; + public static readonly string OQS_SIG_alg_cross_rsdpg_256_small = "cross-rsdpg-256-small"; + public static readonly string OQS_SIG_alg_uov_ov_Is = "OV-Is"; + public static readonly string OQS_SIG_alg_uov_ov_Ip = "OV-Ip"; + public static readonly string OQS_SIG_alg_uov_ov_III = "OV-III"; + public static readonly string OQS_SIG_alg_uov_ov_V = "OV-V"; + public static readonly string OQS_SIG_alg_uov_ov_Is_pkc = "OV-Is-pkc"; + public static readonly string OQS_SIG_alg_uov_ov_Ip_pkc = "OV-Ip-pkc"; + public static readonly string OQS_SIG_alg_uov_ov_III_pkc = "OV-III-pkc"; + public static readonly string OQS_SIG_alg_uov_ov_V_pkc = "OV-V-pkc"; + public static readonly string OQS_SIG_alg_uov_ov_Is_pkc_skc = "OV-Is-pkc-skc"; + public static readonly string OQS_SIG_alg_uov_ov_Ip_pkc_skc = "OV-Ip-pkc-skc"; + public static readonly string OQS_SIG_alg_uov_ov_III_pkc_skc = "OV-III-pkc-skc"; + public static readonly string OQS_SIG_alg_uov_ov_V_pkc_skc = "OV-V-pkc-skc"; } diff --git a/src/LibOQS.NET.Tests/KemTests.cs b/src/LibOQS.NET.Tests/KemTests.cs index 56342b7..4faa18d 100644 --- a/src/LibOQS.NET.Tests/KemTests.cs +++ b/src/LibOQS.NET.Tests/KemTests.cs @@ -6,13 +6,30 @@ namespace LibOQS.NET.Tests; public class KemTests { - [Theory] + [SkippableTheory] [InlineData(KemAlgorithm.MlKem512)] [InlineData(KemAlgorithm.MlKem768)] [InlineData(KemAlgorithm.MlKem1024)] [InlineData(KemAlgorithm.Kyber512)] [InlineData(KemAlgorithm.Kyber768)] [InlineData(KemAlgorithm.Kyber1024)] + [InlineData(KemAlgorithm.BikeL1)] + [InlineData(KemAlgorithm.BikeL3)] + [InlineData(KemAlgorithm.BikeL5)] + [InlineData(KemAlgorithm.Hqc128)] + [InlineData(KemAlgorithm.Hqc192)] + [InlineData(KemAlgorithm.Hqc256)] + [InlineData(KemAlgorithm.NtruPrimeSntrup761)] + // [InlineData(KemAlgorithm.ClassicMcEliece348864)] + // [InlineData(KemAlgorithm.ClassicMcEliece348864f)] + // [InlineData(KemAlgorithm.ClassicMcEliece460896)] + // [InlineData(KemAlgorithm.ClassicMcEliece460896f)] + // [InlineData(KemAlgorithm.ClassicMcEliece6688128)] + // [InlineData(KemAlgorithm.ClassicMcEliece6688128f)] + // [InlineData(KemAlgorithm.ClassicMcEliece6960119)] + // [InlineData(KemAlgorithm.ClassicMcEliece6960119f)] + // [InlineData(KemAlgorithm.ClassicMcEliece8192128)] + // [InlineData(KemAlgorithm.ClassicMcEliece8192128f)] [InlineData(KemAlgorithm.FrodoKem640Aes)] [InlineData(KemAlgorithm.FrodoKem640Shake)] [InlineData(KemAlgorithm.FrodoKem976Aes)] @@ -21,23 +38,24 @@ public class KemTests [InlineData(KemAlgorithm.FrodoKem1344Shake)] public void KemEncapsDecaps_ShouldSucceed(KemAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var kem = new KemInstance(algorithm); - + // Generate keypair var (publicKey, secretKey) = kem.GenerateKeypair(); - + Assert.Equal(kem.PublicKeyLength, publicKey.Length); Assert.Equal(kem.SecretKeyLength, secretKey.Length); - + // Encapsulate var (ciphertext, sharedSecret1) = kem.Encapsulate(publicKey); - + Assert.Equal(kem.CiphertextLength, ciphertext.Length); Assert.Equal(kem.SharedSecretLength, sharedSecret1.Length); - + // Decapsulate var sharedSecret2 = kem.Decapsulate(secretKey, ciphertext); - + Assert.Equal(kem.SharedSecretLength, sharedSecret2.Length); Assert.Equal(sharedSecret1, sharedSecret2); } @@ -47,7 +65,7 @@ public void KemEncapsulate_WithWrongKeySize_ShouldThrow() { using var kem = new KemInstance(KemAlgorithm.MlKem512); var wrongSizeKey = new byte[100]; // Wrong size - + Assert.Throws(() => kem.Encapsulate(wrongSizeKey)); } @@ -57,9 +75,9 @@ public void KemDecapsulate_WithWrongKeySize_ShouldThrow() using var kem = new KemInstance(KemAlgorithm.MlKem512); var (publicKey, _) = kem.GenerateKeypair(); var (ciphertext, _) = kem.Encapsulate(publicKey); - + var wrongSizeKey = new byte[100]; // Wrong size - + Assert.Throws(() => kem.Decapsulate(wrongSizeKey, ciphertext)); } @@ -68,9 +86,9 @@ public void KemDecapsulate_WithWrongCiphertextSize_ShouldThrow() { using var kem = new KemInstance(KemAlgorithm.MlKem512); var (_, secretKey) = kem.GenerateKeypair(); - + var wrongSizeCiphertext = new byte[100]; // Wrong size - + Assert.Throws(() => kem.Decapsulate(secretKey, wrongSizeCiphertext)); } @@ -78,7 +96,7 @@ public void KemDecapsulate_WithWrongCiphertextSize_ShouldThrow() public void KemDispose_ShouldAllowMultipleCalls() { var kem = new KemInstance(KemAlgorithm.MlKem512); - + kem.Dispose(); kem.Dispose(); // Should not throw } @@ -88,30 +106,31 @@ public void KemUseAfterDispose_ShouldThrow() { var kem = new KemInstance(KemAlgorithm.MlKem512); kem.Dispose(); - + Assert.Throws(() => kem.GenerateKeypair()); } - [Theory] + [SkippableTheory] [InlineData(KemAlgorithm.Kyber512)] [InlineData(KemAlgorithm.Kyber768)] [InlineData(KemAlgorithm.Kyber1024)] public void KyberKem_ShouldSucceed(KemAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var kem = new KemInstance(algorithm); - + // Generate keypair var (publicKey, secretKey) = kem.GenerateKeypair(); - + Assert.Equal(kem.PublicKeyLength, publicKey.Length); Assert.Equal(kem.SecretKeyLength, secretKey.Length); - + // Test multiple encapsulations with same keys for (int i = 0; i < 5; i++) { var (ciphertext, sharedSecret1) = kem.Encapsulate(publicKey); var sharedSecret2 = kem.Decapsulate(secretKey, ciphertext); - + Assert.Equal(kem.CiphertextLength, ciphertext.Length); Assert.Equal(kem.SharedSecretLength, sharedSecret1.Length); Assert.Equal(kem.SharedSecretLength, sharedSecret2.Length); @@ -119,7 +138,7 @@ public void KyberKem_ShouldSucceed(KemAlgorithm algorithm) } } - [Theory] + [SkippableTheory] [InlineData(KemAlgorithm.FrodoKem640Aes)] [InlineData(KemAlgorithm.FrodoKem640Shake)] [InlineData(KemAlgorithm.FrodoKem976Aes)] @@ -128,57 +147,64 @@ public void KyberKem_ShouldSucceed(KemAlgorithm algorithm) [InlineData(KemAlgorithm.FrodoKem1344Shake)] public void FrodoKem_ShouldSucceed(KemAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var kem = new KemInstance(algorithm); - + // Generate keypair var (publicKey, secretKey) = kem.GenerateKeypair(); - + Assert.Equal(kem.PublicKeyLength, publicKey.Length); Assert.Equal(kem.SecretKeyLength, secretKey.Length); - + // FrodoKEM typically has larger key sizes than other algorithms Assert.True(kem.PublicKeyLength > 1000, $"FrodoKEM public key should be large: {kem.PublicKeyLength}"); Assert.True(kem.SecretKeyLength > 1000, $"FrodoKEM secret key should be large: {kem.SecretKeyLength}"); - + // Test encapsulation/decapsulation var (ciphertext, sharedSecret1) = kem.Encapsulate(publicKey); var sharedSecret2 = kem.Decapsulate(secretKey, ciphertext); - + Assert.Equal(sharedSecret1, sharedSecret2); } - [Theory] + [SkippableTheory] [InlineData(KemAlgorithm.MlKem512)] [InlineData(KemAlgorithm.Kyber512)] + [InlineData(KemAlgorithm.BikeL1)] + [InlineData(KemAlgorithm.Hqc128)] + [InlineData(KemAlgorithm.NtruPrimeSntrup761)] + // [InlineData(KemAlgorithm.ClassicMcEliece348864)] [InlineData(KemAlgorithm.FrodoKem640Aes)] public void KemKeyLengths_ShouldBeConsistent(KemAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var kem = new KemInstance(algorithm); - + Assert.True(kem.PublicKeyLength > 0); Assert.True(kem.SecretKeyLength > 0); Assert.True(kem.CiphertextLength > 0); Assert.True(kem.SharedSecretLength > 0); - + // Generated keys should match reported lengths var (publicKey, secretKey) = kem.GenerateKeypair(); Assert.Equal(kem.PublicKeyLength, publicKey.Length); Assert.Equal(kem.SecretKeyLength, secretKey.Length); - + // Encapsulation should produce correct lengths var (ciphertext, sharedSecret) = kem.Encapsulate(publicKey); Assert.Equal(kem.CiphertextLength, ciphertext.Length); Assert.Equal(kem.SharedSecretLength, sharedSecret.Length); } - [Theory] + [SkippableTheory] [InlineData(KemAlgorithm.MlKem512)] [InlineData(KemAlgorithm.MlKem768)] [InlineData(KemAlgorithm.MlKem1024)] public void MlKemAlgorithms_ShouldHaveProgressiveSizes(KemAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var kem = new KemInstance(algorithm); - + // ML-KEM algorithms should have progressively larger key sizes switch (algorithm) { @@ -195,7 +221,7 @@ public void MlKemAlgorithms_ShouldHaveProgressiveSizes(KemAlgorithm algorithm) Assert.True(kem.SecretKeyLength > 3000); break; } - + Assert.Equal(32, kem.SharedSecretLength); } @@ -204,16 +230,16 @@ public void KemMultipleInstances_ShouldWorkIndependently() { using var kem1 = new KemInstance(KemAlgorithm.MlKem512); using var kem2 = new KemInstance(KemAlgorithm.Kyber512); - + var (pk1, sk1) = kem1.GenerateKeypair(); var (pk2, sk2) = kem2.GenerateKeypair(); - + var (ct1, ss1_enc) = kem1.Encapsulate(pk1); var (ct2, ss2_enc) = kem2.Encapsulate(pk2); - + var ss1_dec = kem1.Decapsulate(sk1, ct1); var ss2_dec = kem2.Decapsulate(sk2, ct2); - + // Each should work with its own keys Assert.Equal(ss1_enc, ss1_dec); Assert.Equal(ss2_enc, ss2_dec); @@ -225,7 +251,7 @@ public void KemNull_ShouldThrow() using var kem = new KemInstance(KemAlgorithm.MlKem512); var (publicKey, secretKey) = kem.GenerateKeypair(); var (ciphertext, _) = kem.Encapsulate(publicKey); - + Assert.Throws(() => kem.Encapsulate(null!)); Assert.Throws(() => kem.Decapsulate(null!, ciphertext)); Assert.Throws(() => kem.Decapsulate(secretKey, null!)); @@ -236,20 +262,20 @@ public void KemRandomness_EncapsulationsShouldBeDifferent() { using var kem = new KemInstance(KemAlgorithm.MlKem512); var (publicKey, secretKey) = kem.GenerateKeypair(); - + // Multiple encapsulations should produce different ciphertexts but recoverable shared secrets var results = new List<(byte[] ciphertext, byte[] sharedSecret)>(); - + for (int i = 0; i < 5; i++) { var (ct, ss) = kem.Encapsulate(publicKey); results.Add((ct, ss)); - + // Verify decapsulation works var recoveredSS = kem.Decapsulate(secretKey, ct); Assert.Equal(ss, recoveredSS); } - + // All ciphertexts should be different for (int i = 0; i < results.Count; i++) { @@ -284,7 +310,7 @@ public async Task KemThreadSafety_MultipleOperations() var (pk, sk) = kem.GenerateKeypair(); var (ct, ss1) = kem.Encapsulate(pk); var ss2 = kem.Decapsulate(sk, ct); - + if (!ss1.SequenceEqual(ss2)) { results[threadIndex] = false; @@ -301,37 +327,38 @@ public async Task KemThreadSafety_MultipleOperations() } await Task.WhenAll(tasks); - + foreach (var result in results) { Assert.True(result); } } - [Theory] + [SkippableTheory] [InlineData(KemAlgorithm.FrodoKem640Aes, KemAlgorithm.FrodoKem640Shake)] [InlineData(KemAlgorithm.FrodoKem976Aes, KemAlgorithm.FrodoKem976Shake)] [InlineData(KemAlgorithm.FrodoKem1344Aes, KemAlgorithm.FrodoKem1344Shake)] public void FrodoKemVariants_ShouldHaveSameSizes(KemAlgorithm aesVariant, KemAlgorithm shakeVariant) { + if (!aesVariant.IsEnabled() || !shakeVariant.IsEnabled()) return; using var kemAes = new KemInstance(aesVariant); using var kemShake = new KemInstance(shakeVariant); - + // AES and SHAKE variants of the same FrodoKEM should have same key sizes Assert.Equal(kemAes.PublicKeyLength, kemShake.PublicKeyLength); Assert.Equal(kemAes.SecretKeyLength, kemShake.SecretKeyLength); Assert.Equal(kemAes.CiphertextLength, kemShake.CiphertextLength); Assert.Equal(kemAes.SharedSecretLength, kemShake.SharedSecretLength); - + var (pkAes, skAes) = kemAes.GenerateKeypair(); var (pkShake, skShake) = kemShake.GenerateKeypair(); - + var (ctAes, ssAes1) = kemAes.Encapsulate(pkAes); var (ctShake, ssShake1) = kemShake.Encapsulate(pkShake); - + var ssAes2 = kemAes.Decapsulate(skAes, ctAes); var ssShake2 = kemShake.Decapsulate(skShake, ctShake); - + Assert.Equal(ssAes1, ssAes2); Assert.Equal(ssShake1, ssShake2); } diff --git a/src/LibOQS.NET.Tests/LibOQS.NET.Tests.csproj b/src/LibOQS.NET.Tests/LibOQS.NET.Tests.csproj index 6e96cde..0dfb097 100644 --- a/src/LibOQS.NET.Tests/LibOQS.NET.Tests.csproj +++ b/src/LibOQS.NET.Tests/LibOQS.NET.Tests.csproj @@ -9,12 +9,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/LibOQS.NET.Tests/SigTests.cs b/src/LibOQS.NET.Tests/SigTests.cs index 3a7418d..b501de4 100644 --- a/src/LibOQS.NET.Tests/SigTests.cs +++ b/src/LibOQS.NET.Tests/SigTests.cs @@ -6,7 +6,7 @@ namespace LibOQS.NET.Tests; public class SigTests { - [Theory] + [SkippableTheory] [InlineData(SigAlgorithm.MlDsa44)] [InlineData(SigAlgorithm.MlDsa65)] [InlineData(SigAlgorithm.MlDsa87)] @@ -15,8 +15,57 @@ public class SigTests [InlineData(SigAlgorithm.Dilithium5)] [InlineData(SigAlgorithm.Falcon512)] [InlineData(SigAlgorithm.Falcon1024)] + [InlineData(SigAlgorithm.FalconPadded512)] + [InlineData(SigAlgorithm.FalconPadded1024)] + [InlineData(SigAlgorithm.SphincsPlusSha2128fSimple)] + [InlineData(SigAlgorithm.SphincsPlusSha2128sSimple)] + [InlineData(SigAlgorithm.SphincsPlusSha2192fSimple)] + [InlineData(SigAlgorithm.SphincsPlusSha2192sSimple)] + [InlineData(SigAlgorithm.SphincsPlusSha2256fSimple)] + [InlineData(SigAlgorithm.SphincsPlusSha2256sSimple)] + [InlineData(SigAlgorithm.SphincsPlusShake128fSimple)] + [InlineData(SigAlgorithm.SphincsPlusShake128sSimple)] + [InlineData(SigAlgorithm.SphincsPlusShake192fSimple)] + [InlineData(SigAlgorithm.SphincsPlusShake192sSimple)] + [InlineData(SigAlgorithm.SphincsPlusShake256fSimple)] + [InlineData(SigAlgorithm.SphincsPlusShake256sSimple)] + [InlineData(SigAlgorithm.Mayo1)] + [InlineData(SigAlgorithm.Mayo2)] + [InlineData(SigAlgorithm.Mayo3)] + [InlineData(SigAlgorithm.Mayo5)] + [InlineData(SigAlgorithm.CrossRsdp128Balanced)] + [InlineData(SigAlgorithm.CrossRsdp128Fast)] + [InlineData(SigAlgorithm.CrossRsdp128Small)] + [InlineData(SigAlgorithm.CrossRsdp192Balanced)] + [InlineData(SigAlgorithm.CrossRsdp192Fast)] + [InlineData(SigAlgorithm.CrossRsdp192Small)] + [InlineData(SigAlgorithm.CrossRsdp256Balanced)] + [InlineData(SigAlgorithm.CrossRsdp256Fast)] + [InlineData(SigAlgorithm.CrossRsdp256Small)] + [InlineData(SigAlgorithm.CrossRsdpg128Balanced)] + [InlineData(SigAlgorithm.CrossRsdpg128Fast)] + [InlineData(SigAlgorithm.CrossRsdpg128Small)] + [InlineData(SigAlgorithm.CrossRsdpg192Balanced)] + [InlineData(SigAlgorithm.CrossRsdpg192Fast)] + [InlineData(SigAlgorithm.CrossRsdpg192Small)] + [InlineData(SigAlgorithm.CrossRsdpg256Balanced)] + [InlineData(SigAlgorithm.CrossRsdpg256Fast)] + [InlineData(SigAlgorithm.CrossRsdpg256Small)] + [InlineData(SigAlgorithm.UovOvIs)] + [InlineData(SigAlgorithm.UovOvIp)] + [InlineData(SigAlgorithm.UovOvIii)] + [InlineData(SigAlgorithm.UovOvV)] + [InlineData(SigAlgorithm.UovOvIsPkc)] + [InlineData(SigAlgorithm.UovOvIpPkc)] + [InlineData(SigAlgorithm.UovOvIiiPkc)] + [InlineData(SigAlgorithm.UovOvVPkc)] + [InlineData(SigAlgorithm.UovOvIsPkcSkc)] + [InlineData(SigAlgorithm.UovOvIpPkcSkc)] + [InlineData(SigAlgorithm.UovOvIiiPkcSkc)] + [InlineData(SigAlgorithm.UovOvVPkcSkc)] public void SigSignVerify_ShouldSucceed(SigAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var sig = new SigInstance(algorithm); // Generate keypair @@ -94,12 +143,13 @@ public void SigEmptyMessage_ShouldWork() Assert.True(isValid); } - [Theory] + [SkippableTheory] [InlineData(SigAlgorithm.Dilithium2)] [InlineData(SigAlgorithm.Dilithium3)] [InlineData(SigAlgorithm.Dilithium5)] public void DilithiumSignVerify_ShouldSucceed(SigAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var sig = new SigInstance(algorithm); // Generate keypair @@ -128,11 +178,12 @@ public void DilithiumSignVerify_ShouldSucceed(SigAlgorithm algorithm) } } - [Theory] + [SkippableTheory] [InlineData(SigAlgorithm.Falcon512)] [InlineData(SigAlgorithm.Falcon1024)] public void FalconSignVerify_ShouldSucceed(SigAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var sig = new SigInstance(algorithm); // Generate keypair @@ -170,12 +221,18 @@ public void SigAlgorithmIsEnabled_ShouldReturnConsistentResults() } } - [Theory] + [SkippableTheory] [InlineData(SigAlgorithm.MlDsa44)] [InlineData(SigAlgorithm.Dilithium2)] [InlineData(SigAlgorithm.Falcon512)] + [InlineData(SigAlgorithm.FalconPadded512)] + [InlineData(SigAlgorithm.SphincsPlusSha2128fSimple)] + [InlineData(SigAlgorithm.Mayo1)] + [InlineData(SigAlgorithm.CrossRsdp128Balanced)] + [InlineData(SigAlgorithm.UovOvIs)] public void SigKeyLengths_ShouldBeConsistent(SigAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var sig = new SigInstance(algorithm); // Key lengths should be positive @@ -220,11 +277,12 @@ public void SigDifferentAlgorithms_ShouldNotCrossVerify() } } - [Theory] + [SkippableTheory] [InlineData(SigAlgorithm.MlDsa44)] [InlineData(SigAlgorithm.Dilithium2)] public void SigLargeMessage_ShouldWork(SigAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var sig = new SigInstance(algorithm); var (publicKey, secretKey) = sig.GenerateKeypair(); @@ -299,12 +357,13 @@ public void SigSign_WithTamperedSecretKey_ShouldFail() Assert.False(isValid); } - [Theory] + [SkippableTheory] [InlineData(SigAlgorithm.MlDsa44)] [InlineData(SigAlgorithm.MlDsa65)] [InlineData(SigAlgorithm.MlDsa87)] public void MlDsaAlgorithms_ShouldHaveCorrectSecurityLevels(SigAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var sig = new SigInstance(algorithm); // ML-DSA algorithms should have progressively larger keys and signatures @@ -328,11 +387,14 @@ public void MlDsaAlgorithms_ShouldHaveCorrectSecurityLevels(SigAlgorithm algorit } } - [Theory] + [SkippableTheory] [InlineData(SigAlgorithm.Falcon512)] [InlineData(SigAlgorithm.Falcon1024)] + [InlineData(SigAlgorithm.FalconPadded512)] + [InlineData(SigAlgorithm.FalconPadded1024)] public void FalconAlgorithms_ShouldHaveCompactSignatures(SigAlgorithm algorithm) { + Skip.If(!algorithm.IsEnabled(), $"Algorithm {algorithm} is not enabled in this build."); using var sig = new SigInstance(algorithm); var (publicKey, secretKey) = sig.GenerateKeypair(); var message = "Falcon signature test"u8.ToArray(); diff --git a/src/LibOQS.NET/Kem.cs b/src/LibOQS.NET/Kem.cs index 029d0c8..b6fb3e9 100644 --- a/src/LibOQS.NET/Kem.cs +++ b/src/LibOQS.NET/Kem.cs @@ -20,6 +20,40 @@ public enum KemAlgorithm Kyber768, /// Kyber1024 Kyber1024, + /// BIKE-L1 + BikeL1, + /// BIKE-L3 + BikeL3, + /// BIKE-L5 + BikeL5, + /// HQC-128 + Hqc128, + /// HQC-192 + Hqc192, + /// HQC-256 + Hqc256, + /// sntrup761 (NTRU Prime) + NtruPrimeSntrup761, + /// Classic-McEliece-348864 + ClassicMcEliece348864, + /// Classic-McEliece-348864f + ClassicMcEliece348864f, + /// Classic-McEliece-460896 + ClassicMcEliece460896, + /// Classic-McEliece-460896f + ClassicMcEliece460896f, + /// Classic-McEliece-6688128 + ClassicMcEliece6688128, + /// Classic-McEliece-6688128f + ClassicMcEliece6688128f, + /// Classic-McEliece-6960119 + ClassicMcEliece6960119, + /// Classic-McEliece-6960119f + ClassicMcEliece6960119f, + /// Classic-McEliece-8192128 + ClassicMcEliece8192128, + /// Classic-McEliece-8192128f + ClassicMcEliece8192128f, /// FrodoKEM-640-AES FrodoKem640Aes, /// FrodoKEM-640-SHAKE @@ -50,6 +84,23 @@ public static class KemAlgorithmExtensions KemAlgorithm.Kyber512 => Kem.OQS_KEM_alg_kyber_512, KemAlgorithm.Kyber768 => Kem.OQS_KEM_alg_kyber_768, KemAlgorithm.Kyber1024 => Kem.OQS_KEM_alg_kyber_1024, + KemAlgorithm.BikeL1 => Kem.OQS_KEM_alg_bike_l1, + KemAlgorithm.BikeL3 => Kem.OQS_KEM_alg_bike_l3, + KemAlgorithm.BikeL5 => Kem.OQS_KEM_alg_bike_l5, + KemAlgorithm.Hqc128 => Kem.OQS_KEM_alg_hqc_128, + KemAlgorithm.Hqc192 => Kem.OQS_KEM_alg_hqc_192, + KemAlgorithm.Hqc256 => Kem.OQS_KEM_alg_hqc_256, + KemAlgorithm.NtruPrimeSntrup761 => Kem.OQS_KEM_alg_ntruprime_sntrup761, + KemAlgorithm.ClassicMcEliece348864 => Kem.OQS_KEM_alg_classic_mceliece_348864, + KemAlgorithm.ClassicMcEliece348864f => Kem.OQS_KEM_alg_classic_mceliece_348864f, + KemAlgorithm.ClassicMcEliece460896 => Kem.OQS_KEM_alg_classic_mceliece_460896, + KemAlgorithm.ClassicMcEliece460896f => Kem.OQS_KEM_alg_classic_mceliece_460896f, + KemAlgorithm.ClassicMcEliece6688128 => Kem.OQS_KEM_alg_classic_mceliece_6688128, + KemAlgorithm.ClassicMcEliece6688128f => Kem.OQS_KEM_alg_classic_mceliece_6688128f, + KemAlgorithm.ClassicMcEliece6960119 => Kem.OQS_KEM_alg_classic_mceliece_6960119, + KemAlgorithm.ClassicMcEliece6960119f => Kem.OQS_KEM_alg_classic_mceliece_6960119f, + KemAlgorithm.ClassicMcEliece8192128 => Kem.OQS_KEM_alg_classic_mceliece_8192128, + KemAlgorithm.ClassicMcEliece8192128f => Kem.OQS_KEM_alg_classic_mceliece_8192128f, KemAlgorithm.FrodoKem640Aes => Kem.OQS_KEM_alg_frodokem_640_aes, KemAlgorithm.FrodoKem640Shake => Kem.OQS_KEM_alg_frodokem_640_shake, KemAlgorithm.FrodoKem976Aes => Kem.OQS_KEM_alg_frodokem_976_aes, @@ -110,7 +161,7 @@ public KemInstance(KemAlgorithm algorithm) { LibOqs.EnsureInitialized(); Algorithm = algorithm; - + if (!algorithm.IsEnabled()) { throw new AlgorithmNotSupportedException(algorithm.GetIdentifier()); @@ -167,7 +218,7 @@ private void ThrowIfDisposed() public (byte[] Ciphertext, byte[] SharedSecret) Encapsulate(byte[] publicKey) { ThrowIfDisposed(); - + if (publicKey.Length != PublicKeyLength) { throw new ArgumentException($"Public key must be {PublicKeyLength} bytes"); @@ -197,12 +248,12 @@ private void ThrowIfDisposed() public byte[] Decapsulate(byte[] secretKey, byte[] ciphertext) { ThrowIfDisposed(); - + if (secretKey.Length != SecretKeyLength) { throw new ArgumentException($"Secret key must be {SecretKeyLength} bytes"); } - + if (ciphertext.Length != CiphertextLength) { throw new ArgumentException($"Ciphertext must be {CiphertextLength} bytes"); diff --git a/src/LibOQS.NET/LibOQS.NET.csproj b/src/LibOQS.NET/LibOQS.NET.csproj index da5fa51..71cb1a4 100644 --- a/src/LibOQS.NET/LibOQS.NET.csproj +++ b/src/LibOQS.NET/LibOQS.NET.csproj @@ -7,7 +7,7 @@ enable true LibOQS.NET - 0.1.3 + 0.2.0 filipw A .NET wrapper for liboqs - a C library for quantum-resistant cryptographic algorithms https://github.com/filipw/maybe-liboqs-dotnet diff --git a/src/LibOQS.NET/Sig.cs b/src/LibOQS.NET/Sig.cs index df27d4e..0be80dc 100644 --- a/src/LibOQS.NET/Sig.cs +++ b/src/LibOQS.NET/Sig.cs @@ -24,14 +24,102 @@ public enum SigAlgorithm Falcon512, /// Falcon-1024 Falcon1024, - /// SPHINCS+-Haraka-128f-robust - SphincsPlusHaraka128fRobust, - /// SPHINCS+-Haraka-128f-simple - SphincsPlusHaraka128fSimple, - /// SPHINCS+-Haraka-128s-robust - SphincsPlusHaraka128sRobust, - /// SPHINCS+-Haraka-128s-simple - SphincsPlusHaraka128sSimple, + /// Falcon-padded-512 + FalconPadded512, + /// Falcon-padded-1024 + FalconPadded1024, + /// SPHINCS+-SHA2-128f-simple + SphincsPlusSha2128fSimple, + /// SPHINCS+-SHA2-128s-simple + SphincsPlusSha2128sSimple, + /// SPHINCS+-SHA2-192f-simple + SphincsPlusSha2192fSimple, + /// SPHINCS+-SHA2-192s-simple + SphincsPlusSha2192sSimple, + /// SPHINCS+-SHA2-256f-simple + SphincsPlusSha2256fSimple, + /// SPHINCS+-SHA2-256s-simple + SphincsPlusSha2256sSimple, + /// SPHINCS+-SHAKE-128f-simple + SphincsPlusShake128fSimple, + /// SPHINCS+-SHAKE-128s-simple + SphincsPlusShake128sSimple, + /// SPHINCS+-SHAKE-192f-simple + SphincsPlusShake192fSimple, + /// SPHINCS+-SHAKE-192s-simple + SphincsPlusShake192sSimple, + /// SPHINCS+-SHAKE-256f-simple + SphincsPlusShake256fSimple, + /// SPHINCS+-SHAKE-256s-simple + SphincsPlusShake256sSimple, + /// MAYO-1 + Mayo1, + /// MAYO-2 + Mayo2, + /// MAYO-3 + Mayo3, + /// MAYO-5 + Mayo5, + /// cross-rsdp-128-balanced + CrossRsdp128Balanced, + /// cross-rsdp-128-fast + CrossRsdp128Fast, + /// cross-rsdp-128-small + CrossRsdp128Small, + /// cross-rsdp-192-balanced + CrossRsdp192Balanced, + /// cross-rsdp-192-fast + CrossRsdp192Fast, + /// cross-rsdp-192-small + CrossRsdp192Small, + /// cross-rsdp-256-balanced + CrossRsdp256Balanced, + /// cross-rsdp-256-fast + CrossRsdp256Fast, + /// cross-rsdp-256-small + CrossRsdp256Small, + /// cross-rsdpg-128-balanced + CrossRsdpg128Balanced, + /// cross-rsdpg-128-fast + CrossRsdpg128Fast, + /// cross-rsdpg-128-small + CrossRsdpg128Small, + /// cross-rsdpg-192-balanced + CrossRsdpg192Balanced, + /// cross-rsdpg-192-fast + CrossRsdpg192Fast, + /// cross-rsdpg-192-small + CrossRsdpg192Small, + /// cross-rsdpg-256-balanced + CrossRsdpg256Balanced, + /// cross-rsdpg-256-fast + CrossRsdpg256Fast, + /// cross-rsdpg-256-small + CrossRsdpg256Small, + /// OV-Is + UovOvIs, + /// OV-Ip + UovOvIp, + /// OV-III + UovOvIii, + /// OV-V + UovOvV, + /// OV-Is-pkc + UovOvIsPkc, + /// OV-Ip-pkc + UovOvIpPkc, + /// OV-III-pkc + UovOvIiiPkc, + /// OV-V-pkc + UovOvVPkc, + /// OV-Is-pkc-skc + UovOvIsPkcSkc, + /// OV-Ip-pkc-skc + UovOvIpPkcSkc, + /// OV-III-pkc-skc + UovOvIiiPkcSkc, + /// OV-V-pkc-skc + UovOvVPkcSkc, } /// @@ -52,10 +140,54 @@ public static class SigAlgorithmExtensions SigAlgorithm.Dilithium5 => Sig.OQS_SIG_alg_dilithium5, SigAlgorithm.Falcon512 => Sig.OQS_SIG_alg_falcon_512, SigAlgorithm.Falcon1024 => Sig.OQS_SIG_alg_falcon_1024, - SigAlgorithm.SphincsPlusHaraka128fRobust => Sig.OQS_SIG_alg_sphincs_haraka_128f_robust, - SigAlgorithm.SphincsPlusHaraka128fSimple => Sig.OQS_SIG_alg_sphincs_haraka_128f_simple, - SigAlgorithm.SphincsPlusHaraka128sRobust => Sig.OQS_SIG_alg_sphincs_haraka_128s_robust, - SigAlgorithm.SphincsPlusHaraka128sSimple => Sig.OQS_SIG_alg_sphincs_haraka_128s_simple, + SigAlgorithm.FalconPadded512 => Sig.OQS_SIG_alg_falcon_padded_512, + SigAlgorithm.FalconPadded1024 => Sig.OQS_SIG_alg_falcon_padded_1024, + SigAlgorithm.SphincsPlusSha2128fSimple => Sig.OQS_SIG_alg_sphincs_sha2_128f_simple, + SigAlgorithm.SphincsPlusSha2128sSimple => Sig.OQS_SIG_alg_sphincs_sha2_128s_simple, + SigAlgorithm.SphincsPlusSha2192fSimple => Sig.OQS_SIG_alg_sphincs_sha2_192f_simple, + SigAlgorithm.SphincsPlusSha2192sSimple => Sig.OQS_SIG_alg_sphincs_sha2_192s_simple, + SigAlgorithm.SphincsPlusSha2256fSimple => Sig.OQS_SIG_alg_sphincs_sha2_256f_simple, + SigAlgorithm.SphincsPlusSha2256sSimple => Sig.OQS_SIG_alg_sphincs_sha2_256s_simple, + SigAlgorithm.SphincsPlusShake128fSimple => Sig.OQS_SIG_alg_sphincs_shake_128f_simple, + SigAlgorithm.SphincsPlusShake128sSimple => Sig.OQS_SIG_alg_sphincs_shake_128s_simple, + SigAlgorithm.SphincsPlusShake192fSimple => Sig.OQS_SIG_alg_sphincs_shake_192f_simple, + SigAlgorithm.SphincsPlusShake192sSimple => Sig.OQS_SIG_alg_sphincs_shake_192s_simple, + SigAlgorithm.SphincsPlusShake256fSimple => Sig.OQS_SIG_alg_sphincs_shake_256f_simple, + SigAlgorithm.SphincsPlusShake256sSimple => Sig.OQS_SIG_alg_sphincs_shake_256s_simple, + SigAlgorithm.Mayo1 => Sig.OQS_SIG_alg_mayo_1, + SigAlgorithm.Mayo2 => Sig.OQS_SIG_alg_mayo_2, + SigAlgorithm.Mayo3 => Sig.OQS_SIG_alg_mayo_3, + SigAlgorithm.Mayo5 => Sig.OQS_SIG_alg_mayo_5, + SigAlgorithm.CrossRsdp128Balanced => Sig.OQS_SIG_alg_cross_rsdp_128_balanced, + SigAlgorithm.CrossRsdp128Fast => Sig.OQS_SIG_alg_cross_rsdp_128_fast, + SigAlgorithm.CrossRsdp128Small => Sig.OQS_SIG_alg_cross_rsdp_128_small, + SigAlgorithm.CrossRsdp192Balanced => Sig.OQS_SIG_alg_cross_rsdp_192_balanced, + SigAlgorithm.CrossRsdp192Fast => Sig.OQS_SIG_alg_cross_rsdp_192_fast, + SigAlgorithm.CrossRsdp192Small => Sig.OQS_SIG_alg_cross_rsdp_192_small, + SigAlgorithm.CrossRsdp256Balanced => Sig.OQS_SIG_alg_cross_rsdp_256_balanced, + SigAlgorithm.CrossRsdp256Fast => Sig.OQS_SIG_alg_cross_rsdp_256_fast, + SigAlgorithm.CrossRsdp256Small => Sig.OQS_SIG_alg_cross_rsdp_256_small, + SigAlgorithm.CrossRsdpg128Balanced => Sig.OQS_SIG_alg_cross_rsdpg_128_balanced, + SigAlgorithm.CrossRsdpg128Fast => Sig.OQS_SIG_alg_cross_rsdpg_128_fast, + SigAlgorithm.CrossRsdpg128Small => Sig.OQS_SIG_alg_cross_rsdpg_128_small, + SigAlgorithm.CrossRsdpg192Balanced => Sig.OQS_SIG_alg_cross_rsdpg_192_balanced, + SigAlgorithm.CrossRsdpg192Fast => Sig.OQS_SIG_alg_cross_rsdpg_192_fast, + SigAlgorithm.CrossRsdpg192Small => Sig.OQS_SIG_alg_cross_rsdpg_192_small, + SigAlgorithm.CrossRsdpg256Balanced => Sig.OQS_SIG_alg_cross_rsdpg_256_balanced, + SigAlgorithm.CrossRsdpg256Fast => Sig.OQS_SIG_alg_cross_rsdpg_256_fast, + SigAlgorithm.CrossRsdpg256Small => Sig.OQS_SIG_alg_cross_rsdpg_256_small, + SigAlgorithm.UovOvIs => Sig.OQS_SIG_alg_uov_ov_Is, + SigAlgorithm.UovOvIp => Sig.OQS_SIG_alg_uov_ov_Ip, + SigAlgorithm.UovOvIii => Sig.OQS_SIG_alg_uov_ov_III, + SigAlgorithm.UovOvV => Sig.OQS_SIG_alg_uov_ov_V, + SigAlgorithm.UovOvIsPkc => Sig.OQS_SIG_alg_uov_ov_Is_pkc, + SigAlgorithm.UovOvIpPkc => Sig.OQS_SIG_alg_uov_ov_Ip_pkc, + SigAlgorithm.UovOvIiiPkc => Sig.OQS_SIG_alg_uov_ov_III_pkc, + SigAlgorithm.UovOvVPkc => Sig.OQS_SIG_alg_uov_ov_V_pkc, + SigAlgorithm.UovOvIsPkcSkc => Sig.OQS_SIG_alg_uov_ov_Is_pkc_skc, + SigAlgorithm.UovOvIpPkcSkc => Sig.OQS_SIG_alg_uov_ov_Ip_pkc_skc, + SigAlgorithm.UovOvIiiPkcSkc => Sig.OQS_SIG_alg_uov_ov_III_pkc_skc, + SigAlgorithm.UovOvVPkcSkc => Sig.OQS_SIG_alg_uov_ov_V_pkc_skc, _ => throw new ArgumentException($"Unknown algorithm: {algorithm}") }; @@ -105,7 +237,7 @@ public SigInstance(SigAlgorithm algorithm) { LibOqs.EnsureInitialized(); Algorithm = algorithm; - + if (!algorithm.IsEnabled()) { throw new AlgorithmNotSupportedException(algorithm.GetIdentifier()); @@ -162,7 +294,7 @@ private void ThrowIfDisposed() public byte[] Sign(byte[] message, byte[] secretKey) { ThrowIfDisposed(); - + if (secretKey.Length != SecretKeyLength) { throw new ArgumentException($"Secret key must be {SecretKeyLength} bytes"); @@ -196,7 +328,7 @@ public byte[] Sign(byte[] message, byte[] secretKey) public bool Verify(byte[] message, byte[] signature, byte[] publicKey) { ThrowIfDisposed(); - + if (publicKey.Length != PublicKeyLength) { throw new ArgumentException($"Public key must be {PublicKeyLength} bytes");