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