// Copyright 2016-2025 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Adapted from server/ciphersuites.go in the NATS server Go source. using System.Net.Security; using System.Security.Authentication; namespace ZB.MOM.NatsNet.Server.Auth; /// /// TLS cipher suite and curve preference definitions. /// Mirrors Go ciphersuites.go — cipherMap, defaultCipherSuites, curvePreferenceMap, /// defaultCurvePreferences. /// public static class CipherSuites { /// /// Map of cipher suite names to their values. /// Populated at static init time — mirrors Go init() + cipherMap. /// public static IReadOnlyDictionary CipherMap { get; } /// /// Reverse map of cipher suite ID to name. /// Mirrors Go cipherMapByID. /// public static IReadOnlyDictionary CipherMapById { get; } static CipherSuites() { // .NET does not have a direct equivalent of Go's tls.CipherSuites() / // tls.InsecureCipherSuites() enumeration. We enumerate the well-known // TLS 1.2 and 1.3 cipher suites defined in the TlsCipherSuite enum. var byName = new Dictionary(StringComparer.OrdinalIgnoreCase); var byId = new Dictionary(); foreach (TlsCipherSuite cs in Enum.GetValues(typeof(TlsCipherSuite))) { var name = cs.ToString(); byName.TryAdd(name, cs); byId.TryAdd(cs, name); } CipherMap = byName; CipherMapById = byId; } /// /// Compatibility init hook for PortTracker parity with Go init(). /// Safe and idempotent. /// public static void Init() { _ = CipherMap; _ = CipherMapById; } /// /// Returns the default set of TLS 1.2 cipher suites. /// .NET manages cipher suite selection at the OS/SChannel/OpenSSL level; /// this list provides the preferred suites for configuration alignment with Go. /// Mirrors Go defaultCipherSuites. /// public static TlsCipherSuite[] DefaultCipherSuites() { // Return commonly-used TLS 1.2 cipher suites in preference order. // TLS 1.3 suites are always enabled in .NET and cannot be individually toggled. return [ TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TlsCipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, ]; } /// /// Supported named curve / key exchange preferences. /// Mirrors Go curvePreferenceMap. /// public static IReadOnlyDictionary CurvePreferenceMap { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase) { // .NET does not expose individual curve selection in the same way as Go. // These entries exist for configuration-file compatibility and mapping. // Actual curve negotiation is handled by the OS TLS stack. ["X25519"] = new SslApplicationProtocol("X25519"), ["CurveP256"] = new SslApplicationProtocol("CurveP256"), ["CurveP384"] = new SslApplicationProtocol("CurveP384"), ["CurveP521"] = new SslApplicationProtocol("CurveP521"), }; /// /// Returns the default curve preferences, ordered highest security first. /// Mirrors Go defaultCurvePreferences. /// public static string[] DefaultCurvePreferences() { return [ "X25519", "CurveP256", "CurveP384", "CurveP521", ]; } }