Skip to content

Implement X25519DiffieHellman#127248

Open
vcsjones wants to merge 6 commits intodotnet:mainfrom
vcsjones:x25519-impl
Open

Implement X25519DiffieHellman#127248
vcsjones wants to merge 6 commits intodotnet:mainfrom
vcsjones:x25519-impl

Conversation

@vcsjones
Copy link
Copy Markdown
Member

This implements X25519 Diffie-Hellman on Windows 10+, Apple macOS, iOS / tvOS by way of CryptoKit, and OpenSSL.

What will be follow up pull requests

  1. Platform-specific implementations (X25519DiffieHellmanOpenSsl/Cng)
  2. Android implementation

Contributes to #126206

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @bartonjs, @vcsjones, @dotnet/area-system-security
See info in area-owners.md if you want to be subscribed.

@vcsjones vcsjones added this to the 11.0.0 milestone Apr 21, 2026
@vcsjones vcsjones requested a review from bartonjs April 21, 2026 21:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements the proposed X25519DiffieHellman API across Windows (CNG), Apple platforms (CryptoKit via Swift bindings), and OpenSSL, with extensive conformance/contract tests and supporting native interop glue.

Changes:

  • Adds new public System.Security.Cryptography.X25519DiffieHellman API (ref + implementation) with import/export (raw, SPKI, PKCS#8, PEM) and raw secret derivation.
  • Introduces platform-specific implementations (Windows/CNG, Apple/CryptoKit, OpenSSL) plus new native entrypoints/bindings for OpenSSL and Apple.
  • Adds a comprehensive test suite (vectors, key round-tripping, PEM/PKCS#8 behavior, supported vs not-supported gating) and factors shared PKCS#8 test validation into a helper.
Show a summary per file
File Description
src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey_x25519.h Declares OpenSSL PAL entrypoints for X25519 import/export/generate.
src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey_x25519.c Implements OpenSSL PAL wrappers for raw key import/export and keygen.
src/native/libs/System.Security.Cryptography.Native/opensslshim.h Adds OpenSSL shim bindings for raw X25519 key APIs.
src/native/libs/System.Security.Cryptography.Native/entrypoints.c Registers new OpenSSL-side native exports for X25519.
src/native/libs/System.Security.Cryptography.Native/CMakeLists.txt Includes the new OpenSSL X25519 PAL source in the native build.
src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.swift Adds CryptoKit-backed Swift entrypoints for X25519 operations.
src/native/libs/System.Security.Cryptography.Native.Apple/pal_swiftbindings.h Declares Swift binding entrypoints for X25519 for P/Invoke table.
src/native/libs/System.Security.Cryptography.Native.Apple/entrypoints.c Registers AppleCryptoNative X25519 entrypoints.
src/libraries/System.Security.Cryptography/tests/X25519DiffieHellmanTests.cs Adds API-level tests for import/export, ASN.1 validation, PEM behavior.
src/libraries/System.Security.Cryptography/tests/X25519DiffieHellmanTestData.cs Adds RFC 7748 vectors and encoded test blobs (SPKI/PKCS#8/etc.).
src/libraries/System.Security.Cryptography/tests/X25519DiffieHellmanNotSupportedTests.cs Adds tests asserting PNSE behavior when X25519 isn’t supported.
src/libraries/System.Security.Cryptography/tests/X25519DiffieHellmanKeyTests.cs Adds key roundtrip tests, scalar clamping preservation checks, vectors.
src/libraries/System.Security.Cryptography/tests/X25519DiffieHellmanImplementationTests.cs Hooks base test suite to the public X25519DiffieHellman implementation.
src/libraries/System.Security.Cryptography/tests/X25519DiffieHellmanContractTests.cs Adds contract tests for base-class behavior (dispose, buffer sizing, etc.).
src/libraries/System.Security.Cryptography/tests/X25519DiffieHellmanBaseTests.cs Adds shared behavioral tests (vectors, PEM/PKCS#8 export/import patterns).
src/libraries/System.Security.Cryptography/tests/System.Security.Cryptography.Tests.csproj Wires new X25519 test files + shared PKCS#8 helper into test build.
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X25519DiffieHellmanImplementation.Windows.cs Implements X25519 over CNG (key import/export + secret agreement).
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X25519DiffieHellmanImplementation.OpenSsl.cs Implements X25519 over OpenSSL handles + PAL entrypoints.
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X25519DiffieHellmanImplementation.NotSupported.cs Provides the not-supported fallback implementation.
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X25519DiffieHellmanImplementation.Apple.cs Implements X25519 using AppleCrypto interop (CryptoKit).
src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X25519DiffieHellman.cs Adds the public API surface and shared PKCS#8/SPKI/PEM glue logic.
src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj Adds new sources + platform interop files to the library build.
src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs Adds reference assembly surface for X25519DiffieHellman.
src/libraries/Common/tests/System/Security/Cryptography/Pkcs8TestHelpers.cs Introduces shared PKCS#8-encryption structure validation helper for tests.
src/libraries/Common/tests/System/Security/Cryptography/MLKemBaseTests.cs Refactors PKCS#8 encryption assertions to reuse Pkcs8TestHelpers.
src/libraries/Common/src/System/Security/Cryptography/Oids.cs Adds the X25519 OID constant for use in encoding/decoding.
src/libraries/Common/src/Microsoft/Win32/SafeHandles/SafeBCryptSecretHandle.cs Adds SafeHandle wrapper for BCrypt secret agreement handles.
src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptSecretAgreement.cs Adds BCryptSecretAgreement P/Invoke wrapper returning SafeBCryptSecretHandle.
src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDestroySecret.cs Adds BCryptDestroySecret P/Invoke for SafeHandle release.
src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDeriveKey.cs Adds BCryptDeriveKey P/Invoke wrapper used by X25519 derivation on Windows.
src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.X25519.cs Adds Unix/OpenSSL interop wrappers for X25519 PAL entrypoints.
src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X25519.cs Adds AppleCrypto interop + SafeX25519KeyHandle definition.
THIRD-PARTY-NOTICES.TXT Adds Wycheproof Apache-2.0 license notice for included test vectors.

Copilot's findings

Comments suppressed due to low confidence (2)

src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X25519DiffieHellman.cs:1276

  • ImportFromEncryptedPem(ReadOnlySpan, ReadOnlySpan) also doesn't call ThrowIfNotSupported() before attempting to parse the PEM. This can result in non-PlatformNotSupportedException failures when X25519 isn't available. Add an early ThrowIfNotSupported() for consistent platform-guard behavior.
        public static X25519DiffieHellman ImportFromEncryptedPem(ReadOnlySpan<char> source, ReadOnlySpan<byte> passwordBytes)
        {
            return PemKeyHelpers.ImportEncryptedFactoryPem<X25519DiffieHellman, byte>(
                source,
                passwordBytes,
                ImportEncryptedPkcs8PrivateKey);
        }

src/libraries/Common/tests/System/Security/Cryptography/MLKemBaseTests.cs:575

  • After switching AssertEncryptedPkcs8PrivateKeyContents to call Pkcs8TestHelpers, GetHashAlgorithmFromPbkdf2Params is now unused in this file. Please remove the dead method (and any now-unused usings) to avoid analyzer warnings / warnings-as-errors in test builds.
        private static void AssertEncryptedPkcs8PrivateKeyContents(PbeParameters pbeParameters, ReadOnlyMemory<byte> contents)
        {
            Pkcs8TestHelpers.AssertEncryptedPkcs8PrivateKeyContents(pbeParameters, contents);
        }

        private static HashAlgorithmName GetHashAlgorithmFromPbkdf2Params(in ValuePbkdf2Params pbkdf2Params)
        {
            return pbkdf2Params.Prf.Algorithm switch
            {
                "1.2.840.113549.2.7" => HashAlgorithmName.SHA1,
                "1.2.840.113549.2.9" => HashAlgorithmName.SHA256,
                "1.2.840.113549.2.10" => HashAlgorithmName.SHA384,
                "1.2.840.113549.2.11" => HashAlgorithmName.SHA512,
                string other => throw new XunitException($"Unknown hash algorithm OID '{other}'."),
            };
        }
  • Files reviewed: 33/33 changed files
  • Comments generated: 3

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 21, 2026 21:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Comments suppressed due to low confidence (1)

src/libraries/Common/tests/System/Security/Cryptography/MLKemBaseTests.cs:574

  • GetHashAlgorithmFromPbkdf2Params is now unused after moving the encrypted PKCS#8 parsing assertions into Pkcs8TestHelpers. If warnings are treated as errors for this test project, this will break the build. Remove the unused method (and any now-unneeded usings) or use it from Pkcs8TestHelpers instead of duplicating logic there.
        private static void AssertEncryptedPkcs8PrivateKeyContents(PbeParameters pbeParameters, ReadOnlyMemory<byte> contents)
        {
            Pkcs8TestHelpers.AssertEncryptedPkcs8PrivateKeyContents(pbeParameters, contents);
        }

        private static HashAlgorithmName GetHashAlgorithmFromPbkdf2Params(in ValuePbkdf2Params pbkdf2Params)
        {
            return pbkdf2Params.Prf.Algorithm switch
            {
                "1.2.840.113549.2.7" => HashAlgorithmName.SHA1,
                "1.2.840.113549.2.9" => HashAlgorithmName.SHA256,
                "1.2.840.113549.2.10" => HashAlgorithmName.SHA384,
                "1.2.840.113549.2.11" => HashAlgorithmName.SHA512,
                string other => throw new XunitException($"Unknown hash algorithm OID '{other}'."),
            };
  • Files reviewed: 33/33 changed files
  • Comments generated: 2

Copy link
Copy Markdown
Member

@bartonjs bartonjs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made it through the main (non-native) implementation parts, stopped before the tests. I'll look more tomorrow.

Copilot AI review requested due to automatic review settings April 22, 2026 02:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 34/34 changed files
  • Comments generated: 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants