5
5
using System ;
6
6
using System . Diagnostics ;
7
7
using System . Security . Cryptography ;
8
+ using System . Security . Cryptography . X509Certificates ;
8
9
9
10
namespace Microsoft . Data . SqlClient
10
11
{
11
- // Contains methods to convert cryptography keys between different formats.
12
- internal sealed class KeyConverter
13
- {
12
+ internal sealed partial class KeyConverter
13
+ {
14
+ // Magic numbers identifying blob types
15
+ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/cba27df5-4880-4f95-a879-783f8657e53b
16
+ private readonly struct KeyBlobMagicNumber
17
+ {
18
+ internal static readonly byte [ ] ECDHPublicP384 = new byte [ ] { 0x45 , 0x43 , 0x4b , 0x33 } ;
19
+ }
20
+
21
+ // The ECC public key blob is structured as follows:
22
+ // BCRYPT_ECCKEY_BLOB header
23
+ // byte[KeySize] X
24
+ // byte[KeySize] Y
25
+ private readonly struct ECCPublicKeyBlob
26
+ {
27
+ // Size of an ECC public key blob
28
+ internal const int Size = 104 ;
29
+ // Size of the BCRYPT_ECCKEY_BLOB header
30
+ internal const int HeaderSize = 8 ;
31
+ // Size of each coordinate
32
+ internal const int KeySize = ( Size - HeaderSize ) / 2 ;
33
+ }
34
+
35
+ // Serializes an ECDiffieHellmanPublicKey to an ECC public key blob
36
+ // "ECDiffieHellmanPublicKey.ToByteArray() doesn't have a (standards-)defined export
37
+ // format. The version used by ECDiffieHellmanPublicKeyCng is Windows-specific"
38
+ // from https://github.com/dotnet/runtime/issues/27276
39
+ // => ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix
40
+ internal static byte [ ] GetECDiffieHellmanPublicKeyBlob ( ECDiffieHellman ecDiffieHellman )
41
+ {
42
+ byte [ ] keyBlob = new byte [ ECCPublicKeyBlob . Size ] ;
43
+
44
+ // Set magic number
45
+ Buffer . BlockCopy ( KeyBlobMagicNumber . ECDHPublicP384 , 0 , keyBlob , 0 , 4 ) ;
46
+ // Set key size
47
+ keyBlob [ 4 ] = ( byte ) ECCPublicKeyBlob . KeySize ;
48
+
49
+ ECPoint ecPoint = ecDiffieHellman . PublicKey . ExportParameters ( ) . Q ;
50
+ Debug . Assert ( ecPoint . X . Length == ECCPublicKeyBlob . KeySize && ecPoint . Y . Length == ECCPublicKeyBlob . KeySize ,
51
+ $ "ECDH public key was not the expected length. Actual (X): { ecPoint . X . Length } . Actual (Y): { ecPoint . Y . Length } Expected: { ECCPublicKeyBlob . Size } ") ;
52
+ // Copy x and y coordinates to key blob
53
+ Buffer . BlockCopy ( ecPoint . X , 0 , keyBlob , ECCPublicKeyBlob . HeaderSize , ECCPublicKeyBlob . KeySize ) ;
54
+ Buffer . BlockCopy ( ecPoint . Y , 0 , keyBlob , ECCPublicKeyBlob . HeaderSize + ECCPublicKeyBlob . KeySize , ECCPublicKeyBlob . KeySize ) ;
55
+ return keyBlob ;
56
+ }
57
+
14
58
// The RSA public key blob is structured as follows:
15
59
// BCRYPT_RSAKEY_BLOB header
16
60
// byte[ExponentSize] publicExponent
@@ -29,59 +73,32 @@ private readonly struct RSAPublicKeyBlob
29
73
internal const int ModulusOffset = HeaderSize ;
30
74
}
31
75
32
- // Extracts the public key's modulus and exponent from an RSA public key blob
33
- // and returns an RSAParameters object
34
- internal static RSAParameters RSAPublicKeyBlobToParams ( byte [ ] keyBlob )
76
+ internal static RSA CreateRSAFromPublicKeyBlob ( byte [ ] keyBlob )
35
77
{
36
- Debug . Assert ( keyBlob . Length == RSAPublicKeyBlob . Size ,
37
- $ "RSA public key blob was not the expected length. Actual: { keyBlob . Length } . Expected: { RSAPublicKeyBlob . Size } ") ;
78
+ Debug . Assert ( keyBlob . Length == RSAPublicKeyBlob . Size , $ "RSA public key blob was not the expected length. Actual: { keyBlob . Length } . Expected: { RSAPublicKeyBlob . Size } ") ;
38
79
39
80
byte [ ] exponent = new byte [ RSAPublicKeyBlob . ExponentSize ] ;
40
81
byte [ ] modulus = new byte [ RSAPublicKeyBlob . ModulusSize ] ;
41
82
Buffer . BlockCopy ( keyBlob , RSAPublicKeyBlob . ExponentOffset , exponent , 0 , RSAPublicKeyBlob . ExponentSize ) ;
42
83
Buffer . BlockCopy ( keyBlob , RSAPublicKeyBlob . ModulusOffset , modulus , 0 , RSAPublicKeyBlob . ModulusSize ) ;
43
-
44
- return new RSAParameters ( )
84
+ var rsaParameters = new RSAParameters ( )
45
85
{
46
86
Exponent = exponent ,
47
87
Modulus = modulus
48
88
} ;
89
+ return RSA . Create ( rsaParameters ) ;
49
90
}
50
91
51
- // The ECC public key blob is structured as follows:
52
- // BCRYPT_ECCKEY_BLOB header
53
- // byte[KeySize] X
54
- // byte[KeySize] Y
55
- private readonly struct ECCPublicKeyBlob
56
- {
57
- // Size of an ECC public key blob
58
- internal const int Size = 104 ;
59
- // Size of the BCRYPT_ECCKEY_BLOB header
60
- internal const int HeaderSize = 8 ;
61
- // Size of each coordinate
62
- internal const int KeySize = ( Size - HeaderSize ) / 2 ;
63
- }
64
-
65
- // Magic numbers identifying blob types
66
- // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/cba27df5-4880-4f95-a879-783f8657e53b
67
- private readonly struct KeyBlobMagicNumber
68
- {
69
- internal static readonly byte [ ] ECDHPublicP384 = new byte [ ] { 0x45 , 0x43 , 0x4b , 0x33 } ;
70
- }
71
-
72
- // Extracts the public key's X and Y coordinates from an ECC public key blob
73
- // and returns an ECParameters object
74
- internal static ECParameters ECCPublicKeyBlobToParams ( byte [ ] keyBlob )
92
+ internal static ECDiffieHellman CreateECDiffieHellmanFromPublicKeyBlob ( byte [ ] keyBlob )
75
93
{
76
- Debug . Assert ( keyBlob . Length == ECCPublicKeyBlob . Size ,
77
- $ "ECC public key blob was not the expected length. Actual: { keyBlob . Length } . Expected: { ECCPublicKeyBlob . Size } ") ;
94
+ Debug . Assert ( keyBlob . Length == ECCPublicKeyBlob . Size , $ "ECC public key blob was not the expected length. Actual: { keyBlob . Length } . Expected: { ECCPublicKeyBlob . Size } ") ;
78
95
79
96
byte [ ] x = new byte [ ECCPublicKeyBlob . KeySize ] ;
80
97
byte [ ] y = new byte [ ECCPublicKeyBlob . KeySize ] ;
81
98
Buffer . BlockCopy ( keyBlob , ECCPublicKeyBlob . HeaderSize , x , 0 , ECCPublicKeyBlob . KeySize ) ;
82
99
Buffer . BlockCopy ( keyBlob , ECCPublicKeyBlob . HeaderSize + ECCPublicKeyBlob . KeySize , y , 0 , ECCPublicKeyBlob . KeySize ) ;
83
100
84
- return new ECParameters
101
+ var parameters = new ECParameters
85
102
{
86
103
Curve = ECCurve . NamedCurves . nistP384 ,
87
104
Q = new ECPoint
@@ -90,29 +107,29 @@ internal static ECParameters ECCPublicKeyBlobToParams(byte[] keyBlob)
90
107
Y = y
91
108
} ,
92
109
} ;
110
+
111
+ return ECDiffieHellman . Create ( parameters ) ;
93
112
}
94
113
95
- // Serializes an ECDiffieHellmanPublicKey to an ECC public key blob
96
- // "ECDiffieHellmanPublicKey.ToByteArray() doesn't have a (standards-)defined export
97
- // format. The version used by ECDiffieHellmanPublicKeyCng is Windows-specific"
98
- // from https://github.com/dotnet/runtime/issues/27276
99
- // => ECDiffieHellmanPublicKey.ToByteArray() is not supported in Unix
100
- internal static byte [ ] ECDHPublicKeyToECCKeyBlob ( ECDiffieHellmanPublicKey publicKey )
114
+ internal static ECDiffieHellman CreateECDiffieHellman ( int keySize )
101
115
{
102
- byte [ ] keyBlob = new byte [ ECCPublicKeyBlob . Size ] ;
116
+ // platform agnostic creates a key of the correct size but does not
117
+ // set the key derivation type or algorithm, these must be set by calling
118
+ // DeriveKeyFromHash later in DeriveKey
119
+ ECDiffieHellman clientDHKey = ECDiffieHellman . Create ( ) ;
120
+ clientDHKey . KeySize = keySize ;
121
+ return clientDHKey ;
122
+ }
103
123
104
- // Set magic number
105
- Buffer . BlockCopy ( KeyBlobMagicNumber . ECDHPublicP384 , 0 , keyBlob , 0 , 4 ) ;
106
- // Set key size
107
- keyBlob [ 4 ] = ( byte ) ECCPublicKeyBlob . KeySize ;
124
+ internal static byte [ ] DeriveKey ( ECDiffieHellman ecd , ECDiffieHellmanPublicKey publicKey )
125
+ {
126
+ // see notes in CreateECDDiffieHellman
127
+ return ecd . DeriveKeyFromHash ( publicKey , HashAlgorithmName . SHA256 ) ;
128
+ }
108
129
109
- ECPoint ecPoint = publicKey . ExportParameters ( ) . Q ;
110
- Debug . Assert ( ecPoint . X . Length == ECCPublicKeyBlob . KeySize && ecPoint . Y . Length == ECCPublicKeyBlob . KeySize ,
111
- $ "ECDH public key was not the expected length. Actual (X): { ecPoint . X . Length } . Actual (Y): { ecPoint . Y . Length } Expected: { ECCPublicKeyBlob . Size } ") ;
112
- // Copy x and y coordinates to key blob
113
- Buffer . BlockCopy ( ecPoint . X , 0 , keyBlob , ECCPublicKeyBlob . HeaderSize , ECCPublicKeyBlob . KeySize ) ;
114
- Buffer . BlockCopy ( ecPoint . Y , 0 , keyBlob , ECCPublicKeyBlob . HeaderSize + ECCPublicKeyBlob . KeySize , ECCPublicKeyBlob . KeySize ) ;
115
- return keyBlob ;
130
+ internal static RSA GetRSAFromCertificate ( X509Certificate2 certificate )
131
+ {
132
+ return certificate . GetRSAPublicKey ( ) ;
116
133
}
117
134
}
118
135
}
0 commit comments