// 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",
];
}
}