Implement X25519DiffieHellman#127248
Conversation
|
Tagging subscribers to this area: @bartonjs, @vcsjones, @dotnet/area-system-security |
There was a problem hiding this comment.
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.X25519DiffieHellmanAPI (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
There was a problem hiding this comment.
Copilot's findings
Comments suppressed due to low confidence (1)
src/libraries/Common/tests/System/Security/Cryptography/MLKemBaseTests.cs:574
GetHashAlgorithmFromPbkdf2Paramsis now unused after moving the encrypted PKCS#8 parsing assertions intoPkcs8TestHelpers. 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 fromPkcs8TestHelpersinstead 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
bartonjs
left a comment
There was a problem hiding this comment.
I made it through the main (non-native) implementation parts, stopped before the tests. I'll look more tomorrow.
|
At this point it is probably worth me explaining what is going on with Windows public key imports. Public keys can fall in to three buckets
All three have an additional property of whether or not they are canonically encoded as well. RFC 7748 has no restrictions on the keys that key imported. What RFC 7748 cares about is the result. If the shared secret is all zeros, this MAY be blocked. For 2 and 3, CryptoKit and OpenSSL more or less do what the RFC says: let anything import and reject the all zero shared secret. Windows, by default, does block key 2 and 3. However, this results in a different key import experience. We can pass a flag to BCrypt to permit 2 and 3. Permitting 2 has an unintended side effect though: Windows does not explicitly block producing an all-zero shared secret. It handles this at key import time instead of at shared secret creation time. However, we want to continue to allow 3: small subgroups are fine and legitimate in the case of X25519. So, to unify platform behavior, Windows has some additional handling.
|
|
/ba-g Build Analysis seems hung on |
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
Contributes to #126206