1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.IO; 6 using Internal.Cryptography; 7 8 namespace System.Security.Cryptography 9 { 10 public sealed partial class ECDsaCng : ECDsa 11 { 12 private CngAlgorithmCore _core; 13 private CngAlgorithm _hashAlgorithm; 14 15 /// <summary> 16 /// Hash algorithm to use when generating a signature over arbitrary data 17 /// </summary> 18 public CngAlgorithm HashAlgorithm 19 { 20 get 21 { 22 return _hashAlgorithm; 23 } 24 set 25 { 26 _hashAlgorithm = value ?? throw new ArgumentNullException(nameof(value)); 27 } 28 } 29 30 /// <summary> 31 /// Creates a new ECDsaCng object that will use the specified key. The key's 32 /// <see cref="CngKey.AlgorithmGroup" /> must be ECDsa. This constructor 33 /// creates a copy of the key. Hence, the caller can safely dispose of the 34 /// passed in key and continue using the ECDsaCng object. 35 /// </summary> 36 /// <param name="key">Key to use for ECDsa operations</param> 37 /// <exception cref="ArgumentException">if <paramref name="key" /> is not an ECDsa key</exception> 38 /// <exception cref="ArgumentNullException">if <paramref name="key" /> is null.</exception> ECDsaCng(CngKey key)39 public ECDsaCng(CngKey key) 40 { 41 if (key == null) 42 throw new ArgumentNullException(nameof(key)); 43 44 if (!IsEccAlgorithmGroup(key.AlgorithmGroup)) 45 throw new ArgumentException(SR.Cryptography_ArgECDsaRequiresECDsaKey, nameof(key)); 46 47 Key = CngAlgorithmCore.Duplicate(key); 48 } 49 Dispose(bool disposing)50 protected override void Dispose(bool disposing) 51 { 52 _core.Dispose(); 53 } 54 DisposeKey()55 private void DisposeKey() 56 { 57 _core.DisposeKey(); 58 } 59 IsEccAlgorithmGroup(CngAlgorithmGroup algorithmGroup)60 private static bool IsEccAlgorithmGroup(CngAlgorithmGroup algorithmGroup) 61 { 62 // Sometimes, when reading from certificates, ECDSA keys get identified as ECDH. 63 // Windows allows the ECDH keys to perform both key exchange (ECDH) and signing (ECDSA), 64 // so either value is acceptable for the ECDSA wrapper object. 65 // 66 // It is worth noting, however, that ECDSA-identified keys cannot be used for key exchange (ECDH) in CNG. 67 return algorithmGroup == CngAlgorithmGroup.ECDsa || algorithmGroup == CngAlgorithmGroup.ECDiffieHellman; 68 } 69 GetCurveName()70 internal string GetCurveName() 71 { 72 return Key.GetCurveName(); 73 } 74 ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters)75 private void ImportFullKeyBlob(byte[] ecfullKeyBlob, bool includePrivateParameters) 76 { 77 Key = ECCng.ImportFullKeyBlob(ecfullKeyBlob, includePrivateParameters); 78 } 79 ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters)80 private void ImportKeyBlob(byte[] ecfullKeyBlob, string curveName, bool includePrivateParameters) 81 { 82 Key = ECCng.ImportKeyBlob(ecfullKeyBlob, curveName, includePrivateParameters); 83 } 84 ExportKeyBlob(bool includePrivateParameters)85 private byte[] ExportKeyBlob(bool includePrivateParameters) 86 { 87 return ECCng.ExportKeyBlob(Key, includePrivateParameters); 88 } 89 ExportFullKeyBlob(bool includePrivateParameters)90 private byte[] ExportFullKeyBlob(bool includePrivateParameters) 91 { 92 return ECCng.ExportFullKeyBlob(Key, includePrivateParameters); 93 } 94 FromXmlString(string xml, ECKeyXmlFormat format)95 public void FromXmlString(string xml, ECKeyXmlFormat format) 96 => throw new PlatformNotSupportedException(); 97 98 public byte[] SignData(byte[] data) 99 => SignData(data, new HashAlgorithmName(HashAlgorithm.Algorithm)); 100 SignData(byte[] data, int offset, int count)101 public byte[] SignData(byte[] data, int offset, int count) => 102 SignData(data, offset, count, new HashAlgorithmName(HashAlgorithm.Algorithm)); 103 104 public byte[] SignData(Stream data) 105 => SignData(data, new HashAlgorithmName(HashAlgorithm.Algorithm)); 106 107 public string ToXmlString(ECKeyXmlFormat format) 108 => throw new PlatformNotSupportedException(); 109 VerifyData(byte[] data, byte[] signature)110 public bool VerifyData(byte[] data, byte[] signature) 111 => VerifyData(data, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); 112 VerifyData(byte[] data, int offset, int count, byte[] signature)113 public bool VerifyData(byte[] data, int offset, int count, byte[] signature) 114 => VerifyData(data, offset, count, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); 115 VerifyData(Stream data, byte[] signature)116 public bool VerifyData(Stream data, byte[] signature) 117 => VerifyData(data, signature, new HashAlgorithmName(HashAlgorithm.Algorithm)); 118 } 119 } 120