ECDH C# key exchange ( get the shared secret beetween the two party)

146 Views Asked by At

I have a smart card reader and a smart card. I need to perform a Diffie-Hellman key exchange between the chip and the reader to get the shared secret, and then generate a new DHMappedGenerator in C#.

I have an elliptic curve with the following information:

Using ECC-NIST 256 curve for the domain parameters
Could be another curve,
Private ECC key (Generated from a RNG)
d_pace_ecdh_card_private=0029482318BE67844AE13D6C2CD672AE69525F9016496DF15AF141BB26E901EB
prime=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
a=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
order=FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
b=5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
G_X=
basepoint=6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5

Calculate Ecc public key (Q=d_pace_ecdh_card_private*basepoint)
pace_ecdh_public=046CEC918BFBE1198005718DEA22D2139C856B66326B66A8AF769DAADB4D4F439B56A161713158746F8D3117F097972B1F9CB2382E54A3AF2D61FAA30ED1FEF436

I also have a temporary public key from the chip:
Key: ~DH_PK_PICC - DH ephemeral public key of passport (for generic mapping)
04 c0 ba 9a 4b ca 30 66 a2 de c5 fc 9b 12 03 15 3e 24 ec 8b 69 c0 23 c2 17 cf a4 66 ad b9 fd c3 cd 39 9f 04 a7 fe db 45 cc c5 df 8e 24 aa da c6 23 d4 ec 81 09 32 6c 28 7f 68 03 93 04 46 eb 49 45

Here is the beginning of my code but I am lost:

public string getSharedSecret(string DH_PK_PICC)
{
    // PCD (Proximity Coupling Device) that means the terminal (the reader) AND //PICC (Proximity Integrated Circuit Card) that means the card (the chip)

    // PCD DH ephemeral private key
    var sk_pcd = "0029482318BE67844AE13D6C2CD672AE69525F9016496DF15AF141BB26E901EB";
    var sharedSecret = "";
    using (ECDiffieHellman PCD = ECDiffieHellman.Create(System.Security.Cryptography.ECCurve.NamedCurves.nistP256))
    {

        //DH_PK_PICC is the chip public key
        byte[] DH_PK_PICCBytes = StringToByteArray(DH_PK_PICC);

        sharedSecret = byteToHexStr(getDeriveKey(DH_PK_PICCBytes, PCD));            

    }

    return sharedSecret;
}

static byte[] getDeriveKey(byte[] key1, ECDiffieHellman alice)
{
    byte[] keyX = new byte[key1.Length / 2];
    byte[] keyY = new byte[keyX.Length];
    Buffer.BlockCopy(key1, 1, keyX, 0, keyX.Length);
    Buffer.BlockCopy(key1, 1 + keyX.Length, keyY, 0, keyY.Length);
    ECParameters parameters = new ECParameters
    {
        Curve = ECCurve.NamedCurves.nistP256,
        Q =
    {
        X = keyX,
        Y = keyY,
    },
    };
    byte[] derivedKey;
    using (ECDiffieHellman bob = ECDiffieHellman.Create(parameters))
    using (ECDiffieHellmanPublicKey bobPublic = bob.PublicKey)
    {
        return derivedKey = alice.DeriveKeyFromHash(bobPublic, HashAlgorithmName.SHA256);
    }
}

Here is the type of key I get as output: A3E4EE14B631B0962AA2795F57530ABEBAD150BA4E088D226A2970C7BC1BDEF8

And here is the type of key the chip gets as output:

04 5b 92 77 be 2a 64 a3 71 4a 53 11 db 5e d4 8b d1 ca 6b 85 a3 53 c8 8f d6 c6 7d 9e 05 5a 43 89 4d 44 83 c3 46 3f 59 d3 b0 33 ff e0 da 9a 93 32 f9 1f 51 6f de 5c ca a2 cd 85 b5 af 81 7a eb d6 c4```

The two keys are of different sizes.

And here is the new Domain that the chip generates:

 mapped DH domain parameters (~D [PACE])
```none
30 81 e0 02 01 01 30 2c 06 07 2a 86 48 ce 3d
01 02 21 00 ff ff ff ff 00 00 00 01 00 00 00 00
00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff
ff ff ff ff 30 44 04 20 ff ff ff ff 00 00 00 01
00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff
ff ff ff ff ff ff ff fc 04 20 5a c6 35 d8 aa 3a
93 e7 b3 eb bd 55 76 98 86 bc 65 1d 06 b0 cc 53
b0 f6 3b ce 3c 3e 27 d2 60 4b 04 41 04 6f ab 85
68 33 01 94 d3 ed 31 47 55 15 bc 82 d8 03 b7 db
c7 95 9b e9 06 32 fb be 03 48 8d 83 f8 f6 d7 26
43 a6 c0 20 d2 74 cb c5 1c fb 2e 21 f0 4f fc 1f
bb 00 97 6d c1 38 f8 f9 e2 ae 7a 00 88 02 21 00
ff ff ff ff 00 00 00 00 ff ff ff ff ff ff ff ff
bc e6 fa ad a7 17 9e 84 f3 b9 ca c2 fc 63 25 51 02 01 01

Edit - LOG PLATINUMREADER

Using PACE algorithm index: 0
PACE Protocol OID: id-PACE-ECDH-GM-AES-CBC-CMAC-128
Protocol: PACE - Start
Info: Version - 2
 Info: SharedPasswordType - PIN (0x03)

APDU: SetMSE Pace - Start
APDU: Request
                                                            00 22 c1 a4 12 80 0a 04 00 7f 00 07 02 02 04 02 ."..............
                                                            02 83 01 03 84 01 0c                            .......
APDU: Response                                                         90 00                                           ..
APDU: SetMSE Pace - End
APDU: GeneralAuthentication - Start
APDU: Request                                                            10 86 00 00 02 7c 00 00                         .....|..
APDU: Response                                                            7c 12 80 10 53 55 da 31 de a7 f3 5b 58 71 ef fe |...SU.1...[Xq..                                                     c2 34 45 66 90 00                            .4Ef..
APDU: GeneralAuthentication - End
Key: z - encrypted nonce (z [PACE])                                                            53 55 da 31 de a7 f3 5b 58 71 ef fe c2 34 45 66 SU.1...[Xq...4Ef
Key: K - derived key from shared secret                                                            59 20 1b d2 c1 c3 4b ac c9 83 e7 93 34 1d af e1 Y ....K.....4...
Key: nonce - decrypted nonce                                                            70 87 3d 68 3a 1b 99 59 df 89 6a d2 61 10 b7 bf p.=h:..Y..j.a...
Key: D_PICC - original DH domain parameters (D_PICC [PACE])                                                            30 81 e0 02 01 01 30 2c 06 07 2a 86 48 ce 3d 01 0.....0,..*.H.=.                                                            01 02 21 00 ff ff ff ff 00 00 00 01 00 00 00 00 ..!.............                                                            00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff ................                                                            ff ff ff ff 30 44 04 20 ff ff ff ff 00 00 00 01 ....0D. ........                                                            00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ................                                                            ff ff ff ff ff ff ff fc 04 20 5a c6 35 d8 aa 3a ......... Z.5..:                                                            93 e7 b3 eb bd 55 76 98 86 bc 65 1d 06 b0 cc 53 .....Uv...e....S                                                            b0 f6 3b ce 3c 3e 27 d2 60 4b 04 41 04 6b 17 d1 ..;.<>'.`K.A.k..                                                            f2 e1 2c 42 47 f8 bc e6 e5 63 a4 40 f2 77 03 7d ..,[email protected].}                                                            81 2d eb 33 a0 f4 a1 39 45 d8 98 c2 96 4f e3 42 .-.3...9E....O.B                                                            e2 fe 1a 7f 9b 8e e7 eb 4a 7c 0f 9e 16 2b ce 33 ........J|...+.3                                                            57 6b 31 5e ce cb b6 40 68 37 bf 51 f5 02 21 00 Wk1^[email protected]..!.                                                            ff ff ff ff 00 00 00 00 ff ff ff ff ff ff ff ff ................                                                            bc e6 fa ad a7 17 9e 84 f3 b9 ca c2 fc 63 25 51 .............c%Q                                                            02 01 01                                        ...
Info: Algorithm - ECDH
Operations: Passport::performPACE - Generating DH key pair (for generic mapping)
Key: ~DH_PCD_SK - DH ephemeral private key (for generic mapping)                                                            e7 d8 72 d4 21 57 24 6e 0e 24 3e 5d 96 93 4b 79 ..r.!W$n.$>]..Ky                                                            8a a8 2b 39 d9 d2 b6 c6 a8 24 35 a6 b2 33 b1 e5 ..+9.....$5..3..
Key: ~DH_PCD_PK - DH ephemeral public key (for generic mapping)                                                            04 4a ef 83 45 4d dd 59 b4 81 24 df cf ad 73 97 .J..EM.Y..$...s.                                                            9f 67 15 91 bd e3 d8 12 f1 03 a5 4a 52 02 f4 9f .g.........JR...                                                            50 85 0e 5d b4 42 94 4a 44 9a d2 4a 50 e7 1c 5b P..].B.JD..JP..[                                                            c7 f2 7d 10 34 c7 32 d4 ea 3b 9c 6f 96 20 74 17 ..}.4.2..;.o. t.                                                            bc                                              .
APDU: GeneralAuthenticate - Start
APDU: Request                                                            10 86 00 00 45 7c 43 81 41 04 4a ef 83 45 4d dd ....E|C.A.J..EM.                                                            59 b4 81 24 df cf ad 73 97 9f 67 15 91 bd e3 d8 Y..$...s..g.....                                                            12 f1 03 a5 4a 52 02 f4 9f 50 85 0e 5d b4 42 94 ....JR...P..].B.                                                            4a 44 9a d2 4a 50 e7 1c 5b c7 f2 7d 10 34 c7 32 JD..JP..[..}.4.2                                                            d4 ea 3b 9c 6f 96 20 74 17 bc 00                ..;.o. t...

APDU: Response                                                            7c 43 82 41 04 c0 ba 9a 4b ca 30 66 a2 de c5 fc |C.A....K.0f....                                                            9b 12 03 15 3e 24 ec 8b 69 c0 23 c2 17 cf a4 66 ....>$..i.#....f                                                            ad b9 fd c3 cd 39 9f 04 a7 fe db 45 cc c5 df 8e .....9.....E....                                                            24 aa da c6 23 d4 ec 81 09 32 6c 28 7f 68 03 93 $...#....2l(.h..                                                            04 46 eb 49 45 90 00                            .F.IE..
APDU: GeneralAuthenticate - End

Key: ~DH_PK_PICC - DH ephemeral public key of passport (for generic mapping)                                                            
04 c0 ba 9a 4b ca 30 66 a2 de c5 fc 9b 12 03 15 ....K.0f........                                                            3e 24 ec 8b 69 c0 23 c2 17 cf a4 66 ad b9 fd c3 >$..i.#....f....                                                            cd 39 9f 04 a7 fe db 45 cc c5 df 8e 24 aa da c6 .9.....E....$...                                                            23 d4 ec 81 09 32 6c 28 7f 68 03 93 04 46 eb 49 #....2l(.h...F.I                                                            45 
Key: DHMappedGenerator - DH shared secret (mapped Generator)                                                            04 5b 92 77 be 2a 64 a3 71 4a 53 11 db 5e d4 8b .[.w.*d.qJS..^..                                                            d1 ca 6b 85 a3 53 c8 8f d6 c6 7d 9e 05 5a 43 89 ..k..S....}..ZC.                                                            4d 44 83 c3 46 3f 59 d3 b0 33 ff e0 da 9a 93 32 MD..F?Y..3.....2                                                            f9 1f 51 6f de 5c ca a2 cd 85 b5 af 81 7a eb d6 ..Qo.\.......z..                                                            c4                                              .
Key: ~D - mapped DH domain parameters (~D [PACE])
                                                            30 81 e0 02 01 01 30 2c 06 07 2a 86 48 ce 3d 01 0.....0,..*.H.=.
                                                            01 02 21 00 ff ff ff ff 00 00 00 01 00 00 00 00 ..!.............
                                                            00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff ................
                                                            ff ff ff ff 30 44 04 20 ff ff ff ff 00 00 00 01 ....0D. ........
                                                            00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff ................
                                                            ff ff ff ff ff ff ff fc 04 20 5a c6 35 d8 aa 3a ......... Z.5..:
                                                            93 e7 b3 eb bd 55 76 98 86 bc 65 1d 06 b0 cc 53 .....Uv...e....S
                                                            b0 f6 3b ce 3c 3e 27 d2 60 4b 04 41 04 6f ab 85 ..;.<>'.`K.A.o..
                                                            68 33 01 94 d3 ed 31 47 55 15 bc 82 d8 03 b7 db h3....1GU.......
                                                            c7 95 9b e9 06 32 fb be 03 48 8d 83 f8 f6 d7 26 .....2...H.....&
                                                            43 a6 c0 20 d2 74 cb c5 1c fb 2e 21 f0 4f fc 1f C.. .t.....!.O..
                                                            bb 00 97 6d c1 38 f8 f9 e2 ae 7a 00 88 02 21 00 ...m.8....z...!.
                                                            ff ff ff ff 00 00 00 00 ff ff ff ff ff ff ff ff ................
                                                            bc e6 fa ad a7 17 9e 84 f3 b9 ca c2 fc 63 25 51 .............c%Q
                                                            02 01 01                                        ...
00:00:00.147 GENERIC P21188 T31468 2024-03-08 17:28:58.056: Info: DH-KA Algorithm - ECDH
00:00:00.151 GENERIC P21188 T31468 2024-03-08 17:28:58.060: Operations: Passport::performPACE - Generating DH key pair
00:00:00.152 GENERIC P21188 T31468 2024-03-08 17:28:58.061: Key: ~SK_PCD - DH ephemeral private key (~SK_PCD [PACE])
                                                            4b 9d 93 b2 0f af 53 72 4e 6d 21 f8 e7 32 29 77 K.....SrNm!..2)w
                                                            16 74 e5 c9 e7 fc 8e 3d 7a 86 cd c4 36 e9 65 3f .t.....=z...6.e?
00:00:00.152 GENERIC P21188 T31468 2024-03-08 17:28:58.061: Key: ~PK_PCD - DH ephemeral public key (~PK_PCD [PACE])
                                                            04 f0 d0 65 a4 16 54 a3 b7 91 20 38 3f df d6 5a ...e..T... 8?..Z
                                                            92 f0 8f a1 db 77 29 85 bd f8 6c 95 20 d1 f6 6c .....w)...l. ..l
                                                            fe 1b 10 4d 0d 4e 88 52 a0 a9 02 96 7d 14 87 bc ...M.N.R....}...
                                                            a5 a5 0d 18 d9 8e f8 5a 51 c3 47 80 26 c2 b0 7c .......ZQ.G.&..|
                                                            be                                              .
00:00:00.152 GENERIC P21188 T31468 2024-03-08 17:28:58.061: APDU: GeneralAuthenticate - Start
00:00:00.152 GENERIC P21188 T31468 2024-03-08 17:28:58.061: APDU: Request
                                                            10 86 00 00 45 7c 43 83 41 04 f0 d0 65 a4 16 54 ....E|C.A...e..T
                                                            a3 b7 91 20 38 3f df d6 5a 92 f0 8f a1 db 77 29 ... 8?..Z.....w)
                                                            85 bd f8 6c 95 20 d1 f6 6c fe 1b 10 4d 0d 4e 88 ...l. ..l...M.N.
                                                            52 a0 a9 02 96 7d 14 87 bc a5 a5 0d 18 d9 8e f8 R....}..........
                                                            5a 51 c3 47 80 26 c2 b0 7c be 00                ZQ.G.&..|..
00:00:00.259 GENERIC P21188 T31468 2024-03-08 17:28:58.168: APDU: Response
                                                            7c 43 84 41 04 18 2f f1 3b 46 7b ea e0 55 51 dc |C.A../.;F{..UQ.
                                                            1b d5 1b 2c 69 3a c4 c3 c7 71 aa dc 5f d3 15 29 ...,i:...q.._..)
                                                            a3 3f 72 9e a0 22 cd 80 60 1e 79 09 4f 89 90 5b .?r.."..`.y.O..[
                                                            b5 5d dc 47 d0 43 28 de ad 9b 68 15 c1 88 d7 35 .].G.C(...h....5
                                                            6b 05 77 2a a4 90 00                            k.w*...
00:00:00.259 GENERIC P21188 T31468 2024-03-08 17:28:58.168: APDU: GeneralAuthenticate - End
00:00:00.259 GENERIC P21188 T31468 2024-03-08 17:28:58.168: Key: ~PK_PICC - DH ephemeral public key of passport (~PK_PICC [PACE])
                                                            04 18 2f f1 3b 46 7b ea e0 55 51 dc 1b d5 1b 2c ../.;F{..UQ....,
                                                            69 3a c4 c3 c7 71 aa dc 5f d3 15 29 a3 3f 72 9e i:...q.._..).?r.
                                                            a0 22 cd 80 60 1e 79 09 4f 89 90 5b b5 5d dc 47 ."..`.y.O..[.].G
                                                            d0 43 28 de ad 9b 68 15 c1 88 d7 35 6b 05 77 2a .C(...h....5k.w*
                                                            a4                                              .
00:00:00.260 GENERIC P21188 T31468 2024-03-08 17:28:58.169: Key: K - DH shared secret (K [PACE])
                                                            ae 99 f4 dc f9 44 a4 59 7c 8d 58 bd 7b 32 94 63 .....D.Y|.X.{2.c
                                                            c0 d3 eb 62 3d 43 9a 88 89 53 24 8f 93 8e c3 d3 ...b=C...S$.....
00:00:00.260 GENERIC P21188 T31468 2024-03-08 17:28:58.169: Key: K_Enc - derived encryption key (K_Enc [PACE])
                                                            0d 88 f5 67 7a 4b 90 06 50 39 21 f5 4e e1 cf 50 ...gzK..P9!.N..P
00:00:00.260 GENERIC P21188 T31468 2024-03-08 17:28:58.169: Key: K_MAC - derived MAC key (K_MAC [PACE])
                                                            bb 65 75 d3 c8 11 d3 ec 1a d4 8e 81 1e ad 9b d4 .eu.............
00:00:00.260 GENERIC P21188 T31468 2024-03-08 17:28:58.169: Operations: Passport::performPACE - Preparing exchange of PCD authentication tokens
00:00:00.265 GENERIC P21188 T31468 2024-03-08 17:28:58.174: Operations: Passport::performPACE - Preparing exchange of ICC authentication tokens
00:00:00.269 GENERIC P21188 T31468 2024-03-08 17:28:58.178: Key: T_PCD - PCD's calculated authentication token (T_PCD [PACE])
                                                            ac 21 04 5b bc 13 6e 3c                         .!.[..n<
00:00:00.269 GENERIC P21188 T31468 2024-03-08 17:28:58.178: Key: T_PICC - PICC's calculated authentication token (T_PICC [PACE])
                                                            00 9a 51 40 9e a8 27 47                         ..Q@..'G
00:00:00.269 GENERIC P21188 T31468 2024-03-08 17:28:58.178: APDU: GeneralAuthenticate - Start
00:00:00.269 GENERIC P21188 T31468 2024-03-08 17:28:58.178: APDU: Request
                                                            00 86 00 00 0c 7c 0a 85 08 ac 21 04 5b bc 13 6e .....|....!.[..n
                                                            3c 00                                           <.
00:00:00.329 GENERIC P21188 T31468 2024-03-08 17:28:58.238: APDU: Response
                                                            7c 0a 86 08 00 9a 51 40 9e a8 27 47 90 00       |.....Q@..'G..
00:00:00.329 GENERIC P21188 T31468 2024-03-08 17:28:58.238: APDU: GeneralAuthenticate - End
00:00:00.329 GENERIC P21188 T31468 2024-03-08 17:28:58.238: Protocol: PACE - End
00:00:00.329 INFO    P21188 T31468 2024-03-08 17:28:58.238: PACE processing time 00:00:00.281
1

There are 1 best solutions below

4
Topaco On

There are several issues in your code, e.g:

  • sk_pcd contains the wrong private key;
  • even if sk_pcd would contain the correct key, it is not imported anywhere, instead a random key is applied;
  • DeriveKeyFromHash() does not determine the raw shared secret, but its hash;
  • during processing, two shared secrets are determined, of which only one is considered.

Here is an overview of the PACE protocol. During processing, two shared secrets are generated (referred to as mapped generator and K [PACE] in the PACE log), which have the following values in the posted PACE log together with the private and public keys involved:

- mapped generator
shared secret, ECPoint:  0x045b9277be2a64a3714a5311db5ed48bd1ca6b85a353c88fd6c67d9e055a43894d4483c3463f59d3b033ffe0da9a9332f91f516fde5ccaa2cd85b5af817aebd6c4
private key (DH_PCD_SK): 0xe7d872d42157246e0e243e5d96934b798aa82b39d9d2b6c6a82435a6b233b1e5
public key (DH_PK_PICC): 0x04c0ba9a4bca3066a2dec5fc9b1203153e24ec8b69c023c217cfa466adb9fdc3cd399f04a7fedb45ccc5df8e24aadac623d4ec8109326c287f6803930446eb4945

- K [PACE]
shared secret:           0xae99f4dcf944a4597c8d58bd7b329463c0d3eb623d439a888953248f938ec3d3
private key (SK_PCD):    0x4b9d93b20faf53724e6d21f8e73229771674e5c9e7fc8e3d7a86cdc436e9653f
public key (PK_PICC):    0x04182ff13b467beae05551dc1bd51b2c693ac4c3c771aadc5fd31529a33f729ea022cd80601e79094f89905bb55ddc47d04328dead9b6815c188d7356b05772aa4

Regarding the different lengths of the shared secrets: In the ECDH key agreement, the own private key (a scalar) and the public key of the other party (an ECPoint) are scalar mutiplied. The result is an ECPoint whose x coordinate is used as the shared secret.
In the first case, the PACE log specifies the full EC Point associated with the shared secret in uncompressed format (0x04|x|y, length: 1+32+32=65 bytes), while in the second case only the shared secret is specified (length: 32 bytes).

The shared secrets can be determined using native .NET methods, e.g. as follows:

using System;
using System.Linq;
using System.Security.Cryptography;

...

// mapped generator
using ECDiffieHellmanPublicKey ecdhPublic1 = getPublicKey("04c0ba9a4bca3066a2dec5fc9b1203153e24ec8b69c023c217cfa466adb9fdc3cd399f04a7fedb45ccc5df8e24aadac623d4ec8109326c287f6803930446eb4945");
using ECDiffieHellman ecdhPrivate1 = getPrivateKey("e7d872d42157246e0e243e5d96934b798aa82b39d9d2b6c6a82435a6b233b1e5");
var sharedSecret1 = ecdhPrivate1.DeriveRawSecretAgreement(ecdhPublic1);
Console.WriteLine(Convert.ToHexString(sharedSecret1)); // 5B9277BE2A64A3714A5311DB5ED48BD1CA6B85A353C88FD6C67D9E055A43894D

// K [PACE]
using ECDiffieHellmanPublicKey ecdhPublic2 = getPublicKey("04182ff13b467beae05551dc1bd51b2c693ac4c3c771aadc5fd31529a33f729ea022cd80601e79094f89905bb55ddc47d04328dead9b6815c188d7356b05772aa4");
using ECDiffieHellman ecdhPrivate2 = getPrivateKey("4b9d93b20faf53724e6d21f8e73229771674e5c9e7fc8e3d7a86cdc436e9653f");
var sharedSecret2 = ecdhPrivate2.DeriveRawSecretAgreement(ecdhPublic2);
Console.WriteLine(Convert.ToHexString(sharedSecret2)); // AE99F4DCF944A4597C8D58BD7B329463C0D3EB623D439A888953248F938EC3D3

...

private static ECDiffieHellman getPrivateKey(string privateHex)
{
    byte[] rawPrivate = Convert.FromHexString(privateHex);
    ECParameters privateParameters = new()
    {
        Curve = ECCurve.NamedCurves.nistP256,
        D = rawPrivate
    };
    return ECDiffieHellman.Create(privateParameters);
}

private static ECDiffieHellmanPublicKey getPublicKey(string publicUncompressedHex)
{
    ECPoint rawPublic = new()
    {
        X = Convert.FromHexString(publicUncompressedHex).Skip(1).Take(32).ToArray(),
        Y = Convert.FromHexString(publicUncompressedHex).Skip(1 + 32).Take(32).ToArray()
    };
    ECParameters publicParameters = new()
    {
        Curve = ECCurve.NamedCurves.nistP256,
        Q = rawPublic
    };
    return ECDiffieHellman.Create(publicParameters).PublicKey;
}

DeriveRawSecretAgreement() is available as of .NET 8. AFAIK, earlier .NET versions do not allow the raw shared secret to be determined, but only derived values (e.g. via a hash, DeriveKeyFromHash(), or via an HMAC, DeriveKeyFromHmac()). These are non-reversible, so that the raw shared secret cannot be reconstructed from the derived values. Therefore, if the raw shared secret is required in such versions, a third-party library must be used (e.g. BouncyCastle).
In addition, only the shared secret is determined and not the corresponding full ECPoint. If the latter is required, BouncyCastle again is an option.