how to install the certificate in certificate store without private key? - c#

I have below 2 methods,
GetCaCertificate method reads the PFX certificate with has private key included.
AddCertToStore method add the certificate to the certificate store, here I want to add the certificate in the certificate store with-out Private key, how we can avoid it?
var rootCaCert = GetCaCertificate(#"C:\cert\ca-cert.pfx", "Password#123");
AddCertToStore(rootCaCert, StoreName.Root, StoreLocation.LocalMachine);
private static X509Certificate2 GetCaCertificate(string certPath, string password)
{
return new X509Certificate2(File.ReadAllBytes(certPath), password:password);
}
public static bool AddCertToStore(X509Certificate2 cert, StoreName storeName, StoreLocation storeLocation)
{
bool value;
try
{
using var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
store.Add(cert);
store.Close();
value = true;
}
catch (Exception exception)
{
Console.WriteLine(exception);
value = false;
}
return value;
}

Get a copy of public part of the certificate and add it to the store. That is, replace this line:
store.Add(cert);
with this:
store.Add(new X509Certificate2(cert.RawData));
in this case, you will install only public part of the certificate without associating it with private key.

Related

How do I detect if AsymmetricAlgorithm is a private key or a public key

Is there a simple way to check if a given AsymmetricAlgorithm is a private or a public key? Consider the following example:
private void SavePrivateKey(AsymmetricAlgorithm asymmetricAlgorithm)
{
// if (asymmetricAlgorithm.IsPrivateKey == false)
// throw new ArgumentException();
}
private void SavePrivateKeys()
{
var certificate = CreateCertificate();
var privateKey = RSACertificateExtensions.GetRSAPrivateKey(certificate);
var publicKey = RSACertificateExtensions.GetRSAPublicKey(certificate);
SavePrivateKey(privateKey);
SavePrivateKey(publicKey); // this should throw an exception
}
private X509Certificate2 CreateCertificate()
{
CngKeyCreationParameters keyParams = new CngKeyCreationParameters();
keyParams.KeyUsage = CngKeyUsages.Signing;
keyParams.Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider;
keyParams.ExportPolicy = CngExportPolicies.AllowExport | CngExportPolicies.AllowPlaintextExport;
keyParams.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(2048), CngPropertyOptions.None));
var cngKey = CngKey.Create(CngAlgorithm.Rsa, Guid.NewGuid().ToString(), keyParams);
var rsaKey = new RSACng(cngKey);
var req = new CertificateRequest("cn=mycert", rsaKey, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
var cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(5));
return cert;
}
Here, both private and public keys have the same type - RSACng. In theory I can try to export key parameters and see if the public key fails to export the private key params. But then I would not know if the export failed because it is a public key, or because it is missing export policies or something else went wrong. Also the underlying key type may be different, it could be RSACng, RSACryptoServiceProvider, DSA etc.
The ToXmlString() method takes in the includePrivateParameters parameter. If that parameter is set, and the AsymmetricAlgorithm object does not include information about the private key, ToXmlString() will throw a CryptographicException exception:
private void SavePrivateKey(AsymmetricAlgorithm aa)
{
System.Console.Write("This is ");
try
{
aa.ToXmlString(true);
}
catch(CryptographicException ce)
{
System.Console.Write("not ");
}
System.Console.WriteLine("a private key");
}

How to fix "CCertRequest::Submit: The RPC server is unavailable. 0x800706ba" error?

Scenario:
I am learning AWS CloudHSM. So far, I have
created an EC2 instance with Windows Server 2019 Datacenter as OS
created a certification authority (root CA) on this server with Dintinguised Name "CN=myservername-CA1" (https://docs.aws.amazon.com/cloudhsm/latest/userguide/win-ca-setup.html )
while connected to EC2 instance via RDP, I can login to my cloud hsm account and can manage users, create new keys etc.
Details of CA:
Provider: RSA#Cavium Key Storage Provider
Key Length: 2048
Hash Algorithm: SHA256
Distinguished Name: CN=myservername-CA1
Cert Database log: C:\Windows\system32\CertLog
Now, I have developed a sample .Net WebAPI application which should send a CSR request to my CA and CA should return the signed certificate to the requester. This application is hosted as a web app on IIS on the same EC2 instance.
Source Code (https://blogs.msdn.microsoft.com/alejacma/2008/09/05/how-to-create-a-certificate-request-with-certenroll-and-net-c/ ):
using CloudHsmDemo.Models;
using System;
using System.Threading.Tasks;
using CERTENROLLLib;
using CERTCLILib;
namespace CloudHsmDemo.Services
{
public interface ICertificateService
{
Task<CertificateSigningResponse> SignAsync(CertificateSigningRequest csr);
}
public class CertificateService : ICertificateService
{
private const int CC_DEFAULTCONFIG = 0;
private const int CC_UIPICKCONFIG = 0x1;
private const int CR_IN_BASE64 = 0x1;
private const int CR_IN_FORMATANY = 0;
private const int CR_IN_PKCS10 = 0x100;
private const int CR_DISP_ISSUED = 0x3;
private const int CR_DISP_UNDER_SUBMISSION = 0x5;
private const int CR_OUT_BASE64 = 0x1;
private const int CR_OUT_CHAIN = 0x100;
public async Task<CertificateSigningResponse> SignAsync(CertificateSigningRequest csr)
{
if (csr.ShouldReturnDummyData)
{
return await DummySigningAsync(csr);
}
else
{
return await ActualSigningAsync(csr);
}
}
private async Task<CertificateSigningResponse> DummySigningAsync(CertificateSigningRequest csr)
{
return PopulateCertificateSigningResponse("Sample Certificate", "Sample Message");
}
private async Task<CertificateSigningResponse> ActualSigningAsync(CertificateSigningRequest csr)
{
// Create all the objects that will be required
CCertConfig objCertConfig = new CCertConfigClass();
CCertRequest objCertRequest = new CCertRequestClass();
// string strCAConfig;
string strRequest;
int iDisposition;
string strDisposition;
string strCert;
CertificateSigningResponse certificateSigningResponse;
try
{
strRequest = await CreateCertificateSigningRequest(csr);
// Get CA config from UI
// strCAConfig = objCertConfig.GetConfig(CC_DEFAULTCONFIG);
//strCAConfig = objCertConfig.GetConfig(CC_UIPICKCONFIG);
// Submit the request
iDisposition = objCertRequest.Submit(
CR_IN_BASE64 | CR_IN_FORMATANY,
strRequest,
null,
"<my_ec2_instance_public_dns>\\<my_server_name>"
);
// Check the submission status
if (CR_DISP_ISSUED != iDisposition) // Not enrolled
{
strDisposition = objCertRequest.GetDispositionMessage();
if (CR_DISP_UNDER_SUBMISSION == iDisposition) // Pending
{
certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, $"The submission is pending: {strDisposition}");
}
else // Failed
{
certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, $"The submission failed: {strDisposition}; Last Status: {objCertRequest.GetLastStatus().ToString()}");
}
}
// Get the certificate
strCert = objCertRequest.GetCertificate(
CR_OUT_BASE64 | CR_OUT_CHAIN
);
certificateSigningResponse = PopulateCertificateSigningResponse(strCert, "Certificate signing process succeeded.");
}
catch (Exception ex)
{
certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, ex.Message);
}
if (certificateSigningResponse == null)
{
certificateSigningResponse = PopulateCertificateSigningResponse(string.Empty, "Certificate signing process failed.");
}
return certificateSigningResponse;
}
// this method creates a request string properly when
private async Task<string> CreateCertificateSigningRequest(CertificateSigningRequest csr)
{
// Create all the objects that will be required
CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10Class();
CX509PrivateKey objPrivateKey = new CX509PrivateKeyClass();
CCspInformation objCSP = new CCspInformationClass();
CCspInformations objCSPs = new CCspInformationsClass();
CX500DistinguishedName objDN = new CX500DistinguishedNameClass();
CX509Enrollment objEnroll = new CX509EnrollmentClass();
CObjectIds objObjectIds = new CObjectIdsClass();
CObjectId objObjectId = new CObjectIdClass();
CX509ExtensionKeyUsage objExtensionKeyUsage = new CX509ExtensionKeyUsageClass();
CX509ExtensionEnhancedKeyUsage objX509ExtensionEnhancedKeyUsage = new CX509ExtensionEnhancedKeyUsageClass();
string strRequest;
try
{
// Initialize the csp object using the desired Cryptograhic Service Provider (CSP)
objCSP.InitializeFromName("Microsoft Enhanced Cryptographic Provider v1.0");
//objCSP.InitializeFromName("Cavium Key Storage Provider");
// Add this CSP object to the CSP collection object
objCSPs.Add(objCSP);
// Provide key container name, key length and key spec to the private key object
objPrivateKey.Length = csr.KeySize;
objPrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE;
objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;
objPrivateKey.MachineContext = false;
// Provide the CSP collection object (in this case containing only 1 CSP object)
// to the private key object
objPrivateKey.CspInformations = objCSPs;
// Create the actual key pair
objPrivateKey.Create();
// Initialize the PKCS#10 certificate request object based on the private key.
// Using the context, indicate that this is a user certificate request and don't
// provide a template name
objPkcs10.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, objPrivateKey, "");
// Key Usage Extension
objExtensionKeyUsage.InitializeEncode(
X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |
X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE
);
objPkcs10.X509Extensions.Add((CX509Extension)objExtensionKeyUsage);
// Enhanced Key Usage Extension
objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2"); // OID for Client Authentication usage
objObjectIds.Add(objObjectId);
objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);
objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage);
// Encode the name in using the Distinguished Name object
objDN.Encode("CN=<myservername>-CA1", X500NameFlags.XCN_CERT_NAME_STR_NONE);
// Assing the subject name by using the Distinguished Name object initialized above
objPkcs10.Subject = objDN;
// Create enrollment request
objEnroll.InitializeFromRequest(objPkcs10);
strRequest = objEnroll.CreateRequest(
EncodingType.XCN_CRYPT_STRING_BASE64
);
}
catch (Exception ex)
{
throw ex;
}
return strRequest;
}
private CertificateSigningResponse PopulateCertificateSigningResponse(string certificate, string message)
{
var responseObject = new CertificateSigningResponse
{
Certificate = certificate,
Message = message,
DateTimeInUTC = DateTime.UtcNow,
Status = string.IsNullOrWhiteSpace(certificate) == true ? "Fail" : "Success"
};
return responseObject;
}
}
}
My sample JSON request:
{
"CommonName":"My Test CSR",
"Organization":"My Office",
"OrganizationalUnit":"My Department",
"CityOrLocality":"Sydney",
"StateOrProvince":"NSW",
"CountryOrRegion":"AU",
"KeySize":2048,
"ShouldReturnDummyData": false
}
Problem(s):
when "Cavium Key Storage Provider" or "RSA#Cavium Key Storage
Provider" is used to initialize objCSP, "Invalid provider
specified. (Exception from HRESULT: 0x80090013)" exception is thrown
when "Microsoft Enhanced Cryptographic Provider v1.0" is used to initialize objCSP, "CCertRequest::Submit: The RPC server is
unavailable. 0x800706ba" exception is thrown
To resolve the "The RPC server is unavailable" issue, I have followed the steps https://itworldjd.wordpress.com/2015/10/21/pki-certificates-troubleshooting-certificate-enrollment-rpc-server-is-unavailable/ but no luck.
I hit this error too. Hopefully someone can benefit from how I addressed it.
After requesting a new cert over web enrollment I also got the error.
CCertRequest::Submit: The RPC server is unavailable. 0x800706ba (WIN32: 1722 RPC_S_SERVER_UNAVAILABLE)
Without going into all the detail of DCOM permissions you need to ensure you are accessing the Certificate web server remotely and not locally from the CA server.

Create IExternalSignature with x509Certificate2 in C# and iText 7

I am testing the iText 7.1.2.0 library to sign pdf files, using a digital certificate or smart card (X509Certificate2) in a C # project. But I'm getting this error when I try to create the IExternalSignature.
According to the documentation found (here, here and here), the way to achieve this process is using the BouncyCastle library that allows extracting the primary keys from the digital certificate, however, it is giving me an error and I can not find another way to do it.
In the documentation (here) they are created from .pfx files, but for this case, I need to take the primary keys directly from the certificate in the card reader. In previous versions of iText, it's allowed the creation with the following command:
IExternalSignature externalSignature = new X509Certificate2Signature(Certificate, "SHA-1");
But in version 7 it is no longer available and in the documentation I do not see how to do it.
Someone has used iText 7 and has been able to sign using an X509Certificate2 that knows the correct way to create the IExternalSignature?
This is the code that I am using:
public void SignPDF(string source, string target, X509Certificate2 certificate, string reason, string location, bool addVisibleSign, bool addTimeStamp, string strTSA, int qtySigns, int pageNumber)
{
try
{
Org.BouncyCastle.X509.X509Certificate vert = Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(certificate);
X509CertificateParser objCP = new X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] objChain = new Org.BouncyCastle.X509.X509Certificate[] { objCP.ReadCertificate(certificate.RawData) };
IList<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(new CrlClientOnline(objChain));
PdfReader objReader = new PdfReader(source);
PdfSigner objStamper = new PdfSigner(objReader, new FileStream(target, FileMode.Create), false);
ITSAClient tsaClient = null;
IOcspClient ocspClient = null;
if (addTimeStamp)
{
OCSPVerifier ocspVerifier = new OCSPVerifier(null, null);
ocspClient = new OcspClientBouncyCastle(ocspVerifier);
tsaClient = new TSAClientBouncyCastle(strTSA);
}
PdfSignatureAppearance signatureAppearance = objStamper.GetSignatureAppearance();
signatureAppearance.SetReason(reason);
signatureAppearance.SetLocation(location);
signatureAppearance.SetPageNumber(pageNumber);
signatureAppearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION);
if (addVisibleSign && qtySigns == 1)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(36, 20, 144, 53)).SetPageNumber(pageNumber);
else if (addVisibleSign && qtySigns == 2)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(160, 20, 268, 53)).SetPageNumber(pageNumber);
else if (addVisibleSign && qtySigns == 3)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(284, 20, 392, 53)).SetPageNumber(pageNumber);
else if (addVisibleSign && qtySigns == 4)
signatureAppearance.SetPageRect(new iText.Kernel.Geom.Rectangle(408, 20, 516, 53)).SetPageNumber(pageNumber);
var pk = Org.BouncyCastle.Security.DotNetUtilities.GetKeyPair(certificate.PrivateKey).Private;
IExternalSignature externalSignature = new PrivateKeySignature(pk, "SHA-1");
objStamper.SignDetached(externalSignature, objChain, crlList, ocspClient, tsaClient, 0, PdfSigner.CryptoStandard.CMS);
if (objReader != null)
{
objReader.Close();
}
}
catch (Exception ex)
{
result.error = true;
result.errorMessage += "Error: " + ex.Message;
}
}
Thanks!
I do not believe that class was ported to iText 7- it is just a wrapper class.
You can see how to create a custom IExternalSignatureContainer in this example
Note that the source for the iText 5 X509Certificate2Signature can be found here
So something like this:
public class X509Certificate2Signature: IExternalSignature {
private String hashAlgorithm;
private String encryptionAlgorithm;
private X509Certificate2 certificate;
public X509Certificate2Signature(X509Certificate2 certificate, String hashAlgorithm) {
if (!certificate.HasPrivateKey)
throw new ArgumentException("No private key.");
this.certificate = certificate;
this.hashAlgorithm = DigestAlgorithms.GetDigest(DigestAlgorithms.GetAllowedDigest(hashAlgorithm));
if (certificate.PrivateKey is RSACryptoServiceProvider)
encryptionAlgorithm = "RSA";
else if (certificate.PrivateKey is DSACryptoServiceProvider)
encryptionAlgorithm = "DSA";
else
throw new ArgumentException("Unknown encryption algorithm " + certificate.PrivateKey);
}
public virtual byte[] Sign(byte[] message) {
if (certificate.PrivateKey is RSACryptoServiceProvider) {
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) certificate.PrivateKey;
return rsa.SignData(message, hashAlgorithm);
}
else {
DSACryptoServiceProvider dsa = (DSACryptoServiceProvider) certificate.PrivateKey;
return dsa.SignData(message);
}
}
public virtual String GetHashAlgorithm() {
return hashAlgorithm;
}
public virtual String GetEncryptionAlgorithm() {
return encryptionAlgorithm;
}
}
Will replicate the class' function in iText 7. How to use the class is shown here in my first link, though you most likely will be using the signDetached() method instead of the signDeffered() method.
The certificate.PrivateKey in my experience is not reliable when you're dealing with non-RSA key pairs. For example a certificate that has an ECDsa key-pair will throw a NotSupportedException("The certificate key algorithm is not supported") on calling .PrivateKey, don't know why (actually here's why, also probably useful). So I implemented a (little janky) workaround to retrieve the private key, and create an IExternalSignature out of it. Since the code has no knowledge of what type of key a certificate has, and I couldn't be bothered to process the other properties to find out, I wrote a loop that tries for a generic, RSA, DSA and ECDsa key extraction. The generic works for RSA too, but since X509Certificate2 has a GetRSAPrivateKey() method, I made a switch case for it just in case.
#nullable enable
private (IExternalSignature? signature, IDisposable? key) ExtractPrivateKey(X509Certificate2 certificate)
{
IExternalSignature? signature = null;
bool foundPk = false;
int attempt = 0;
IDisposable? key = null;
while (foundPk is false)
{
try
{
switch (attempt)
{
case 0:
AsymmetricAlgorithm? pk = certificate.PrivateKey; //throws exception when certificate has an ECDsa key
signature = new PrivateKeySignature(DotNetUtilities.GetKeyPair(pk).Private, _digestAlgorithm);
key = pk;
break;
case 1:
RSA rsa = certificate.GetRSAPrivateKey() ?? throw new NotSupportedException("RSA private key is null on the certificate.");
signature = new PrivateKeySignature(DotNetUtilities.GetRsaKeyPair(rsa).Private, _digestAlgorithm);
key = rsa;
break;
case 2:
DSA dsa = certificate.GetDSAPrivateKey() ?? throw new NotSupportedException("Dsa private key is null on the certificate.");
signature = new PrivateKeySignature(DotNetUtilities.GetDsaKeyPair(dsa).Private, _digestAlgorithm);
key = dsa;
break;
case 3:
ECDsa ecdsa = certificate.GetECDsaPrivateKey() ?? throw new NotSupportedException("ECDsa private key is null on the certificate.");
signature = new EcdsaSignature(ecdsa, _digestAlgorithm);
key = ecdsa;
break;
}
foundPk = true;
}
catch (Exception e)
{
_logger.LogDebug(e, $"Private key extraction ran into an exception. Attempt (zero-based): {attempt}");
}
attempt++;
}
if (signature == null)
{
throw new NotSupportedException(
$"The private key of the certificate could not be retrieved for signing. {JsonConvert.SerializeObject(certificate.SubjectName)}");
}
return (signature, key);
}
As you can see iText 7 has a handy utilities class, that contains a lot of util functions ported from the Java version, but for some reason only a lot, and not all of them. It doesn't support ECDsa key pairs, so I had to implement my own version of that. For completeness that class is included below.
#nullable enable
using System;
using System.Security.Cryptography;
using iText.Signatures;
public class EcdsaSignature : IExternalSignature
{
private readonly string _encryptionAlgorithm;
private readonly string _hashAlgorithm;
private readonly ECDsa _pk;
private const string EcdsaEncryptionAlgorithm = "ECDSA";
public EcdsaSignature(ECDsa? pk, string hashAlgorithm)
{
_pk = pk ?? throw new ArgumentNullException(nameof(pk), "ECDSA private key cannot be null.");
_hashAlgorithm = DigestAlgorithms.GetDigest(DigestAlgorithms.GetAllowedDigest(hashAlgorithm));
_encryptionAlgorithm = EcdsaEncryptionAlgorithm;
}
/// <summary>
/// <inheritDoc />
/// </summary>
public virtual string GetEncryptionAlgorithm()
{
return _encryptionAlgorithm;
}
/// <summary>
/// <inheritDoc />
/// </summary>
public virtual string GetHashAlgorithm()
{
return _hashAlgorithm;
}
/// <summary>
/// <inheritDoc />
/// </summary>
/// <remarks>
/// <see href="https://stackoverflow.com/a/67255440/6389395"> RFC 5480 format.</see>
/// </remarks>
public virtual byte[] Sign(byte[] message)
{
return _pk.SignData(message, new HashAlgorithmName(_hashAlgorithm), DSASignatureFormat.Rfc3279DerSequence);
}
}
Also note that the ExtractPrivateKey() method returns the key as an IDisposable as well, this is so it can be disposed of after the signature is done. I could have made a public property in EcdsaSignature, but iText's own IExternalSignatures don't expose the PK either, so neither should I.

Removing certificate from storage does not work

I'm trying to remove certificate from storage and using this function:
public static void RemoveFromStorage(StoreName storeName, IEnumerable<CertInfo> certificates)
{
var store = new X509Store(storeName, StoreLocation.CurrentUser);
store.Open(OpenFlags.MaxAllowed | OpenFlags.IncludeArchived);
foreach (var cert in certificates)
{
var toRemove = store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false);
store.Certificates.Remove(toRemove[0]);
}
store.Close();
}
Function doesn't throw any exception, Find function returns proper certificate from storage, but after calling Remove function it is not removed.
What am I doing wrong?
The store needs to be opened for ReadWrite.
Try this:
public static void RemoveFromStorage(StoreName storeName, IEnumerable<CertInfo> certificates)
{
var store = new X509Store(storeName, StoreLocation.CurrentUser);
store.Open(OpenFlags.MaxAllowed | OpenFlags.IncludeArchived | OpenFlags.ReadWrite);
foreach (var cert in certificates)
{
var toRemove = store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false);
store.Certificates.Remove(toRemove[0]);
}
store.Close();
}
The problem was this line
store.Certificates.Remove(toRemove[0]);
Correct is:
store.Remove(toRemove[0]);

C# RunAs /Smartcard

My application used to accept username/password to authenticate to a remote share (on Windows server) and then get the file listings etc.
public int ConnectNetResource(string server, string user, string password, ref string driveLeter) {
NETRESOURCE net = new NETRESOURCE();
net.dwScope = 0;
net.dwType = 0;
net.dwDisplayType = 0;
net.dwUsage = 0;
net.lpRemoteName = server;
net.lpLocalName = driveLeter;
net.lpProvider = null;
return WNetAddConnection2(ref net, password, user, 0);
}
Now, we need to authenticate using SmartCard. I have code to GetSmartCards, but I do not know how to make use of the certificate to authenticate.
public static X509Certificate2 GetClientCertificate()
{
X509Certificate2 certificate = null;
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
// Nothing to do if no cert found.
if (store.Certificates != null && store.Certificates.Count > 0)
{
if (store.Certificates.Count == 1)
{
// Return the certificate present.
certificate = store.Certificates[0];
}
else
{
// Request the user to select a certificate
var certificates = X509Certificate2UI.SelectFromCollection(store.Certificates, "Digital Certificates", "Select a certificate from the following list:", X509SelectionFlag.SingleSelection);
// Check if one has been returned
if (certificates != null && certificates.Count > 0)
certificate = certificates[0];
}
}
}
finally
{
store.Close();
}
return certificate;
}
GetClientCertificate function will return a user selected certificate, now HOW do I use this certificate to connect to a remote share. What API's or .dll can i use.
Btw, I am a windows engineer who can google code and make it work somehow. Will greatly appreciate a working code. Thank you.

Categories