Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
CngKey.cs
Go to the documentation of this file.
3using System.Text;
6
8
9public sealed class CngKey : IDisposable
10{
12
14
15 private static readonly byte[] s_pkcs12TripleDesOidBytes = Encoding.ASCII.GetBytes("1.2.840.113549.1.12.1.3\0");
16
18 {
19 get
20 {
21 string propertyAsString = _keyHandle.GetPropertyAsString("Algorithm Name", CngPropertyOptions.None);
22 return new CngAlgorithm(propertyAsString);
23 }
24 }
25
27 {
28 get
29 {
30 string propertyAsString = _keyHandle.GetPropertyAsString("Algorithm Group", CngPropertyOptions.None);
31 if (propertyAsString == null)
32 {
33 return null;
34 }
35 return new CngAlgorithmGroup(propertyAsString);
36 }
37 }
38
40 {
41 get
42 {
43 return (CngExportPolicies)_keyHandle.GetPropertyAsDword("Export Policy", CngPropertyOptions.None);
44 }
45 internal set
46 {
47 _keyHandle.SetExportPolicy(value);
48 }
49 }
50
52
53 public unsafe bool IsEphemeral
54 {
55 get
56 {
57 Unsafe.SkipInit(out byte b);
58 if (global::Interop.NCrypt.NCryptGetProperty(_keyHandle, "CLR IsEphemeral", &b, 1, out var pcbResult, CngPropertyOptions.CustomProperty) != 0)
59 {
60 return false;
61 }
62 if (pcbResult != 1)
63 {
64 return false;
65 }
66 if (b != 1)
67 {
68 return false;
69 }
70 return true;
71 }
72 private set
73 {
74 byte b = (byte)(value ? 1 : 0);
75 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptSetProperty(_keyHandle, "CLR IsEphemeral", &b, 1, CngPropertyOptions.CustomProperty);
76 if (errorCode != 0)
77 {
78 throw errorCode.ToCryptographicException();
79 }
80 }
81 }
82
83 public bool IsMachineKey
84 {
85 get
86 {
87 CngKeyOpenOptions propertyAsDword = (CngKeyOpenOptions)_keyHandle.GetPropertyAsDword("Key Type", CngPropertyOptions.None);
88 return (propertyAsDword & CngKeyOpenOptions.MachineKey) == CngKeyOpenOptions.MachineKey;
89 }
90 }
91
92 public string? KeyName
93 {
94 get
95 {
96 if (IsEphemeral)
97 {
98 return null;
99 }
100 return _keyHandle.GetPropertyAsString("Name", CngPropertyOptions.None);
101 }
102 }
103
104 public int KeySize
105 {
106 get
107 {
108 int result = 0;
109 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptGetIntProperty(_keyHandle, "PublicKeyLength", ref result);
110 if (errorCode != 0)
111 {
112 errorCode = global::Interop.NCrypt.NCryptGetIntProperty(_keyHandle, "Length", ref result);
113 }
114 if (errorCode != 0)
115 {
116 throw errorCode.ToCryptographicException();
117 }
118 return result;
119 }
120 }
121
122 public CngKeyUsages KeyUsage => (CngKeyUsages)_keyHandle.GetPropertyAsDword("Key Usage", CngPropertyOptions.None);
123
125 {
126 get
127 {
128 return _keyHandle.GetPropertyAsIntPtr("HWND Handle", CngPropertyOptions.None);
129 }
130 set
131 {
132 global::Interop.NCrypt.NCryptSetProperty(_keyHandle, "HWND Handle", &value, IntPtr.Size, CngPropertyOptions.None);
133 }
134 }
135
136 public CngProvider? Provider
137 {
138 get
139 {
140 string propertyAsString = _providerHandle.GetPropertyAsString("Name", CngPropertyOptions.None);
141 if (propertyAsString == null)
142 {
143 return null;
144 }
145 return new CngProvider(propertyAsString);
146 }
147 }
148
150
151 public unsafe CngUIPolicy UIPolicy
152 {
153 get
154 {
155 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptGetProperty(_keyHandle, "UI Policy", null, 0, out var pcbResult, CngPropertyOptions.None);
156 if (errorCode != 0 && errorCode != global::Interop.NCrypt.ErrorCode.NTE_NOT_FOUND)
157 {
158 throw errorCode.ToCryptographicException();
159 }
160 CngUIProtectionLevels protectionLevel;
161 string friendlyName;
162 string description;
163 string creationTitle;
164 if (errorCode != 0 || pcbResult == 0)
165 {
166 protectionLevel = CngUIProtectionLevels.None;
167 friendlyName = null;
168 description = null;
169 creationTitle = null;
170 }
171 else
172 {
173 if (pcbResult < sizeof(global::Interop.NCrypt.NCRYPT_UI_POLICY))
174 {
175 throw global::Interop.NCrypt.ErrorCode.E_FAIL.ToCryptographicException();
176 }
177 byte[] array = new byte[pcbResult];
178 fixed (byte* ptr = &array[0])
179 {
180 errorCode = global::Interop.NCrypt.NCryptGetProperty(_keyHandle, "UI Policy", ptr, array.Length, out pcbResult, CngPropertyOptions.None);
181 if (errorCode != 0)
182 {
183 throw errorCode.ToCryptographicException();
184 }
185 global::Interop.NCrypt.NCRYPT_UI_POLICY* ptr2 = (global::Interop.NCrypt.NCRYPT_UI_POLICY*)ptr;
186 protectionLevel = ptr2->dwFlags;
187 friendlyName = Marshal.PtrToStringUni(ptr2->pszFriendlyName);
188 description = Marshal.PtrToStringUni(ptr2->pszDescription);
189 creationTitle = Marshal.PtrToStringUni(ptr2->pszCreationTitle);
190 }
191 }
192 string propertyAsString = _keyHandle.GetPropertyAsString("Use Context", CngPropertyOptions.None);
193 return new CngUIPolicy(protectionLevel, friendlyName, description, propertyAsString, creationTitle);
194 }
195 }
196
197 public string? UniqueName
198 {
199 get
200 {
201 if (IsEphemeral)
202 {
203 return null;
204 }
205 return _keyHandle.GetPropertyAsString("Unique Name", CngPropertyOptions.None);
206 }
207 }
208
209 private CngKey(SafeNCryptProviderHandle providerHandle, SafeNCryptKeyHandle keyHandle)
210 {
211 _providerHandle = providerHandle;
212 _keyHandle = keyHandle;
213 }
214
215 public void Dispose()
216 {
217 if (_providerHandle != null)
218 {
220 }
221 if (_keyHandle != null)
222 {
224 }
225 }
226
228 {
229 if (name == null)
230 {
231 throw new ArgumentNullException("name");
232 }
233 byte[] array = _keyHandle.GetProperty(name, options);
234 if (array == null)
235 {
236 throw global::Interop.NCrypt.ErrorCode.NTE_NOT_FOUND.ToCryptographicException();
237 }
238 if (array.Length == 0)
239 {
240 array = null;
241 }
242 return new CngProperty(name, array, options);
243 }
244
245 public unsafe bool HasProperty(string name, CngPropertyOptions options)
246 {
247 if (name == null)
248 {
249 throw new ArgumentNullException("name");
250 }
251 int pcbResult;
252 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptGetProperty(_keyHandle, name, null, 0, out pcbResult, options);
253 return errorCode switch
254 {
255 global::Interop.NCrypt.ErrorCode.NTE_NOT_FOUND => false,
256 global::Interop.NCrypt.ErrorCode.ERROR_SUCCESS => true,
257 _ => throw errorCode.ToCryptographicException(),
258 };
259 }
260
261 public unsafe void SetProperty(CngProperty property)
262 {
263 byte[] valueWithoutCopying = property.GetValueWithoutCopying();
264 if (valueWithoutCopying == null)
265 {
266 throw global::Interop.NCrypt.ErrorCode.NTE_INVALID_PARAMETER.ToCryptographicException();
267 }
268 fixed (byte* pbInput = valueWithoutCopying.MapZeroLengthArrayToNonNullPointer())
269 {
270 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptSetProperty(_keyHandle, property.Name, pbInput, valueWithoutCopying.Length, property.Options);
271 if (errorCode != 0)
272 {
273 throw errorCode.ToCryptographicException();
274 }
275 }
276 }
277
278 public static CngKey Create(CngAlgorithm algorithm)
279 {
280 return Create(algorithm, null);
281 }
282
283 public static CngKey Create(CngAlgorithm algorithm, string? keyName)
284 {
285 return Create(algorithm, keyName, null);
286 }
287
288 public static CngKey Create(CngAlgorithm algorithm, string? keyName, CngKeyCreationParameters? creationParameters)
289 {
290 if (algorithm == null)
291 {
292 throw new ArgumentNullException("algorithm");
293 }
294 if (creationParameters == null)
295 {
296 creationParameters = new CngKeyCreationParameters();
297 }
298 SafeNCryptProviderHandle safeNCryptProviderHandle = creationParameters.Provider.OpenStorageProvider();
299 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptCreatePersistedKey(safeNCryptProviderHandle, out var phKey, algorithm.Algorithm, keyName, 0, creationParameters.KeyCreationOptions);
300 if (errorCode != 0)
301 {
302 throw errorCode.ToCryptographicException();
303 }
304 InitializeKeyProperties(phKey, creationParameters);
305 errorCode = global::Interop.NCrypt.NCryptFinalizeKey(phKey, 0);
306 if (errorCode != 0)
307 {
308 throw errorCode.ToCryptographicException();
309 }
310 CngKey cngKey = new CngKey(safeNCryptProviderHandle, phKey);
311 if (keyName == null)
312 {
313 cngKey.IsEphemeral = true;
314 }
315 return cngKey;
316 }
317
318 private unsafe static void InitializeKeyProperties(SafeNCryptKeyHandle keyHandle, CngKeyCreationParameters creationParameters)
319 {
320 if (creationParameters.ExportPolicy.HasValue)
321 {
322 CngExportPolicies value = creationParameters.ExportPolicy.Value;
323 keyHandle.SetExportPolicy(value);
324 }
325 if (creationParameters.KeyUsage.HasValue)
326 {
327 CngKeyUsages value2 = creationParameters.KeyUsage.Value;
328 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptSetProperty(keyHandle, "Key Usage", &value2, 4, CngPropertyOptions.Persist);
329 if (errorCode != 0)
330 {
331 throw errorCode.ToCryptographicException();
332 }
333 }
334 if (creationParameters.ParentWindowHandle != IntPtr.Zero)
335 {
336 IntPtr parentWindowHandle = creationParameters.ParentWindowHandle;
337 global::Interop.NCrypt.ErrorCode errorCode2 = global::Interop.NCrypt.NCryptSetProperty(keyHandle, "HWND Handle", &parentWindowHandle, sizeof(IntPtr), CngPropertyOptions.None);
338 if (errorCode2 != 0)
339 {
340 throw errorCode2.ToCryptographicException();
341 }
342 }
343 CngUIPolicy uIPolicy = creationParameters.UIPolicy;
344 if (uIPolicy != null)
345 {
346 InitializeKeyUiPolicyProperties(keyHandle, uIPolicy);
347 }
348 foreach (CngProperty parameter in creationParameters.Parameters)
349 {
350 byte[] valueWithoutCopying = parameter.GetValueWithoutCopying();
351 int cbInput = ((valueWithoutCopying != null) ? valueWithoutCopying.Length : 0);
352 fixed (byte* pbInput = valueWithoutCopying.MapZeroLengthArrayToNonNullPointer())
353 {
354 global::Interop.NCrypt.ErrorCode errorCode3 = global::Interop.NCrypt.NCryptSetProperty(keyHandle, parameter.Name, pbInput, cbInput, parameter.Options);
355 if (errorCode3 != 0)
356 {
357 throw errorCode3.ToCryptographicException();
358 }
359 }
360 }
361 }
362
363 private unsafe static void InitializeKeyUiPolicyProperties(SafeNCryptKeyHandle keyHandle, CngUIPolicy uiPolicy)
364 {
365 //The blocks IL_0031, IL_0039, IL_004a, IL_00b2 are reachable both inside and outside the pinned region starting at IL_002c. ILSpy has duplicated these blocks in order to place them both within and outside the `fixed` statement.
366 fixed (char* value3 = uiPolicy.CreationTitle)
367 {
368 string? friendlyName = uiPolicy.FriendlyName;
369 char* intPtr;
370 string? description;
371 global::Interop.NCrypt.NCRYPT_UI_POLICY nCRYPT_UI_POLICY2;
372 if (friendlyName == null)
373 {
374 char* value;
375 intPtr = (value = null);
376 description = uiPolicy.Description;
377 fixed (char* ptr = description)
378 {
379 char* value2 = ptr;
380 global::Interop.NCrypt.NCRYPT_UI_POLICY nCRYPT_UI_POLICY = default(global::Interop.NCrypt.NCRYPT_UI_POLICY);
381 nCRYPT_UI_POLICY.dwVersion = 1;
382 nCRYPT_UI_POLICY.dwFlags = uiPolicy.ProtectionLevel;
383 nCRYPT_UI_POLICY.pszCreationTitle = new IntPtr(value3);
384 nCRYPT_UI_POLICY.pszFriendlyName = new IntPtr(value);
385 nCRYPT_UI_POLICY.pszDescription = new IntPtr(value2);
386 nCRYPT_UI_POLICY2 = nCRYPT_UI_POLICY;
387 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptSetProperty(keyHandle, "UI Policy", &nCRYPT_UI_POLICY2, sizeof(global::Interop.NCrypt.NCRYPT_UI_POLICY), CngPropertyOptions.Persist);
388 if (errorCode != 0)
389 {
390 throw errorCode.ToCryptographicException();
391 }
392 }
393 }
394 else
395 {
396 fixed (char* ptr2 = &friendlyName.GetPinnableReference())
397 {
398 char* value;
399 intPtr = (value = ptr2);
400 description = uiPolicy.Description;
401 fixed (char* ptr = description)
402 {
403 char* value2 = ptr;
404 global::Interop.NCrypt.NCRYPT_UI_POLICY nCRYPT_UI_POLICY = default(global::Interop.NCrypt.NCRYPT_UI_POLICY);
405 nCRYPT_UI_POLICY.dwVersion = 1;
406 nCRYPT_UI_POLICY.dwFlags = uiPolicy.ProtectionLevel;
407 nCRYPT_UI_POLICY.pszCreationTitle = new IntPtr(value3);
408 nCRYPT_UI_POLICY.pszFriendlyName = new IntPtr(value);
409 nCRYPT_UI_POLICY.pszDescription = new IntPtr(value2);
410 nCRYPT_UI_POLICY2 = nCRYPT_UI_POLICY;
411 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptSetProperty(keyHandle, "UI Policy", &nCRYPT_UI_POLICY2, sizeof(global::Interop.NCrypt.NCRYPT_UI_POLICY), CngPropertyOptions.Persist);
412 if (errorCode != 0)
413 {
414 throw errorCode.ToCryptographicException();
415 }
416 }
417 }
418 }
419 }
420 string useContext = uiPolicy.UseContext;
421 if (useContext == null)
422 {
423 return;
424 }
425 int cbInput = checked((useContext.Length + 1) * 2);
426 fixed (char* pbInput = useContext)
427 {
428 global::Interop.NCrypt.ErrorCode errorCode2 = global::Interop.NCrypt.NCryptSetProperty(keyHandle, "Use Context", pbInput, cbInput, CngPropertyOptions.Persist);
429 if (errorCode2 != 0)
430 {
431 throw errorCode2.ToCryptographicException();
432 }
433 }
434 }
435
436 internal bool IsECNamedCurve()
437 {
439 }
440
441 internal static bool IsECNamedCurve(string algorithm)
442 {
443 if (!(algorithm == CngAlgorithm.ECDiffieHellman.Algorithm))
444 {
445 return algorithm == CngAlgorithm.ECDsa.Algorithm;
446 }
447 return true;
448 }
449
450 internal string GetCurveName(out string oidValue)
451 {
452 if (IsECNamedCurve())
453 {
454 oidValue = null;
455 return _keyHandle.GetPropertyAsString("ECCCurveName", CngPropertyOptions.None);
456 }
457 return GetECSpecificCurveName(out oidValue);
458 }
459
460 private string GetECSpecificCurveName(out string oidValue)
461 {
462 string algorithm = Algorithm.Algorithm;
463 if (algorithm == CngAlgorithm.ECDiffieHellmanP256.Algorithm || algorithm == CngAlgorithm.ECDsaP256.Algorithm)
464 {
465 oidValue = "1.2.840.10045.3.1.7";
466 return "nistP256";
467 }
468 if (algorithm == CngAlgorithm.ECDiffieHellmanP384.Algorithm || algorithm == CngAlgorithm.ECDsaP384.Algorithm)
469 {
470 oidValue = "1.3.132.0.34";
471 return "nistP384";
472 }
473 if (algorithm == CngAlgorithm.ECDiffieHellmanP521.Algorithm || algorithm == CngAlgorithm.ECDsaP521.Algorithm)
474 {
475 oidValue = "1.3.132.0.35";
476 return "nistP521";
477 }
479 }
480
482 {
483 string friendlyName = curve.Oid.FriendlyName;
484 byte[] array = new byte[(friendlyName.Length + 1) * 2];
485 Encoding.Unicode.GetBytes(friendlyName, 0, friendlyName.Length, array, 0);
486 return new CngProperty("ECCCurveName", array, CngPropertyOptions.None);
487 }
488
489 internal static CngAlgorithm EcdsaCurveNameToAlgorithm(string name)
490 {
491 switch (name)
492 {
493 case "nistP256":
494 case "ECDSA_P256":
495 return CngAlgorithm.ECDsaP256;
496 case "nistP384":
497 case "ECDSA_P384":
498 return CngAlgorithm.ECDsaP384;
499 case "nistP521":
500 case "ECDSA_P521":
501 return CngAlgorithm.ECDsaP521;
502 default:
503 return CngAlgorithm.ECDsa;
504 }
505 }
506
507 internal static CngAlgorithm EcdhCurveNameToAlgorithm(string name)
508 {
509 switch (name)
510 {
511 case "nistP256":
512 case "ECDH_P256":
514 case "nistP384":
515 case "ECDH_P384":
517 case "nistP521":
518 case "ECDH_P521":
520 default:
522 }
523 }
524
526 {
528 }
529
530 public static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format)
531 {
533 }
534
535 internal static CngKey Import(byte[] keyBlob, string curveName, CngKeyBlobFormat format)
536 {
538 }
539
540 public static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider)
541 {
542 return Import(keyBlob, null, format, provider);
543 }
544
549
550 internal unsafe static CngKey ImportEncryptedPkcs8(ReadOnlySpan<byte> keyBlob, ReadOnlySpan<char> password, CngProvider provider)
551 {
552 SafeNCryptProviderHandle safeNCryptProviderHandle = provider.OpenStorageProvider();
555 {
556 global::Interop.NCrypt.NCryptBuffer* ptr = stackalloc global::Interop.NCrypt.NCryptBuffer[1];
557 *ptr = new global::Interop.NCrypt.NCryptBuffer
558 {
559 BufferType = global::Interop.NCrypt.BufferType.PkcsSecret,
560 cbBuffer = checked(2 * (password.Length + 1)),
561 pvBuffer = safeUnicodeStringHandle.DangerousGetHandle()
562 };
563 if (ptr->pvBuffer == IntPtr.Zero)
564 {
565 ptr->cbBuffer = 0;
566 }
567 global::Interop.NCrypt.NCryptBufferDesc nCryptBufferDesc = default(global::Interop.NCrypt.NCryptBufferDesc);
568 nCryptBufferDesc.cBuffers = 1;
569 nCryptBufferDesc.pBuffers = (IntPtr)ptr;
570 nCryptBufferDesc.ulVersion = 0;
571 global::Interop.NCrypt.NCryptBufferDesc pParameterList = nCryptBufferDesc;
572 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptImportKey(safeNCryptProviderHandle, IntPtr.Zero, "PKCS8_PRIVATEKEY", ref pParameterList, out phKey, ref MemoryMarshal.GetReference(keyBlob), keyBlob.Length, 0);
573 if (errorCode != 0)
574 {
575 phKey.Dispose();
576 throw errorCode.ToCryptographicException();
577 }
578 }
579 CngKey cngKey = new CngKey(safeNCryptProviderHandle, phKey);
580 cngKey.IsEphemeral = true;
581 return cngKey;
582 }
583
584 internal static CngKey Import(byte[] keyBlob, string curveName, CngKeyBlobFormat format, CngProvider provider)
585 {
586 if (keyBlob == null)
587 {
588 throw new ArgumentNullException("keyBlob");
589 }
590 return Import(new ReadOnlySpan<byte>(keyBlob), curveName, format, provider);
591 }
592
593 internal static CngKey Import(ReadOnlySpan<byte> keyBlob, string curveName, CngKeyBlobFormat format, CngProvider provider)
594 {
595 if (format == null)
596 {
597 throw new ArgumentNullException("format");
598 }
599 if (provider == null)
600 {
601 throw new ArgumentNullException("provider");
602 }
603 SafeNCryptProviderHandle safeNCryptProviderHandle = provider.OpenStorageProvider();
604 SafeNCryptKeyHandle phKey = null;
605 if (curveName == null)
606 {
607 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptImportKey(safeNCryptProviderHandle, IntPtr.Zero, format.Format, IntPtr.Zero, out phKey, ref MemoryMarshal.GetReference(keyBlob), keyBlob.Length, 0);
608 if (errorCode != 0)
609 {
610 throw errorCode.ToCryptographicException();
611 }
612 }
613 else
614 {
615 phKey = System.Security.Cryptography.ECCng.ImportKeyBlob(format.Format, keyBlob, curveName, safeNCryptProviderHandle);
616 }
617 CngKey cngKey = new CngKey(safeNCryptProviderHandle, phKey);
618 cngKey.IsEphemeral = format != CngKeyBlobFormat.OpaqueTransportBlob;
619 return cngKey;
620 }
621
623 {
624 if (format == null)
625 {
626 throw new ArgumentNullException("format");
627 }
628 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, format.Format, IntPtr.Zero, null, 0, out var pcbResult, 0);
629 if (errorCode != 0)
630 {
631 throw errorCode.ToCryptographicException();
632 }
633 byte[] array = new byte[pcbResult];
634 errorCode = global::Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, format.Format, IntPtr.Zero, array, array.Length, out pcbResult, 0);
635 if (errorCode != 0)
636 {
637 throw errorCode.ToCryptographicException();
638 }
639 Array.Resize(ref array, pcbResult);
640 return array;
641 }
642
643 internal bool TryExportKeyBlob(string blobType, Span<byte> destination, out int bytesWritten)
644 {
645 Span<byte> span = default(Span<byte>);
646 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, blobType, IntPtr.Zero, ref MemoryMarshal.GetReference(span), span.Length, out var pcbResult, 0);
647 if (errorCode != 0)
648 {
649 throw errorCode.ToCryptographicException();
650 }
651 if (pcbResult > destination.Length)
652 {
653 bytesWritten = 0;
654 return false;
655 }
656 errorCode = global::Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, blobType, IntPtr.Zero, ref MemoryMarshal.GetReference(destination), destination.Length, out pcbResult, 0);
657 if (errorCode != 0)
658 {
659 throw errorCode.ToCryptographicException();
660 }
661 bytesWritten = pcbResult;
662 return true;
663 }
664
665 internal byte[] ExportPkcs8KeyBlob(ReadOnlySpan<char> password, int kdfCount)
666 {
667 int bytesWritten;
668 byte[] allocated;
669 bool flag = ExportPkcs8KeyBlob(allocate: true, _keyHandle, password, kdfCount, Span<byte>.Empty, out bytesWritten, out allocated);
670 return allocated;
671 }
672
673 internal bool TryExportPkcs8KeyBlob(ReadOnlySpan<char> password, int kdfCount, Span<byte> destination, out int bytesWritten)
674 {
675 byte[] allocated;
676 return ExportPkcs8KeyBlob(allocate: false, _keyHandle, password, kdfCount, destination, out bytesWritten, out allocated);
677 }
678
679 internal unsafe static bool ExportPkcs8KeyBlob(bool allocate, SafeNCryptKeyHandle keyHandle, ReadOnlySpan<char> password, int kdfCount, Span<byte> destination, out int bytesWritten, out byte[] allocated)
680 {
682 fixed (byte* ptr2 = s_pkcs12TripleDesOidBytes)
683 {
684 global::Interop.NCrypt.NCryptBuffer* ptr = stackalloc global::Interop.NCrypt.NCryptBuffer[3];
685 global::Interop.NCrypt.PBE_PARAMS pBE_PARAMS = default(global::Interop.NCrypt.PBE_PARAMS);
686 Span<byte> data = new Span<byte>(pBE_PARAMS.rgbSalt, 8);
688 pBE_PARAMS.Params.cbSalt = data.Length;
689 pBE_PARAMS.Params.iIterations = kdfCount;
690 *ptr = new global::Interop.NCrypt.NCryptBuffer
691 {
692 BufferType = global::Interop.NCrypt.BufferType.PkcsSecret,
693 cbBuffer = checked(2 * (password.Length + 1)),
694 pvBuffer = safeUnicodeStringHandle.DangerousGetHandle()
695 };
696 if (ptr->pvBuffer == IntPtr.Zero)
697 {
698 ptr->cbBuffer = 0;
699 }
700 ptr[1] = new global::Interop.NCrypt.NCryptBuffer
701 {
702 BufferType = global::Interop.NCrypt.BufferType.PkcsAlgOid,
703 cbBuffer = s_pkcs12TripleDesOidBytes.Length,
704 pvBuffer = (IntPtr)ptr2
705 };
706 ptr[2] = new global::Interop.NCrypt.NCryptBuffer
707 {
708 BufferType = global::Interop.NCrypt.BufferType.PkcsAlgParam,
709 cbBuffer = sizeof(global::Interop.NCrypt.PBE_PARAMS),
710 pvBuffer = (IntPtr)(&pBE_PARAMS)
711 };
712 global::Interop.NCrypt.NCryptBufferDesc nCryptBufferDesc = default(global::Interop.NCrypt.NCryptBufferDesc);
713 nCryptBufferDesc.cBuffers = 3;
714 nCryptBufferDesc.pBuffers = (IntPtr)ptr;
715 nCryptBufferDesc.ulVersion = 0;
716 global::Interop.NCrypt.NCryptBufferDesc pParameterList = nCryptBufferDesc;
717 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptExportKey(keyHandle, IntPtr.Zero, "PKCS8_PRIVATEKEY", ref pParameterList, ref MemoryMarshal.GetReference(default(Span<byte>)), 0, out var pcbResult, 0);
718 if (errorCode != 0)
719 {
720 throw errorCode.ToCryptographicException();
721 }
722 allocated = null;
723 if (allocate)
724 {
725 allocated = new byte[pcbResult];
726 destination = allocated;
727 }
728 else if (pcbResult > destination.Length)
729 {
730 bytesWritten = 0;
731 return false;
732 }
733 errorCode = global::Interop.NCrypt.NCryptExportKey(keyHandle, IntPtr.Zero, "PKCS8_PRIVATEKEY", ref pParameterList, ref MemoryMarshal.GetReference(destination), destination.Length, out pcbResult, 0);
734 if (errorCode != 0)
735 {
736 throw errorCode.ToCryptographicException();
737 }
738 if (allocate && pcbResult != destination.Length)
739 {
740 byte[] array = new byte[pcbResult];
741 destination.Slice(0, pcbResult).CopyTo(array);
742 Array.Clear(allocated, 0, pcbResult);
743 allocated = array;
744 }
745 bytesWritten = pcbResult;
746 return true;
747 }
748 }
749
750 public void Delete()
751 {
752 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptDeleteKey(_keyHandle, 0);
753 if (errorCode != 0)
754 {
755 throw errorCode.ToCryptographicException();
756 }
758 Dispose();
759 }
760
761 public static bool Exists(string keyName)
762 {
764 }
765
766 public static bool Exists(string keyName, CngProvider provider)
767 {
768 return Exists(keyName, provider, CngKeyOpenOptions.None);
769 }
770
771 public static bool Exists(string keyName, CngProvider provider, CngKeyOpenOptions options)
772 {
773 if (keyName == null)
774 {
775 throw new ArgumentNullException("keyName");
776 }
777 if (provider == null)
778 {
779 throw new ArgumentNullException("provider");
780 }
781 using SafeNCryptProviderHandle hProvider = provider.OpenStorageProvider();
782 SafeNCryptKeyHandle phKey = null;
783 try
784 {
785 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptOpenKey(hProvider, out phKey, keyName, 0, options);
786 return errorCode switch
787 {
788 global::Interop.NCrypt.ErrorCode.NTE_BAD_KEYSET => false,
789 global::Interop.NCrypt.ErrorCode.ERROR_SUCCESS => true,
790 _ => throw errorCode.ToCryptographicException(),
791 };
792 }
793 finally
794 {
795 phKey?.Dispose();
796 }
797 }
798
799 public static CngKey Open(string keyName)
800 {
802 }
803
804 public static CngKey Open(string keyName, CngProvider provider)
805 {
806 return Open(keyName, provider, CngKeyOpenOptions.None);
807 }
808
809 public static CngKey Open(string keyName, CngProvider provider, CngKeyOpenOptions openOptions)
810 {
811 if (keyName == null)
812 {
813 throw new ArgumentNullException("keyName");
814 }
815 if (provider == null)
816 {
817 throw new ArgumentNullException("provider");
818 }
819 SafeNCryptProviderHandle safeNCryptProviderHandle = provider.OpenStorageProvider();
821 global::Interop.NCrypt.ErrorCode errorCode = global::Interop.NCrypt.NCryptOpenKey(safeNCryptProviderHandle, out phKey, keyName, 0, openOptions);
822 if (errorCode != 0)
823 {
824 throw errorCode.ToCryptographicException();
825 }
826 return new CngKey(safeNCryptProviderHandle, phKey);
827 }
828
829 public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
830 {
831 if (keyHandle == null)
832 {
833 throw new ArgumentNullException("keyHandle");
834 }
835 if (keyHandle.IsClosed || keyHandle.IsInvalid)
836 {
838 }
839 SafeNCryptKeyHandle keyHandle2 = keyHandle.Duplicate();
840 SafeNCryptProviderHandle safeNCryptProviderHandle = new SafeNCryptProviderHandle();
841 IntPtr propertyAsIntPtr = keyHandle.GetPropertyAsIntPtr("Provider Handle", CngPropertyOptions.None);
842 safeNCryptProviderHandle.SetHandleValue(propertyAsIntPtr);
843 CngKey cngKey = null;
844 try
845 {
846 cngKey = new CngKey(safeNCryptProviderHandle, keyHandle2);
847 bool flag = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey;
848 if (!cngKey.IsEphemeral && flag)
849 {
850 cngKey.IsEphemeral = true;
851 }
852 else if (cngKey.IsEphemeral && !flag)
853 {
855 }
856 }
857 catch
858 {
859 cngKey?.Dispose();
860 throw;
861 }
862 return cngKey;
863 }
864}
static unsafe void Clear(Array array)
Definition Array.cs:755
static unsafe? string PtrToStringUni(IntPtr ptr)
Definition Marshal.cs:652
static string Cryptography_CurveNotSupported
Definition SR.cs:64
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag
Definition SR.cs:90
static string Cryptography_OpenInvalidHandle
Definition SR.cs:92
Definition SR.cs:7
static CngKey ImportEncryptedPkcs8(ReadOnlySpan< byte > keyBlob, ReadOnlySpan< char > password)
Definition CngKey.cs:545
static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
Definition CngKey.cs:829
static unsafe CngKey ImportEncryptedPkcs8(ReadOnlySpan< byte > keyBlob, ReadOnlySpan< char > password, CngProvider provider)
Definition CngKey.cs:550
bool TryExportKeyBlob(string blobType, Span< byte > destination, out int bytesWritten)
Definition CngKey.cs:643
CngProperty GetProperty(string name, CngPropertyOptions options)
Definition CngKey.cs:227
CngKey(SafeNCryptProviderHandle providerHandle, SafeNCryptKeyHandle keyHandle)
Definition CngKey.cs:209
static CngAlgorithm EcdsaCurveNameToAlgorithm(string name)
Definition CngKey.cs:489
unsafe bool HasProperty(string name, CngPropertyOptions options)
Definition CngKey.cs:245
static CngAlgorithm EcdhCurveNameToAlgorithm(string name)
Definition CngKey.cs:507
static CngKey Create(CngAlgorithm algorithm, string? keyName, CngKeyCreationParameters? creationParameters)
Definition CngKey.cs:288
static CngKey Create(CngAlgorithm algorithm)
Definition CngKey.cs:278
static CngKey Open(string keyName, CngProvider provider, CngKeyOpenOptions openOptions)
Definition CngKey.cs:809
static bool Exists(string keyName)
Definition CngKey.cs:761
static bool Exists(string keyName, CngProvider provider)
Definition CngKey.cs:766
string GetECSpecificCurveName(out string oidValue)
Definition CngKey.cs:460
static bool Exists(string keyName, CngProvider provider, CngKeyOpenOptions options)
Definition CngKey.cs:771
static bool IsECNamedCurve(string algorithm)
Definition CngKey.cs:441
static CngKey Open(string keyName, CngProvider provider)
Definition CngKey.cs:804
unsafe CngUIPolicy UIPolicy
Definition CngKey.cs:152
static CngProperty GetPropertyFromNamedCurve(ECCurve curve)
Definition CngKey.cs:481
static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format)
Definition CngKey.cs:530
readonly SafeNCryptProviderHandle _providerHandle
Definition CngKey.cs:13
static CngKey Open(string keyName)
Definition CngKey.cs:799
static CngKey Import(ReadOnlySpan< byte > keyBlob, string curveName, CngKeyBlobFormat format, CngProvider provider)
Definition CngKey.cs:593
byte[] Export(CngKeyBlobFormat format)
Definition CngKey.cs:622
static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider)
Definition CngKey.cs:540
SafeNCryptProviderHandle ProviderHandle
Definition CngKey.cs:149
static unsafe bool ExportPkcs8KeyBlob(bool allocate, SafeNCryptKeyHandle keyHandle, ReadOnlySpan< char > password, int kdfCount, Span< byte > destination, out int bytesWritten, out byte[] allocated)
Definition CngKey.cs:679
unsafe void SetProperty(CngProperty property)
Definition CngKey.cs:261
static readonly byte[] s_pkcs12TripleDesOidBytes
Definition CngKey.cs:15
static CngKey Create(CngAlgorithm algorithm, string? keyName)
Definition CngKey.cs:283
static unsafe void InitializeKeyProperties(SafeNCryptKeyHandle keyHandle, CngKeyCreationParameters creationParameters)
Definition CngKey.cs:318
string GetCurveName(out string oidValue)
Definition CngKey.cs:450
byte[] ExportPkcs8KeyBlob(ReadOnlySpan< char > password, int kdfCount)
Definition CngKey.cs:665
static CngKey Import(ReadOnlySpan< byte > keyBlob, CngKeyBlobFormat format)
Definition CngKey.cs:525
CngExportPolicies ExportPolicy
Definition CngKey.cs:40
bool TryExportPkcs8KeyBlob(ReadOnlySpan< char > password, int kdfCount, Span< byte > destination, out int bytesWritten)
Definition CngKey.cs:673
static CngKey Import(byte[] keyBlob, string curveName, CngKeyBlobFormat format, CngProvider provider)
Definition CngKey.cs:584
static unsafe void InitializeKeyUiPolicyProperties(SafeNCryptKeyHandle keyHandle, CngUIPolicy uiPolicy)
Definition CngKey.cs:363
readonly SafeNCryptKeyHandle _keyHandle
Definition CngKey.cs:11
SafeNCryptKeyHandle Handle
Definition CngKey.cs:51
static CngKey Import(byte[] keyBlob, string curveName, CngKeyBlobFormat format)
Definition CngKey.cs:535
CngAlgorithmGroup? AlgorithmGroup
Definition CngKey.cs:27
static CngProvider MicrosoftSoftwareKeyStorageProvider
CngUIProtectionLevels ProtectionLevel
Definition CngUIPolicy.cs:5
static SafeNCryptKeyHandle ImportKeyBlob(string blobType, ReadOnlySpan< byte > keyBlob, string curveName, SafeNCryptProviderHandle provider)
Definition ECCng.cs:307
static Encoding Unicode
Definition Encoding.cs:519
static Encoding ASCII
Definition Encoding.cs:511
static int Size
Definition IntPtr.cs:21
static readonly IntPtr Zero
Definition IntPtr.cs:18
static Span< T > Empty
Definition Span.cs:87
int Length
Definition Span.cs:70