├── KeyGenSigning
├── KeyGenSigning
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── KeyGenSigning.csproj
│ └── Program.cs
├── CertLib
│ ├── CertificateSigningRequest.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── CertificateGenerationRequest.cs
│ ├── CertLib.csproj
│ ├── CertUtil.cs
│ ├── CertificateGenerator.cs
│ ├── CertificateSigner.cs
│ └── NativeMethods.cs
└── KeyGenSigning.sln
├── README.md
├── LICENSE
└── .gitignore
/KeyGenSigning/KeyGenSigning/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Deprecation Note: These samples are fairly old and they rely on some legacy APIs in Windows.
2 |
3 | There are now classes builtin to .NET Core that do all this work for you. See the [CertificateRequest](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.certificaterequest?view=net-5.0) class for more details.
4 |
5 | Crypto
6 | ======
7 |
8 | Crypto Samples in .NET
9 |
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/CertificateSigningRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Security.Cryptography.X509Certificates;
3 |
4 | namespace CertLib
5 | {
6 | public class CertificateSigningRequest
7 | {
8 | ///
9 | /// The certificate to sign
10 | ///
11 | public X509Certificate2 Certificate { get; set; }
12 |
13 | ///
14 | /// The period of validity for the certificate
15 | ///
16 | public TimeSpan ExpirationLength { get; set; }
17 |
18 | ///
19 | /// The preferred algorithm to sign the certificate
20 | ///
21 | public string SignatureAlgorithm { get; set; }
22 |
23 | ///
24 | /// The specification for key usage
25 | ///
26 | public int KeySpecification { get; set; }
27 |
28 | ///
29 | /// Any X.509 extensions to attach before signing the certificate
30 | ///
31 | public X509ExtensionCollection Extensions { get; set; }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2014 Steve Syfuhs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("CertLib")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("CertLib")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("7cb228d0-806f-492a-9595-2bf48b7c978a")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/KeyGenSigning/KeyGenSigning.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeyGenSigning", "KeyGenSigning\KeyGenSigning.csproj", "{359E4E9C-F5E2-4876-B12A-6B462FC053E4}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CertLib", "CertLib\CertLib.csproj", "{94AE4CAB-E021-4469-B142-F64701E25022}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {359E4E9C-F5E2-4876-B12A-6B462FC053E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {359E4E9C-F5E2-4876-B12A-6B462FC053E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {359E4E9C-F5E2-4876-B12A-6B462FC053E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {359E4E9C-F5E2-4876-B12A-6B462FC053E4}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {94AE4CAB-E021-4469-B142-F64701E25022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {94AE4CAB-E021-4469-B142-F64701E25022}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {94AE4CAB-E021-4469-B142-F64701E25022}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {94AE4CAB-E021-4469-B142-F64701E25022}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/KeyGenSigning/KeyGenSigning/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("KeyGenSigning")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("KeyGenSigning")]
13 | [assembly: AssemblyCopyright("Copyright © 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("48bc511d-b36d-4234-9fd9-eb4f65c6fd96")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/CertificateGenerationRequest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Security.Cryptography;
4 | using System.Security.Cryptography.X509Certificates;
5 |
6 | namespace CertLib
7 | {
8 | public class CertificateGenerationRequest
9 | {
10 | private string subject;
11 |
12 | ///
13 | /// The subject of the certificate
14 | ///
15 | public string Subject
16 | {
17 | get
18 | {
19 | if (string.IsNullOrWhiteSpace(subject))
20 | return subject;
21 |
22 | if (!subject.StartsWith("CN="))
23 | subject = "CN=" + subject;
24 |
25 | return subject;
26 | }
27 | set
28 | {
29 | subject = value;
30 | }
31 | }
32 |
33 | ///
34 | /// The size of the key
35 | ///
36 | public int KeySize { get; set; }
37 |
38 | ///
39 | /// Custom CSP parameters to specify key generation requirements
40 | ///
41 | public CspParameters Parameters { get; set; }
42 |
43 | ///
44 | /// Length of certificate validity
45 | ///
46 | public TimeSpan ExpirationLength { get; set; }
47 |
48 | ///
49 | /// The algorithm signature used to sign the certificate
50 | ///
51 | public string SignatureAlgorithm { get; set; }
52 |
53 | ///
54 | /// Any X.509 extensions to attach to the certificate before signing
55 | ///
56 | public X509ExtensionCollection Extensions { get; set; }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/CertLib.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {94AE4CAB-E021-4469-B142-F64701E25022}
8 | Library
9 | Properties
10 | CertLib
11 | CertLib
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | true
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
59 |
--------------------------------------------------------------------------------
/KeyGenSigning/KeyGenSigning/KeyGenSigning.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {359E4E9C-F5E2-4876-B12A-6B462FC053E4}
8 | Exe
9 | Properties
10 | KeyGenSigning
11 | KeyGenSigning
12 | v4.5
13 | 512
14 |
15 |
16 | x64
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | {94ae4cab-e021-4469-b142-f64701e25022}
53 | CertLib
54 |
55 |
56 |
57 |
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 |
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/CertUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Cryptography.X509Certificates;
5 | using System.Text;
6 |
7 | namespace CertLib
8 | {
9 | internal static class CertUtil
10 | {
11 | internal unsafe static List ConvertExtensions(X509ExtensionCollection extensions)
12 | {
13 | List ret = new List();
14 |
15 | if (extensions == null || extensions.Count == 0)
16 | {
17 | ret.Add(IntPtr.Zero);
18 | return ret;
19 | }
20 |
21 | int extensionStructSize = Marshal.SizeOf(typeof(NativeMethods.CERT_EXTENSION));
22 | NativeMethods.CERT_EXTENSIONS extensionsStruct = new NativeMethods.CERT_EXTENSIONS();
23 |
24 | IntPtr extensionsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.CERT_EXTENSIONS)));
25 |
26 | ret.Add(extensionsPtr);
27 |
28 | extensionsStruct.cExtension = (uint)extensions.Count;
29 | extensionsStruct.rgExtension = Marshal.AllocHGlobal(extensionStructSize * extensions.Count);
30 |
31 | ret.Add(extensionsStruct.rgExtension);
32 |
33 | Marshal.StructureToPtr(extensionsStruct, extensionsPtr, false);
34 | NativeMethods.CERT_EXTENSION extensionStruct = new NativeMethods.CERT_EXTENSION();
35 |
36 | byte* workPointer = (byte*)extensionsStruct.rgExtension.ToPointer();
37 |
38 | foreach (X509Extension ext in extensions)
39 | {
40 | extensionStruct.pszObjId = Marshal.StringToHGlobalAnsi(ext.Oid.Value);
41 | ret.Add(extensionStruct.pszObjId);
42 |
43 | extensionStruct.fCritical = ext.Critical;
44 | byte[] rawData = ext.RawData;
45 |
46 | extensionStruct.Value = new NativeMethods.CRYPTOAPI_BLOB();
47 |
48 | extensionStruct.Value.cbData = (uint)rawData.Length;
49 | extensionStruct.Value.pbData = Marshal.AllocHGlobal(rawData.Length); ;
50 |
51 | Marshal.Copy(rawData, 0, extensionStruct.Value.pbData, rawData.Length);
52 |
53 | ret.Add(extensionStruct.Value.pbData);
54 |
55 | Marshal.StructureToPtr(extensionStruct, new IntPtr(workPointer), false);
56 | workPointer += extensionStructSize;
57 | }
58 |
59 | return ret;
60 | }
61 |
62 | internal static Dictionary ReadAllProviders()
63 | {
64 | var installedCSPs = new Dictionary();
65 | StringBuilder pszName;
66 |
67 | int cbName;
68 | int dwType;
69 | int dwIndex;
70 |
71 | dwIndex = 0;
72 | dwType = 1;
73 | cbName = 0;
74 |
75 | while (NativeMethods.CryptEnumProviders(dwIndex, IntPtr.Zero, 0, ref dwType, null, ref cbName))
76 | {
77 | pszName = new StringBuilder(cbName);
78 |
79 | if (NativeMethods.CryptEnumProviders(dwIndex++, IntPtr.Zero, 0, ref dwType, pszName, ref cbName))
80 | {
81 | installedCSPs.Add(pszName.ToString(), dwType);
82 | }
83 | }
84 |
85 | return installedCSPs;
86 | }
87 |
88 | internal static FILETIME FileTimeFromDateTime(DateTime date)
89 | {
90 | long ftime = date.ToFileTime();
91 |
92 | FILETIME ft = new FILETIME();
93 |
94 | ft.dwHighDateTime = (int)(ftime >> 32);
95 | ft.dwLowDateTime = (int)ftime;
96 |
97 | return ft;
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/KeyGenSigning/KeyGenSigning/Program.cs:
--------------------------------------------------------------------------------
1 | using CertLib;
2 | using System;
3 | using System.Security.Cryptography;
4 | using System.Security.Cryptography.X509Certificates;
5 |
6 | namespace KeyGenSigning
7 | {
8 | class Program
9 | {
10 | static void Main(string[] args)
11 | {
12 | var CA = CreateCertificateAuthority();
13 |
14 | Console.WriteLine("CA: " + CA);
15 |
16 | var subordinate = CreateSubordinate();
17 |
18 | Console.WriteLine("Subordinate: " + subordinate);
19 |
20 | var signedSubordinate = SignIt(subordinate, CA);
21 |
22 | Console.WriteLine("Signed: " + signedSubordinate);
23 |
24 | Console.Write("Press enter to close...");
25 |
26 | Console.ReadLine();
27 | }
28 |
29 | private static X509Certificate2 SignIt(X509Certificate2 subordinate, X509Certificate2 CA)
30 | {
31 | var csr = new CertificateSigningRequest()
32 | {
33 | KeySpecification = CertificateSigner.AT_SIGNATURE,
34 | Certificate = subordinate,
35 | ExpirationLength = subordinate.NotAfter - subordinate.NotBefore
36 | };
37 |
38 | return CertificateSigner.SignCertificate(csr, CA);
39 | }
40 |
41 | private static X509Certificate2 CreateCertificateAuthority()
42 | {
43 | CspParameters parameters = new CspParameters()
44 | {
45 | ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider",
46 | ProviderType = 24,
47 | KeyContainerName = Guid.NewGuid().ToString(),
48 | KeyNumber = (int)KeyNumber.Signature,
49 | Flags = CspProviderFlags.UseMachineKeyStore
50 | };
51 |
52 | var extensions = new X509ExtensionCollection();
53 |
54 | extensions.Add(new X509BasicConstraintsExtension(true, false, 0, false));
55 | extensions.Add(new X509KeyUsageExtension(
56 | X509KeyUsageFlags.CrlSign |
57 | X509KeyUsageFlags.DataEncipherment |
58 | X509KeyUsageFlags.DigitalSignature |
59 | X509KeyUsageFlags.KeyAgreement |
60 | X509KeyUsageFlags.KeyCertSign |
61 | X509KeyUsageFlags.KeyEncipherment |
62 | X509KeyUsageFlags.NonRepudiation, false));
63 |
64 | var cgr = new CertificateGenerationRequest()
65 | {
66 | Subject = "Syfuhs Industries Certificate Authority",
67 | Parameters = parameters,
68 | SignatureAlgorithm = "1.2.840.113549.1.1.11",
69 | ExpirationLength = TimeSpan.FromDays(365 * 20),
70 | KeySize = 2048,
71 | Extensions = extensions
72 | };
73 |
74 | var cert = CertificateGenerator.CreateSelfSignedCertificate(cgr);
75 | return cert;
76 | }
77 |
78 | private static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateSubordinate()
79 | {
80 | var oids = new OidCollection();
81 | oids.Add(new Oid("1.3.6.1.5.5.7.3.2")); // client auth
82 | oids.Add(new Oid("1.3.6.1.4.1.311.20.2.2")); // smart card login
83 |
84 | var extensions = new X509ExtensionCollection();
85 | extensions.Add(new X509EnhancedKeyUsageExtension(oids, true));
86 |
87 | var cgr = new CertificateGenerationRequest()
88 | {
89 | Subject = "steve@syfuhs.net",
90 | Extensions = extensions,
91 | ExpirationLength = TimeSpan.FromDays(365 * 5),
92 | KeySize = 2048
93 | };
94 |
95 | var cert = CertificateGenerator.CreateSelfSignedCertificate(cgr);
96 | return cert;
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/CertificateGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.InteropServices;
4 | using System.Security.Cryptography;
5 | using System.Security.Cryptography.X509Certificates;
6 |
7 | namespace CertLib
8 | {
9 | public static class CertificateGenerator
10 | {
11 | public const int MINIMUM_SELF_SIGNED_CERTIFICATE_KEYSIZE = 2048;
12 | public const string MS_ENH_RSA_AES_PROV = "Microsoft Enhanced RSA and AES Cryptographic Provider";
13 | public const int PROV_RSA_AES = 24;
14 |
15 | ///
16 | /// Create a self signed certificate
17 | ///
18 | /// A request to generate certificate
19 | /// Returns a self signed certificate
20 | public static X509Certificate2 CreateSelfSignedCertificate(CertificateGenerationRequest request)
21 | {
22 | var ptr = CreateSelfSignedCertificatePtr(request);
23 |
24 | return new X509Certificate2(ptr);
25 | }
26 |
27 | ///
28 | /// Create a certificate
29 | ///
30 | /// A request to generate certificate
31 | /// Returns a pointer to the signed certificate
32 | internal static unsafe IntPtr CreateSelfSignedCertificatePtr(CertificateGenerationRequest request)
33 | {
34 | if (request == null)
35 | throw new ArgumentNullException("request");
36 |
37 | if (string.IsNullOrWhiteSpace(request.Subject))
38 | throw new ArgumentException("request.Subject is null");
39 |
40 | NativeMethods.CERT_NAME_BLOB pSubjectIssuerBlob = new NativeMethods.CERT_NAME_BLOB(0, null);
41 |
42 | IntPtr extensionsPtr = IntPtr.Zero;
43 |
44 | var subjectName = request.Subject;
45 | var extensions = request.Extensions;
46 |
47 | var parameters = request.Parameters;
48 |
49 | if (parameters == null)
50 | parameters = new CspParameters()
51 | {
52 | ProviderName = MS_ENH_RSA_AES_PROV,
53 | ProviderType = PROV_RSA_AES,
54 | KeyContainerName = Guid.NewGuid().ToString(),
55 | KeyNumber = (int)KeyNumber.Exchange,
56 | Flags = CspProviderFlags.UseMachineKeyStore
57 | };
58 |
59 | var keySize = request.KeySize;
60 |
61 | if (keySize <= 0)
62 | keySize = MINIMUM_SELF_SIGNED_CERTIFICATE_KEYSIZE;
63 |
64 | var expirationLength = request.ExpirationLength;
65 |
66 | if (expirationLength <= TimeSpan.MinValue)
67 | {
68 | expirationLength = TimeSpan.FromDays(365);
69 | }
70 |
71 | var durationInMinutes = expirationLength.TotalMinutes;
72 |
73 | var signatureAlgo = request.SignatureAlgorithm;
74 |
75 | if (string.IsNullOrWhiteSpace(signatureAlgo))
76 | signatureAlgo = NativeMethods.OID_RSA_SHA256RSA;
77 |
78 | string container = Guid.NewGuid().ToString();
79 |
80 | try
81 | {
82 | uint pcbEncoded = 0;
83 |
84 | if (!NativeMethods.CertStrToName(NativeMethods.X509_ASN_ENCODING, subjectName, NativeMethods.CERT_X500_NAME_STR, IntPtr.Zero, null, ref pcbEncoded, IntPtr.Zero) && pcbEncoded <= 0)
85 | throw new Win32Exception(Marshal.GetLastWin32Error());
86 |
87 | byte[] pbEncoded = new byte[pcbEncoded];
88 |
89 | if (!NativeMethods.CertStrToName(NativeMethods.X509_ASN_ENCODING, subjectName, NativeMethods.CERT_X500_NAME_STR, IntPtr.Zero, pbEncoded, ref pcbEncoded, IntPtr.Zero))
90 | throw new Win32Exception(Marshal.GetLastWin32Error());
91 |
92 | using (new RSACryptoServiceProvider(keySize, parameters))
93 | {
94 | pSubjectIssuerBlob.CopyData(pbEncoded);
95 |
96 | NativeMethods.CRYPT_KEY_PROV_INFO pKeyProvInfo = new NativeMethods.CRYPT_KEY_PROV_INFO
97 | {
98 | pwszProvName = parameters.ProviderName,
99 | pwszContainerName = parameters.KeyContainerName,
100 | dwProvType = (uint)parameters.ProviderType,
101 | dwFlags = 0x20, //(uint)parameters.Flags,
102 | dwKeySpec = (uint)parameters.KeyNumber
103 | };
104 |
105 | NativeMethods.CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm = new NativeMethods.CRYPT_ALGORITHM_IDENTIFIER
106 | {
107 | pszObjId = signatureAlgo
108 | };
109 |
110 | pSignatureAlgorithm.parameters.cbData = 0;
111 | pSignatureAlgorithm.parameters.pbData = IntPtr.Zero;
112 |
113 | NativeMethods.SYSTEM_TIME pStartTime = new NativeMethods.SYSTEM_TIME(DateTime.UtcNow);
114 | NativeMethods.SYSTEM_TIME pEndTime = new NativeMethods.SYSTEM_TIME(DateTime.UtcNow.AddMinutes((double)durationInMinutes));
115 |
116 | extensionsPtr = CertUtil.ConvertExtensions(extensions)[0];
117 |
118 | IntPtr handle = NativeMethods.CertCreateSelfSignCertificate(IntPtr.Zero, ref pSubjectIssuerBlob, 0, ref pKeyProvInfo, ref pSignatureAlgorithm, ref pStartTime, ref pEndTime, extensionsPtr);
119 |
120 | if (handle == IntPtr.Zero)
121 | throw new Win32Exception(Marshal.GetLastWin32Error());
122 |
123 | return handle;
124 | }
125 | }
126 | finally
127 | {
128 | if (IntPtr.Zero != extensionsPtr)
129 | {
130 | Marshal.FreeHGlobal(extensionsPtr);
131 | extensionsPtr = IntPtr.Zero;
132 | }
133 |
134 | pSubjectIssuerBlob.Dispose();
135 | }
136 | }
137 | }
138 | }
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/CertificateSigner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Security.Cryptography;
6 | using System.Security.Cryptography.X509Certificates;
7 |
8 | namespace CertLib
9 | {
10 | public static class CertificateSigner
11 | {
12 | public const int AT_KEYEXCHANGE = (int)NativeMethods.AT_KEYEXCHANGE;
13 | public const int AT_SIGNATURE = (int)NativeMethods.AT_SIGNATURE;
14 |
15 | ///
16 | /// Accepts a CSR-like object to sign by another key
17 | ///
18 | /// The request to sign
19 | /// The signing key
20 | /// Returns a signed certificate
21 | public static X509Certificate2 SignCertificate(CertificateSigningRequest request, X509Certificate2 CACert)
22 | {
23 | IntPtr hCAProv = IntPtr.Zero;
24 |
25 | IntPtr hProvAllocPtr = IntPtr.Zero;
26 | IntPtr subordinateCertInfoAllocPtr = IntPtr.Zero;
27 |
28 | RuntimeHelpers.PrepareConstrainedRegions();
29 |
30 | try
31 | {
32 | // Get CA cert into CERT_CONTEXT
33 | // Get CA cert into CERT_INFO from context.pCertInfo
34 |
35 | NativeMethods.CERT_CONTEXT CAContext = (NativeMethods.CERT_CONTEXT)Marshal.PtrToStructure(CACert.Handle, typeof(NativeMethods.CERT_CONTEXT));
36 | NativeMethods.CERT_INFO CACertInfo = (NativeMethods.CERT_INFO)Marshal.PtrToStructure(CAContext.pCertInfo, typeof(NativeMethods.CERT_INFO));
37 |
38 | uint pcbData = 0;
39 |
40 | // get the context property handle of the CA Cert
41 |
42 | if (!NativeMethods.CertGetCertificateContextProperty(CACert.Handle, 2, hProvAllocPtr, ref pcbData))
43 | throw new CryptographicException(Marshal.GetLastWin32Error());
44 |
45 | hProvAllocPtr = NativeMethods.LocalAlloc(0, new IntPtr((long)pcbData));
46 |
47 | if (!NativeMethods.CertGetCertificateContextProperty(CACert.Handle, 2, hProvAllocPtr, ref pcbData))
48 | throw new CryptographicException(Marshal.GetLastWin32Error());
49 |
50 | // get the key handle of the CA Cert
51 |
52 | NativeMethods.CRYPT_KEY_PROV_INFO pKeyInfo = (NativeMethods.CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(hProvAllocPtr, typeof(NativeMethods.CRYPT_KEY_PROV_INFO));
53 |
54 | // Acquire a context to the provider for crypto
55 |
56 | if (!NativeMethods.CryptAcquireContext(ref hCAProv, pKeyInfo.pwszContainerName, pKeyInfo.pwszProvName, pKeyInfo.dwProvType, pKeyInfo.dwFlags))
57 | throw new Win32Exception(Marshal.GetLastWin32Error());
58 |
59 | // Get subordinate cert into CERT_CONTEXT
60 | // Get subordinate cert into CERT_INFO from context.pCertInfo
61 |
62 | NativeMethods.CERT_CONTEXT subordinateCertContext = (NativeMethods.CERT_CONTEXT)Marshal.PtrToStructure(request.Certificate.Handle, typeof(NativeMethods.CERT_CONTEXT));
63 | NativeMethods.CERT_INFO subordinateCertInfo = (NativeMethods.CERT_INFO)Marshal.PtrToStructure(subordinateCertContext.pCertInfo, typeof(NativeMethods.CERT_INFO));
64 |
65 | NativeMethods.CRYPT_ALGORITHM_IDENTIFIER signatureAlgo = new NativeMethods.CRYPT_ALGORITHM_IDENTIFIER()
66 | {
67 | pszObjId = string.IsNullOrWhiteSpace(request.SignatureAlgorithm) ? NativeMethods.OID_RSA_SHA256RSA : request.SignatureAlgorithm
68 | };
69 |
70 | // apply new issuer
71 |
72 | subordinateCertInfo.NotBefore = CertUtil.FileTimeFromDateTime(DateTime.UtcNow.AddHours(-1));
73 | subordinateCertInfo.NotAfter = CertUtil.FileTimeFromDateTime(DateTime.UtcNow.Add(request.ExpirationLength));
74 |
75 | var caExtensions = CertUtil.ConvertExtensions(request.Extensions)[0];
76 |
77 | subordinateCertInfo.cExtension = request.Extensions == null ? 0 : (uint)request.Extensions.Count;
78 | subordinateCertInfo.rgExtension = caExtensions;
79 |
80 | subordinateCertInfo.SignatureAlgorithm = signatureAlgo;
81 | subordinateCertInfo.Issuer = CACertInfo.Subject;
82 |
83 | subordinateCertInfoAllocPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.CERT_INFO)));
84 | Marshal.StructureToPtr(subordinateCertInfo, subordinateCertInfoAllocPtr, false);
85 |
86 | byte[] pbEncodedCert = null;
87 | uint pbEncodedCertLength = 0;
88 |
89 | if (!NativeMethods.CryptSignAndEncodeCertificate(hCAProv,
90 | (uint)request.KeySpecification,
91 | NativeMethods.X509_ASN_ENCODING,
92 | NativeMethods.X509_CERT_TO_BE_SIGNED,
93 | subordinateCertInfoAllocPtr,
94 | ref signatureAlgo,
95 | IntPtr.Zero,
96 | pbEncodedCert,
97 | ref pbEncodedCertLength))
98 | {
99 | throw new Win32Exception(Marshal.GetLastWin32Error());
100 | }
101 |
102 | pbEncodedCert = new byte[pbEncodedCertLength];
103 |
104 | if (!NativeMethods.CryptSignAndEncodeCertificate(hCAProv,
105 | (uint)request.KeySpecification,
106 | NativeMethods.X509_ASN_ENCODING,
107 | NativeMethods.X509_CERT_TO_BE_SIGNED,
108 | subordinateCertInfoAllocPtr,
109 | ref signatureAlgo,
110 | IntPtr.Zero,
111 | pbEncodedCert,
112 | ref pbEncodedCertLength))
113 | {
114 | throw new Win32Exception(Marshal.GetLastWin32Error());
115 | }
116 |
117 | var cert3 = new X509Certificate2(pbEncodedCert);
118 |
119 | return cert3;
120 | }
121 | finally
122 | {
123 | if (hProvAllocPtr != IntPtr.Zero)
124 | NativeMethods.CryptReleaseContext(hProvAllocPtr, 0);
125 |
126 | if (hCAProv != IntPtr.Zero)
127 | NativeMethods.CryptReleaseContext(hCAProv, 0);
128 |
129 | if (hProvAllocPtr != IntPtr.Zero)
130 | Marshal.FreeHGlobal(hProvAllocPtr);
131 |
132 | if (subordinateCertInfoAllocPtr != IntPtr.Zero)
133 | Marshal.FreeHGlobal(subordinateCertInfoAllocPtr);
134 | }
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/KeyGenSigning/CertLib/NativeMethods.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32.SafeHandles;
2 | using System;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 |
6 | namespace CertLib
7 | {
8 | // P/Invoke signatures borrowed from http://www.pinvoke.net/ as well as trial and error
9 |
10 | internal static class NativeMethods
11 | {
12 | public const uint AT_KEYEXCHANGE = 0x00000001;
13 | public const uint AT_SIGNATURE = 0x00000002;
14 |
15 | public const string OID_RSA_SHA256RSA = "1.2.840.113549.1.1.11";
16 | public const string szOID_ENHANCED_KEY_USAGE = "2.5.29.37";
17 |
18 | public const uint CERT_X500_NAME_STR = 3;
19 | public const uint X509_ASN_ENCODING = 0x00000001;
20 | public const uint PKCS_7_ASN_ENCODING = 0x00010000;
21 | public const uint CRYPT_VERIFYCONTEXT = 0xF0000000; //no private key access flag
22 |
23 | private const string ADVAPI32 = "advapi32.dll";
24 | private const string CRYPT32 = "crypt32.dll";
25 | private const string KERNEL32 = "kernel32.dll";
26 |
27 | public const ulong X509_CERT_CRL_TO_BE_SIGNED = 3; // CRL_INFO
28 | public const ulong X509_CERT_REQUEST_TO_BE_SIGNED = 4; // CERT_REQUEST_INFO
29 | public const ulong X509_CERT_TO_BE_SIGNED = 2; // CERT_INFO
30 | public const ulong X509_KEYGEN_REQUEST_TO_BE_SIGNED = 21; // CERT_KEYGEN_REQUEST_INFO
31 |
32 | [DllImport(CRYPT32, SetLastError = true, CharSet = CharSet.Auto)]
33 | [return: MarshalAs(UnmanagedType.Bool)]
34 | public static extern bool CryptSignAndEncodeCertificate(IntPtr hCryptProvOrNCryptKey,
35 | uint dwKeySpec,
36 | uint dwCertEncodingType,
37 | ulong lpszStructType,
38 | IntPtr pvStructInfo,
39 | ref CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
40 | IntPtr pvHashAuxInfo,
41 | byte[] pbEncoded,
42 | ref uint pcbEncoded);
43 |
44 | [DllImport(CRYPT32, SetLastError = true)]
45 | public static extern IntPtr CertCreateSelfSignCertificate(IntPtr hProv,
46 | ref CERT_NAME_BLOB pSubjectIssuerBlob,
47 | uint dwFlagsm,
48 | ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
49 | ref CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
50 | ref SYSTEM_TIME pStartTime,
51 | ref SYSTEM_TIME pEndTime,
52 | IntPtr other);
53 |
54 | [DllImport(CRYPT32, CharSet = CharSet.Unicode, SetLastError = true)]
55 | public static extern bool CertStrToName(uint dwCertEncodingType,
56 | string pszX500,
57 | uint dwStrType,
58 | IntPtr pvReserved,
59 | [In, Out] byte[] pbEncoded,
60 | ref uint pcbEncoded,
61 | IntPtr other);
62 |
63 | [DllImport(ADVAPI32)]
64 | public static extern bool CryptEnumProviders(int dwIndex,
65 | IntPtr pdwReserved,
66 | int dwFlags,
67 | ref int pdwProvType,
68 | StringBuilder pszProvName,
69 | ref int pcbProvName);
70 |
71 | [DllImport(ADVAPI32, CharSet = CharSet.Auto, SetLastError = true)]
72 | public static extern bool CryptAcquireContext(ref IntPtr hProv,
73 | string pszContainer,
74 | string pszProvider,
75 | uint dwProvType,
76 | uint dwFlags);
77 |
78 | [DllImport(ADVAPI32)]
79 | public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);
80 |
81 | [DllImport(CRYPT32, SetLastError = true)]
82 | public static extern bool CertGetCertificateContextProperty(IntPtr pCertContext,
83 | uint dwPropId,
84 | IntPtr pvData,
85 | ref uint pcbData);
86 |
87 | [DllImport(KERNEL32, CharSet = CharSet.Auto, SetLastError = true)]
88 | internal static extern IntPtr LocalAlloc([In] uint uFlags, [In] IntPtr sizetdwBytes);
89 |
90 | [StructLayout(LayoutKind.Sequential)]
91 | public struct CERT_CONTEXT
92 | {
93 | public uint dwCertEncodingType;
94 | public IntPtr pbCertEncoded;
95 | public int cbCertEncoded;
96 | public IntPtr pCertInfo;
97 | public IntPtr hCertStore;
98 | }
99 |
100 | [StructLayout(LayoutKind.Sequential)]
101 | public struct CERT_INFO
102 | {
103 | public uint dwVersion;
104 | public CRYPTOAPI_BLOB SerialNumber;
105 | public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
106 | public CRYPTOAPI_BLOB Issuer;
107 | public FILETIME NotBefore;
108 | public FILETIME NotAfter;
109 | public CRYPTOAPI_BLOB Subject;
110 | public CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo;
111 | public CRYPTOAPI_BLOB IssuerUniqueId;
112 | public CRYPTOAPI_BLOB SubjectUniqueId;
113 | public uint cExtension;
114 | public IntPtr rgExtension;
115 | }
116 |
117 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
118 | public struct CERT_EXTENSION
119 | {
120 | public IntPtr pszObjId;
121 | public bool fCritical;
122 | public NativeMethods.CRYPTOAPI_BLOB Value;
123 | }
124 |
125 | [StructLayout(LayoutKind.Sequential)]
126 | public struct CERT_EXTENSIONS
127 | {
128 | public uint cExtension;
129 | public IntPtr rgExtension;
130 | }
131 |
132 | [StructLayout(LayoutKind.Sequential)]
133 | public struct CERT_NAME_BLOB : IDisposable
134 | {
135 | public int _cbData;
136 | public SafeGlobalMemoryHandle _pbData;
137 |
138 | public CERT_NAME_BLOB(int cb, SafeGlobalMemoryHandle handle)
139 | {
140 | this._cbData = cb;
141 | this._pbData = handle;
142 | }
143 |
144 | public void CopyData(byte[] encodedName)
145 | {
146 | this._pbData = new SafeGlobalMemoryHandle(encodedName);
147 | this._cbData = encodedName.Length;
148 | }
149 |
150 | public void Dispose()
151 | {
152 | if (this._pbData != null)
153 | {
154 | this._pbData.Dispose();
155 | this._pbData = null;
156 | }
157 | }
158 | }
159 |
160 | [StructLayout(LayoutKind.Sequential)]
161 | public struct CRYPT_ALGORITHM_IDENTIFIER
162 | {
163 | [MarshalAs(UnmanagedType.LPStr)]
164 | public string pszObjId;
165 | public NativeMethods.CRYPTOAPI_BLOB parameters;
166 | }
167 |
168 | [StructLayout(LayoutKind.Sequential)]
169 | public struct CRYPT_KEY_PROV_INFO
170 | {
171 | [MarshalAs(UnmanagedType.LPWStr)]
172 | public string pwszContainerName;
173 | [MarshalAs(UnmanagedType.LPWStr)]
174 | public string pwszProvName;
175 | public uint dwProvType;
176 | public uint dwFlags;
177 | public uint cProvParam;
178 | public IntPtr rgProvParam;
179 | public uint dwKeySpec;
180 | }
181 |
182 | [StructLayout(LayoutKind.Sequential)]
183 | public struct CERT_PUBLIC_KEY_INFO
184 | {
185 | public String SubjPKIAlgpszObjId;
186 | public int SubjPKIAlgParameterscbData;
187 | public IntPtr SubjPKIAlgParameterspbData;
188 | public int PublicKeycbData;
189 | public IntPtr PublicKeypbData;
190 | public int PublicKeycUnusedBits;
191 | }
192 |
193 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
194 | public struct CRYPTOAPI_BLOB
195 | {
196 | public uint cbData;
197 | public IntPtr pbData;
198 | }
199 |
200 | [StructLayout(LayoutKind.Sequential)]
201 | public struct SYSTEM_TIME
202 | {
203 | public ushort wYear;
204 | public ushort wMonth;
205 | public ushort wDayOfWeek;
206 | public ushort wDay;
207 | public ushort wHour;
208 | public ushort wMinute;
209 | public ushort wSecond;
210 | public ushort wMilliseconds;
211 |
212 | public SYSTEM_TIME(DateTime dt)
213 | {
214 | this.wYear = (ushort)dt.Year;
215 | this.wMonth = (ushort)dt.Month;
216 | this.wDay = (ushort)dt.Day;
217 | this.wDayOfWeek = (ushort)dt.DayOfWeek;
218 | this.wHour = (ushort)dt.Hour;
219 | this.wMinute = (ushort)dt.Minute;
220 | this.wSecond = (ushort)dt.Second;
221 | this.wMilliseconds = (ushort)dt.Millisecond;
222 | }
223 | }
224 |
225 | internal class SafeGlobalMemoryHandle : SafeHandleZeroOrMinusOneIsInvalid
226 | {
227 | private SafeGlobalMemoryHandle()
228 | : base(true)
229 | {
230 | }
231 |
232 | public SafeGlobalMemoryHandle(byte[] data)
233 | : base(true)
234 | {
235 | base.handle = Marshal.AllocHGlobal(data.Length);
236 | Marshal.Copy(data, 0, base.handle, data.Length);
237 | }
238 |
239 | private SafeGlobalMemoryHandle(IntPtr handle)
240 | : base(true)
241 | {
242 | base.SetHandle(handle);
243 | }
244 |
245 | protected override bool ReleaseHandle()
246 | {
247 | Marshal.FreeHGlobal(base.handle);
248 | return true;
249 | }
250 | }
251 | }
252 | }
253 |
--------------------------------------------------------------------------------