7internal static class ECCng
9 internal static CngKey ImportKeyBlob(
byte[] ecBlob,
string curveName,
bool includePrivateParameters)
39 curveName =
key.GetCurveName(out var _);
41 if (
string.IsNullOrEmpty(curveName))
61 if (blob.Length <=
sizeof(global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB))
65 fixed (
byte* ptr = blob)
67 global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB* ptr2 = (global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB*)ptr;
70 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P256_MAGIC:
71 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P384_MAGIC:
72 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P521_MAGIC:
73 ptr2->Magic = global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC;
75 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P256_MAGIC:
76 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P384_MAGIC:
77 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P521_MAGIC:
78 ptr2->Magic = global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC;
80 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P256_MAGIC:
81 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P384_MAGIC:
82 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P521_MAGIC:
83 ptr2->Magic = global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC;
85 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P256_MAGIC:
86 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P384_MAGIC:
87 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P521_MAGIC:
88 ptr2->Magic = global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC;
96 bool flag = parameters.D !=
null;
97 int num =
sizeof(global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB) + parameters.Q.X.Length + parameters.Q.Y.Length;
100 num += parameters.D.Length;
102 byte[]
array =
new byte[num];
103 fixed (
byte* ptr = &
array[0])
105 global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB* ptr2 = (global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB*)ptr;
107 ptr2->cbKey = parameters.Q.X.Length;
108 int offset =
sizeof(global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB);
109 global::Interop.BCrypt.Emit(
array, ref
offset, parameters.Q.X);
110 global::Interop.BCrypt.Emit(
array, ref
offset, parameters.Q.Y);
113 global::Interop.BCrypt.Emit(
array, ref
offset, parameters.D);
121 bool flag = parameters.D !=
null;
122 ECCurve curve = parameters.Curve;
123 int num =
sizeof(global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB) + curve.
Prime.Length + curve.
A.Length + curve.
B.Length + curve.
G.
X.Length + curve.
G.
Y.Length + curve.
Order.Length + curve.
Cofactor.Length + ((curve.
Seed !=
null) ? curve.Seed.Length : 0) + parameters.Q.X.Length + parameters.Q.Y.Length;
126 num += parameters.D.Length;
128 byte[]
array =
new byte[num];
129 fixed (
byte* ptr = &
array[0])
131 global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB* ptr2 = (global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB*)ptr;
133 ptr2->Magic = ((!flag) ? (ecdh ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC) : (ecdh ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC));
134 ptr2->cbCofactor = curve.
Cofactor.Length;
135 ptr2->cbFieldLength = parameters.Q.X.Length;
136 ptr2->cbSeed = ((curve.Seed !=
null) ? curve.
Seed.Length : 0);
137 ptr2->cbSubgroupOrder = curve.
Order.Length;
140 int offset =
sizeof(global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB);
142 global::Interop.BCrypt.Emit(
array, ref
offset, curve.
A);
143 global::Interop.BCrypt.Emit(
array, ref
offset, curve.
B);
148 if (curve.
Seed !=
null)
152 global::Interop.BCrypt.Emit(
array, ref
offset, parameters.Q.X);
153 global::Interop.BCrypt.Emit(
array, ref
offset, parameters.Q.Y);
156 global::Interop.BCrypt.Emit(
array, ref
offset, parameters.D);
164 global::Interop.BCrypt.KeyBlobMagicNumber magic = (global::Interop.BCrypt.KeyBlobMagicNumber)
BitConverter.
ToInt32(ecBlob, 0);
166 if (ecBlob.Length <
sizeof(global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB))
168 throw global::Interop.NCrypt.ErrorCode.E_FAIL.ToCryptographicException();
170 fixed (
byte* ptr = &ecBlob[0])
172 global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB* ptr2 = (global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB*)ptr;
173 int offset =
sizeof(global::Interop.BCrypt.BCRYPT_ECCKEY_BLOB);
176 X = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbKey),
177 Y = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbKey)
179 if (includePrivateParameters)
181 ecParams.D = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbKey);
188 global::Interop.BCrypt.KeyBlobMagicNumber magic = (global::Interop.BCrypt.KeyBlobMagicNumber)
BitConverter.
ToInt32(ecBlob, 0);
190 if (ecBlob.Length <
sizeof(global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB))
192 throw global::Interop.NCrypt.ErrorCode.E_FAIL.ToCryptographicException();
194 fixed (
byte* ptr = &ecBlob[0])
196 global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB* ptr2 = (global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB*)ptr;
200 int offset =
sizeof(global::Interop.BCrypt.BCRYPT_ECCFULLKEY_BLOB);
201 curve.Prime = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbFieldLength);
202 curve.A = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbFieldLength);
203 curve.B = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbFieldLength);
206 X = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbFieldLength),
207 Y = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbFieldLength)
209 curve.Order = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbSubgroupOrder);
210 curve.Cofactor = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbCofactor);
211 curve.Seed = ((ptr2->cbSeed == 0) ?
null : global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbSeed));
214 X = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbFieldLength),
215 Y = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbFieldLength)
217 if (includePrivateParameters)
219 ecParams.D = global::Interop.BCrypt.Consume(ecBlob, ref
offset, ptr2->cbSubgroupOrder);
221 ecParams.Curve = curve;
227 int num =
sizeof(global::Interop.BCrypt.BCRYPT_ECC_PARAMETER_HEADER) + curve.Prime.Length + curve.A.Length + curve.B.Length + curve.G.X.Length + curve.G.Y.Length + curve.Order.Length + curve.Cofactor.Length + ((curve.Seed !=
null) ? curve.Seed.Length : 0);
228 byte[]
array =
new byte[num];
229 fixed (
byte* ptr = &
array[0])
231 global::Interop.BCrypt.BCRYPT_ECC_PARAMETER_HEADER* ptr2 = (global::Interop.BCrypt.BCRYPT_ECC_PARAMETER_HEADER*)ptr;
233 ptr2->cbCofactor = curve.Cofactor.Length;
234 ptr2->cbFieldLength = curve.A.Length;
235 ptr2->cbSeed = ((curve.Seed !=
null) ? curve.Seed.Length : 0);
236 ptr2->cbSubgroupOrder = curve.Order.Length;
239 int offset =
sizeof(global::Interop.BCrypt.BCRYPT_ECC_PARAMETER_HEADER);
240 global::Interop.BCrypt.Emit(
array, ref
offset, curve.Prime);
241 global::Interop.BCrypt.Emit(
array, ref
offset, curve.A);
242 global::Interop.BCrypt.Emit(
array, ref
offset, curve.B);
243 global::Interop.BCrypt.Emit(
array, ref
offset, curve.G.X);
244 global::Interop.BCrypt.Emit(
array, ref
offset, curve.G.Y);
245 global::Interop.BCrypt.Emit(
array, ref
offset, curve.Order);
246 global::Interop.BCrypt.Emit(
array, ref
offset, curve.Cofactor);
247 if (curve.Seed !=
null)
249 global::Interop.BCrypt.Emit(
array, ref
offset, curve.Seed);
255 private static void CheckMagicValueOfKey(global::Interop.BCrypt.KeyBlobMagicNumber magic,
bool includePrivateParameters)
257 if (includePrivateParameters)
274 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P256_MAGIC:
275 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P256_MAGIC:
276 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P384_MAGIC:
277 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P384_MAGIC:
278 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P521_MAGIC:
279 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P521_MAGIC:
280 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC:
281 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC:
292 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P256_MAGIC:
293 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P256_MAGIC:
294 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P384_MAGIC:
295 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P384_MAGIC:
296 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P521_MAGIC:
297 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P521_MAGIC:
298 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC:
299 case global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC:
310 "ECDSA_P256" => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P256_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P256_MAGIC,
311 "ECDSA_P384" => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P384_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P384_MAGIC,
312 "ECDSA_P521" => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P521_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P521_MAGIC,
313 _ => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC,
321 "ECDH_P256" => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P256_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P256_MAGIC,
322 "ECDH_P384" => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P384_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P384_MAGIC,
323 "ECDH_P521" => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_P521_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_P521_MAGIC,
324 _ => includePrivateParameters ? global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC : global::Interop.BCrypt.KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC,
330 return (global::Interop.BCrypt.ECC_CURVE_TYPE_ENUM)
value;
340 global::Interop.NCrypt.ErrorCode errorCode;
344 global::Interop.BCrypt.BCryptBufferDesc structure =
default(global::Interop.BCrypt.BCryptBufferDesc);
345 global::Interop.BCrypt.BCryptBuffer structure2 =
default(global::Interop.BCrypt.BCryptBuffer);
352 structure2.cbBuffer = (curveName.Length + 1) * 2;
353 structure2.BufferType = global::Interop.BCrypt.CngBufferDescriptors.NCRYPTBUFFER_ECC_CURVE_NAME;
356 structure.cBuffers = 1;
357 structure.pBuffers = intPtr2;
358 structure.ulVersion = 0;
360 errorCode = global::Interop.NCrypt.NCryptImportKey(provider,
IntPtr.
Zero, blobType, intPtr, out phKey, ref
MemoryMarshal.GetReference(keyBlob), keyBlob.
Length, 0);
370 Exception ex = errorCode.ToCryptographicException();
371 if (errorCode == global::Interop.NCrypt.ErrorCode.NTE_INVALID_PARAMETER)
421 if (!name.HasValue ||
string.IsNullOrEmpty(name.Value.Name))
423 return global::Interop.BCrypt.ECC_CURVE_ALG_ID_ENUM.BCRYPT_NO_CURVE_GENERATION_ALG_ID;
425 global::Interop.Crypt32.CRYPT_OID_INFO cRYPT_OID_INFO = global::Interop.Crypt32.FindOidInfo(global::Interop.Crypt32.CryptOidInfoKeyType.CRYPT_OID_INFO_NAME_KEY, name.Value.Name,
OidGroup.HashAlgorithm, fallBackToAllGroups:
false);
426 if (cRYPT_OID_INFO.AlgId == -1)
430 return (global::Interop.BCrypt.ECC_CURVE_ALG_ID_ENUM)cRYPT_OID_INFO.AlgId;
435 global::Interop.Crypt32.CRYPT_OID_INFO cRYPT_OID_INFO = global::Interop.Crypt32.FindAlgIdOidInfo(hashId);
436 if (cRYPT_OID_INFO.AlgId == -1)
static int ToInt32(byte[] value, int startIndex)
static void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld)
static void FreeHGlobal(IntPtr hglobal)
static int SizeOf(object structure)
static IntPtr AllocHGlobal(int cb)
IntPtr DangerousGetHandle()
static string Cryptography_NotValidPrivateKey
static string Cryptography_UnknownHashAlgorithm
static string Cryptography_CurveNotSupported
static string Format(string resourceFormat, object p1)
static string Cryptography_NotValidPublicOrPrivateKey
static CngKey Import(ReadOnlySpan< byte > keyBlob, CngKeyBlobFormat format)
static SafeNCryptKeyHandle ImportKeyBlob(string blobType, ReadOnlySpan< byte > keyBlob, string curveName, SafeNCryptProviderHandle provider)
static string EcdhCurveNameToAlgorithm(string algorithm)
static ? HashAlgorithmName GetHashAlgorithmName(global::Interop.BCrypt.ECC_CURVE_ALG_ID_ENUM hashId)
static global::Interop.BCrypt.KeyBlobMagicNumber EcdsaCurveNameToMagicNumber(string name, bool includePrivateParameters)
static unsafe byte[] GetPrimeCurveParameterBlob(ref ECCurve curve)
static unsafe byte[] GetPrimeCurveBlob(ref ECParameters parameters, bool ecdh)
static CngKey ImportFullKeyBlob(byte[] ecBlob, bool includePrivateParameters)
static CngKey ImportKeyBlob(byte[] ecBlob, string curveName, bool includePrivateParameters)
static unsafe void ExportNamedCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
static global::Interop.BCrypt.KeyBlobMagicNumber EcdhCurveNameToMagicNumber(string name, bool includePrivateParameters)
static byte[] ExportKeyBlob(CngKey key, bool includePrivateParameters)
static bool IsMagicValueOfKeyPrivate(global::Interop.BCrypt.KeyBlobMagicNumber magic)
static string EcdsaCurveNameToAlgorithm(string algorithm)
static ECCurve.ECCurveType ConvertToCurveTypeEnum(global::Interop.BCrypt.ECC_CURVE_TYPE_ENUM value)
static global::Interop.BCrypt.ECC_CURVE_ALG_ID_ENUM GetHashAlgorithmId(HashAlgorithmName? name)
static void CheckMagicValueOfKey(global::Interop.BCrypt.KeyBlobMagicNumber magic, bool includePrivateParameters)
static bool IsMagicValueOfKeyPublic(global::Interop.BCrypt.KeyBlobMagicNumber magic)
static unsafe void FixupGenericBlob(byte[] blob)
static unsafe byte[] GetNamedCurveBlob(ref ECParameters parameters, bool ecdh)
static global::Interop.BCrypt.ECC_CURVE_TYPE_ENUM ConvertToCurveTypeEnum(ECCurve.ECCurveType value)
static byte[] ExportKeyBlob(CngKey key, bool includePrivateParameters, out CngKeyBlobFormat format, out string curveName)
static unsafe void ExportPrimeCurveParameters(ref ECParameters ecParams, byte[] ecBlob, bool includePrivateParameters)
static byte[] ExportFullKeyBlob(CngKey key, bool includePrivateParameters)
static readonly IntPtr Zero