Beispiel #1
0
        /// <summary>
        /// Lists the thumbprint value for each certificate in the specified store location which include "Key Encipherment" in its Key Usage extension
        /// </summary>
        /// <param name="Context">Store location from which to list certificate details (Either <see cref="X509Context.UserReadOnly"/> or <see cref="X509Context.SystemReadOnly"/>)</param>
        /// <param name="allowExpired">If set to True, expired certificates will be included in the output (Note that .NET will not perform cryptographic operations using a certificate which is not within its validity period)</param>
        /// <returns>A string expression listing all available certificate thumbprints and their expiration dates</returns>
        /// <example>
        /// <code>
        /// string availableCerts = <see cref="X509Utils"/>.<see cref="ListCerts"/>(<see cref="X509Context.UserReadOnly"/>);
        /// </code>
        /// </example>
        public static string ListCerts(X509Context Context = null, bool allowExpired = false)
        {
            if (Context == null)
            {
                Context = X509Context.UserReadOnly;
            }

            string output     = "Key Encipherment Certificates found:\r\n\r\n";
            bool   firstAdded = false;

            X509Store store = new X509Store(Context.Location);

            store.Open(OpenFlags.ReadOnly);
            foreach (X509Certificate2 cert in store.Certificates)
            {
                if (X509CryptoAgent.IsUsable(cert, allowExpired))
                {
                    firstAdded = true;
                    output    += cert.Subject + "\t" +
                                 string.Format("Expires {0}", cert.NotAfter.ToShortDateString()) + "\t" +
                                 cert.Thumbprint + "\r\n";
                }
            }

            if (!firstAdded)
            {
                output += "None.\r\n";
            }

            return(output);
        }
Beispiel #2
0
        private static X509Certificate2Collection GetCertificates(X509Context Context)
        {
            X509Store Store = new X509Store(Context.Location);

            Store.Open(OpenFlags.ReadOnly);
            return(Store.Certificates);
        }
Beispiel #3
0
 /// <summary>
 /// Encrypts the specified plaintext expression
 /// </summary>
 /// <param name="thumbprint">The thumbprint of the certificate to use for encryption</param>
 /// <param name="plaintext">The plaintext expression to encrypt</param>
 /// <param name="Context">The certificate store where the encryption certificate resides</param>
 /// <param name="verbose">True enables verbose logging</param>
 /// <returns></returns>
 /// <example>
 /// <code>
 /// string thumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
 /// <see cref="X509Context"/> certStore = <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>;
 /// string plaintext = @"Please encrypt this";
 /// string ciphertext = <see cref="X509Utils"/>.EncryptText(thumbprint, plaintext, certStore);
 /// </code>
 /// </example>
 public static string EncryptText(string thumbprint, string plaintext, X509Context Context, bool verbose = false)
 {
     using (X509CryptoAgent cryptoAgent = new X509CryptoAgent(FormatThumbprint(thumbprint), Context))
     {
         return(cryptoAgent.EncryptText(plaintext));
     }
 }
        /// <summary>
        /// Lists the thumbprint value for all encryption certificates which exist in the specified store location. Certificates which do not have the "Key Encipherment" key usage flag set are not included in the list.
        /// </summary>
        /// <param name="Context">The X509Context from which to list certificates</param>
        /// <param name="includeExpired">If true, expired certificates will be included in the resulting list</param>
        /// <returns>Line-break-separated list of certificate details</returns>
        public static string ListCerts(X509Context Context, bool includeExpired = false)
        {
            StringBuilder expression = new StringBuilder($"Key Encipherment certificates found in {Context.Name} context:\r\n\r\n");
            bool          firstAdded = false;

            List <X509Alias> Aliases           = Context.GetAliases();
            X509Alias        AssignedAlias     = null;
            string           assignedAliasName = string.Empty;

            X509Store Store = new X509Store(Context.Location);

            Store.Open(OpenFlags.ReadOnly);
            foreach (X509Certificate2 cert in Store.Certificates)
            {
                if (IsUsable(cert, includeExpired))
                {
                    if (!firstAdded)
                    {
                        expression.AppendLine(ListCertFormat.HeaderRow);
                        firstAdded = true;
                    }

                    AssignedAlias     = Aliases.FirstOrDefault(p => p.Thumbprint.Matches(cert.Thumbprint));
                    assignedAliasName = AssignedAlias == null ? Constants.NoAliasAssigned : AssignedAlias.Name;
                    expression.AppendLine($"{cert.Thumbprint.LeftAlign(Padding.Thumbprint)}   {assignedAliasName.LeftAlign(Padding.Assigned_Alias)}   {cert.NotAfter.ToString(Constants.DateFormat)}");
                }
            }

            if (!firstAdded)
            {
                expression.AppendLine(@"None.");
            }

            return(expression.ToString());
        }
Beispiel #5
0
        /// <summary>
        /// This constructor is intended to load an already-existing X509Alias
        /// </summary>
        /// <param name="Name">The desired identifier for the alias (must be unique within the specified context</param>
        /// <param name="Context">The context in which to create the alias</param>
        public X509Alias(string Name, X509Context Context)
            : this(Context)
        {
            this.Name = Name;

            if (!LoadIfExists(false))
            {
                throw new X509AliasNotFoundException(this);
            }
        }
Beispiel #6
0
        internal static string GetOne(string thumbprint, X509Context Context)
        {
            foreach (X509Alias Alias in Context.GetAliases())
            {
                if (Alias.Thumbprint.Matches(thumbprint))
                {
                    return(Alias.Name);
                }
            }

            throw new X509AliasNotFoundException(thumbprint, Context);
        }
        /// <summary>
        /// Exports the encryption certificate and corresponding key pair to a file in PKCS#12 format
        /// </summary>
        /// <param name="thumbprint">The thumbprint of the encryption certificate</param>
        /// <param name="Context">The X509Context where the certificate and corresponding key pair exist</param>
        /// <param name="pfxPath">The path to where the PKCS#12 file should be written</param>
        /// <param name="password">The password which will protect the PKCS#12 file</param>
        public static void ExportPFX(string thumbprint, X509Context Context, string pfxPath, string password)
        {
            if (File.Exists(pfxPath))
            {
                File.Delete(pfxPath);
            }

            X509Certificate2 Cert = Util.GetCertByThumbprint(thumbprint, Context);

            byte[] certBytes = Cert.Export(X509ContentType.Pkcs12, password);
            File.WriteAllBytes(pfxPath, certBytes);
            Util.VerifyFileExists(pfxPath);
        }
Beispiel #8
0
        /// <summary>
        /// This constructor is intended to create a new X509Alias pointing to the specified encryption certificate
        /// </summary>
        /// <param name="Name">The desired identifier for the alias</param>
        /// <param name="Thumbprint">The SHA1 thumbprint of the certificate to be used for cryptographic operations. Must exist in the specified Context</param>
        /// <param name="Context">The context in which to create the alias</param>
        /// <param name="complainIfExists">If set to true, an exception is thrown if an existing alias identifier is specified for "Name"</param>
        public X509Alias(string Name, string Thumbprint, X509Context Context, bool complainIfExists)
            : this(Context)
        {
            this.Name       = Name;
            this.Thumbprint = Thumbprint;

            LoadIfExists(complainIfExists);

            if (!X509CryptoAgent.CertificateExists(Thumbprint, Context))
            {
                throw new X509CryptoCertificateNotFoundException(Thumbprint, Context);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Exports the certificate corresponding to the specified certificate thumbprint to a Base64-encoded text file
        /// </summary>
        /// <param name="certThumbprint">Certificate thumbprint (case-insensitive)</param>
        /// <param name="exportPath">Fully-qualified path to where the Base64-encoded file should be written (a ".cer" file extension will be added if no file extension is detected)</param>
        /// <param name="Context">(Optional) The certificate store where the encryption certificate resides (Default: <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>)</param>
        /// <param name="verbose">True enables verbose logging</param>
        /// <returns>The fully-qualified path to where the Base64-encoded certificate file was ultimately written</returns>
        /// <example>
        /// <code>
        /// string thumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
        /// string exportPath = @"C:\data\cert";
        /// <see cref="X509Context"/> certStore = <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>;
        /// string finalExportPath = <see cref="X509Utils"/>.ExportCert(thumbprint, exportPath, certStore);
        /// //finalExportPath is @"C:\data\cert.cer"
        /// </code>
        /// </example>
        public static string ExportCert(string certThumbprint, string exportPath, X509Context Context = null, bool verbose = false)
        {
            if (Context == null)
            {
                Context = X509Context.UserReadOnly;
            }

            if (!Path.HasExtension(exportPath))
            {
                exportPath += @".cer";
            }

            if (!File.Exists(exportPath))
            {
                File.Delete(exportPath);
            }

            certThumbprint = FormatThumbprint(certThumbprint, verbose);
            X509Store store = new X509Store(StoreName.My, Context.Location);

            store.Open(OpenFlags.ReadOnly);

            foreach (X509Certificate2 cert in store.Certificates)
            {
                if (string.Equals(certThumbprint, cert.Thumbprint, StringComparison.OrdinalIgnoreCase))
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine(@"-----BEGIN CERTIFICATE-----");
                    sb.AppendLine(Convert.ToBase64String(cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks));
                    sb.AppendLine(@"-----END CERTIFICATE-----");
                    File.WriteAllText(exportPath, sb.ToString());
                    sb = null;

                    VerifyFile(exportPath);

                    try
                    {
                        X509Certificate2 test = new X509Certificate2(exportPath);
                    }
                    catch (CryptographicException ex)
                    {
                        throw new X509CryptoException($"Certificate with thumbprint {certThumbprint} was exported to path \"{exportPath}\" but the file seems to be corrupt and unusable", ex);
                    }

                    return(exportPath);
                }
            }

            throw new X509CryptoCertificateNotFoundException(certThumbprint, Context);
        }
Beispiel #10
0
        public static X509Certificate2 GetCertByThumbprint(string thumbprint, X509Context Context)
        {
            thumbprint = thumbprint.RemoveNonHexChars();

            X509Store Store = new X509Store(StoreName.My, Context.Location);

            Store.Open(OpenFlags.ReadOnly);
            foreach (X509Certificate2 cert in Store.Certificates)
            {
                if (cert.Thumbprint.Matches(thumbprint))
                {
                    return(cert);
                }
            }

            throw new X509CryptoCertificateNotFoundException(thumbprint, Context);
        }
        /// <summary>
        /// Indicates whether the certificate with the specified thumbprint was found in the specified certificate store
        /// </summary>
        /// <param name="certThumbprint">The certificate thumbprint value to search for (case-insensitive)</param>
        /// <param name="Context">The certificate store from which to load the encryption certificate.  Either CertStore.CurrentUser (default) or CertStore.LocalMachine</param>
        /// <returns>True or False depending upon whether the certificate and corresponding private key was found in the certificate store</returns>
        /// <example>
        /// <code>
        /// string thumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
        /// <see cref="X509Context"/> certStore = <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>;
        ///
        /// bool found;
        ///
        /// using (<see cref="X509CryptoAgent"/> agent = new <see cref="X509CryptoAgent"/>(thumbprint, certStore))
        /// {
        ///     found = agent.CertificateExists(thumbprint, certStore);
        /// }
        /// </code>
        /// </example>
        public static bool CertificateExists(string certThumbprint, X509Context Context)
        {
            certThumbprint = certThumbprint.RemoveNonHexChars();

            X509Store store = new X509Store(StoreName.My, Context.Location);

            store.Open(OpenFlags.ReadOnly);
            foreach (X509Certificate2 cert in store.Certificates)
            {
                if (cert.Thumbprint.Matches(certThumbprint) && IsUsable(cert, true))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #12
0
        /// <summary>
        /// Imports the X509Alias from the specified Json file
        /// Note: This method does not import the encryption certificate or its associated key pair needed to work with the X509Alias.
        /// </summary>
        /// <param name="importPath">The path where the json file is located</param>
        /// <param name="Context">The X509Context in which to load the alias</param>
        /// <param name="newName">If specified, the alias will be identified by the specified expression. Otherwise, the alias name imported from the json file will be used.</param>
        /// <returns></returns>
        public static X509Alias Import(string importPath, X509Context Context, string newName = "")
        {
            if (!File.Exists(importPath))
            {
                throw new FileNotFoundException(importPath);
            }

            try
            {
                X509Alias Alias = new X509Alias(Context);
                Alias.DecodeFromFile(importPath, newName);
                return(Alias);
            }
            catch (Exception ex)
            {
                throw new X509CryptoException($"Unable to import X509Alias from path {importPath}", ex);
            }
        }
Beispiel #13
0
        public bool HasCert(X509Context Context)
        {
            bool found = false;

            using (var Store = new X509Store(Context.Location))
            {
                Store.Open(OpenFlags.ReadOnly);
                foreach (var Cert in Store.Certificates)
                {
                    if (Cert.Thumbprint.Matches(Thumbprint))
                    {
                        found = true;
                        break;
                    }
                }
            }
            return(found);
        }
Beispiel #14
0
        /// <summary>
        /// Installs an encryption certificate and associated key pair in the specified X509Context
        /// </summary>
        /// <param name="infile">The PKCS#12 (usually with a .pfx or .p12 extension) containing the bundled certificate and key pair</param>
        /// <param name="PfxPassword">The password to unlock the PKCS#12 file</param>
        /// <param name="Context">The X509Context in which to place the certificate and key pair</param>
        /// <returns></returns>
        public static string InstallCert(string infile, SecureString PfxPassword, X509Context Context)
        {
            bool certInstalled = false;
            X509Certificate2Collection certCol = new X509Certificate2Collection();
            X509Store keyChain;
            string    thumbprint = string.Empty;

            try
            {
                certCol.Import(infile, PfxPassword.Plaintext(), X509KeyStorageFlags.PersistKeySet);
                keyChain = new X509Store(StoreName.My, Context.Location);
                keyChain.Open(OpenFlags.ReadWrite);

                foreach (X509Certificate2 cert in certCol)
                {
                    if (X509CryptoAgent.IsUsable(cert, Constants.ProbeMode))
                    {
                        keyChain.Add(cert);
                        if (Context.Index == X509Context.Indexer.SystemFull || Context.Index == X509Context.Indexer.SystemReadOnly)
                        {
                            AddIISKeyAccess(cert.Thumbprint);
                        }
                        certInstalled = true;
                        thumbprint    = cert.Thumbprint;
                        break;
                    }
                }
                if (!certInstalled)
                {
                    throw new X509CryptoException($"The PKCS#12 file {Path.GetFileName(infile).InQuotes()} did not contain a valid encryption certificate");
                }
                else
                {
                    return(thumbprint);
                }
            }
            finally
            {
                certCol  = null;
                keyChain = null;
            }
        }
Beispiel #15
0
        /// <summary>
        /// Updates this X509Alias to use a new encryption certificate and key pair. The old certificate and key pair must still be available to perform this operation.
        /// </summary>
        /// <param name="newThumbprint">The SHA1 thumbprint of the new encryption certificate. The certificate and associated key pair must exist and be available in the specified X509Context</param>
        /// <param name="newContext">The X509Context where the new encryption certificate and key pair is located</param>
        public void ReEncrypt(string newThumbprint, X509Context newContext = null)
        {
            if (newContext == null)
            {
                newContext = Context;
            }

            newThumbprint = newThumbprint.RemoveNonHexChars();
            if (!X509CryptoAgent.CertificateExists(newThumbprint, newContext))
            {
                throw new X509CryptoException($"A valid encryption certificate with thumbprint {newThumbprint} was not found in the {Context.Name} context");
            }

            foreach (X509Secret secret in Secrets)
            {
                secret.ReEncrypt(this, newThumbprint, newContext);
            }

            Thumbprint = newThumbprint;
            Context    = newContext;
            Commit();
        }
Beispiel #16
0
        /// <summary>
        /// Encrypts the specified file
        /// </summary>
        /// <param name="thumbprint">The thumbprint of the certificate to use for encryption</param>
        /// <param name="plaintextFilePath">The fully-qualified path of the plaintext file (can be text or binary)</param>
        /// <param name="Context">(Optional) The certificate store where the encryption certificate resides (Default: <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>)</param>
        /// <param name="ciphertextFilePath">(Optional) The fully-qualified path in which to write the encrypted file (If not specified, the plaintext file path is appended with a ".ctx" extension)</param>
        /// <param name="verbose">(Optional) True enables verbose logging</param>
        /// <returns></returns>
        /// <example>
        /// <code>
        /// string thumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
        /// <see cref="X509Context"/> certStore = <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>
        /// string plaintextFilePath = @"C:\Data\accounts.csv";
        /// string ciphertextFilePath =
        /// bool success = <see cref="X509Utils"/>.EncryptFile(thumbprint, plaintextFilePath, certStore);
        /// </code>
        /// </example>
        public static bool EncryptFile(string thumbprint, string plaintextFilePath, X509Context Context = null, string ciphertextFilePath = "", bool verbose = false)
        {
            CheckForFile(plaintextFilePath);

            if (Context == null)
            {
                Context = X509Context.UserReadOnly;
            }

            if (string.IsNullOrEmpty(ciphertextFilePath))
            {
                ciphertextFilePath = plaintextFilePath + CRYPTO_ENCRYPTED_FILE_EXT;
            }
            File.Delete(ciphertextFilePath);

            using (X509CryptoAgent cryptoAgent = new X509CryptoAgent(FormatThumbprint(thumbprint), Context))
            {
                cryptoAgent.EncryptFile(plaintextFilePath, ciphertextFilePath);
            }

            return(File.Exists(ciphertextFilePath));
        }
        /// <summary>
        /// Lists all aliases that are found in the specified X509Context
        /// </summary>
        /// <param name="Context">The X509Context from which to list existing aliases</param>
        /// <returns>Line-break-separated list of X509Alias details</returns>
        public static string ListAliases(X509Context Context)
        {
            StringBuilder expression = new StringBuilder($"X509Aliases found in the {Context.Name} context:\r\n\r\n");
            bool          firstAdded = false;
            Dictionary <string, X509Certificate2> Aliases = X509Alias.GetAll(Context);

            foreach (KeyValuePair <string, X509Certificate2> Alias in Aliases)
            {
                if (!firstAdded)
                {
                    expression.AppendLine(ListAliasFormat.HeaderRow);
                    firstAdded = true;
                }
                expression.AppendLine($"{Alias.Key.LeftAlign(Padding.Alias)}   {Alias.Value.Thumbprint.LeftAlign(Padding.Thumbprint)}   {Alias.Value.NotAfter.ToString(Constants.DateFormat)}");
            }

            if (!firstAdded)
            {
                expression.AppendLine(@"None.");
            }

            return(expression.ToString());
        }
        /// <summary>
        /// Exports the public certificate corresponding to the specified certificate thumbprint to a Base64-encoded file
        /// </summary>
        /// <param name="thumbprint">Thumbprint of the certificate to be exported</param>
        /// <param name="Context">The X509Context where the certificate to be exported exists</param>
        /// <param name="path">The storage path to where the file containing the public certificate should be written</param>
        public static void ExportCert(string thumbprint, X509Context Context, string path)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
            }

            X509Certificate2 Cert = Util.GetCertByThumbprint(thumbprint, Context);
            StringBuilder    sb   = new StringBuilder(Constants.BeginBase64Certificate);

            sb.AppendLine(Convert.ToBase64String(Cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks));
            sb.AppendLine(Constants.EndBase64Certificate);
            File.WriteAllText(path, sb.ToString());
            Util.VerifyFileExists(path);

            try
            {
                X509Certificate2 test = new X509Certificate2(path);
            }
            catch (CryptographicException ex)
            {
                throw new X509CryptoException($"Public certificate with thumbprint {thumbprint} was exported to file path \"{path}\" but the file contents are not usable", ex);
            }
        }
Beispiel #19
0
        internal static Dictionary <string, X509Certificate2> GetAll(X509Context Context)
        {
            Dictionary <string, X509Certificate2> Aliases   = new Dictionary <string, X509Certificate2>();
            X509Certificate2Collection            CertStore = GetCertificates(Context);

            X509Alias CurrentAlias;

            foreach (string aliasName in Context.GetAliasNames())
            {
                CurrentAlias = new X509Alias(aliasName, Context);
                if (X509CryptoAgent.CertificateExists(CurrentAlias.Thumbprint, Context))
                {
                    foreach (X509Certificate2 Cert in CertStore)
                    {
                        if (Cert.Thumbprint.Matches(CurrentAlias.Thumbprint))
                        {
                            Aliases.Add(aliasName, Cert);
                            break;
                        }
                    }
                }
            }
            return(Aliases);
        }
Beispiel #20
0
 /// <summary>
 /// Returns true if this X509Context represents a local system context
 /// </summary>
 /// <param name="Context">an X509Context object</param>
 /// <returns>true if this X509Context represents a local system context</returns>
 public static bool IsSystemContext(this X509Context Context)
 {
     return(Context == X509Context.SystemFull || Context == X509Context.SystemReadOnly);
 }
Beispiel #21
0
 /// <summary>
 /// Returns true if this X509Context represents a user context
 /// </summary>
 /// <param name="Context">an X509Context object</param>
 /// <returns>true if this X509Context represents a user context</returns>
 public static bool IsUserContext(this X509Context Context)
 {
     return(Context == X509Context.UserFull || Context == X509Context.UserReadOnly);
 }
Beispiel #22
0
 /// <summary>
 /// Instantiates an X509CryptoCertificateNotFoundException
 /// </summary>
 /// <param name="thumbprint">The thumbprint of the certificate which could not be located in the specified X509Context</param>
 /// <param name="Context">The X509Context which was checked for the encryption certificate</param>
 public X509CryptoCertificateNotFoundException(string thumbprint, X509Context Context)
     : base($"A certificate with thumbprint \"{thumbprint}\" was not found in the \"{Context.Name}\" context.")
 {
 }
Beispiel #23
0
        internal void ReEncrypt(X509Alias Alias, string newThumbprint, X509Context newContext)
        {
            string newValue = X509Utils.ReEncryptText(Alias.Thumbprint, newThumbprint, Value, Alias.Context, newContext);

            Value = newValue;
        }
Beispiel #24
0
        /// <summary>
        /// Exports the certificate and public/private key pair corresponding to the specified certificate thumbprint to a PKCS#12 bundle written to the specified file path
        /// </summary>
        /// <param name="certThumbprint">Certificate thumbprint (case-insensitive)</param>
        /// <param name="exportPath">Fully-qualified path to where the PKCS#12 bundle file should be written (a ".pfx" file extension will be added if no file extension is detected)</param>
        /// <param name="password">Password to protect the private key once stored in the PKCS#12 bundle file</param>
        /// <param name="Context">(Optional) The certificate store where the encryption certificate resides (Default: <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>)</param>
        /// <param name="verbose">(Optional) True enables verbose logging (Default: false)</param>
        /// <returns>The fully-qualified path to where the PKCS#12 bundle file was ultimately written</returns>
        /// <example>
        /// <code>
        /// string thumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
        /// string exportPath = @"C:\data\bundle";
        /// string password = @"0n3T!m3U$e";
        /// <see cref="X509Context"/> certStore = <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>;
        /// string finalExportPath = <see cref="X509Utils"/>.ExportPFX(thumbprint, exportPath, password, certStore);
        /// //finalExportPath is @"C:\data\bundle.pfx"
        /// </code>
        /// </example>
        public static string ExportPFX(string certThumbprint, string exportPath, string password, X509Context Context = null, bool verbose = false)
        {
            if (Context == null)
            {
                Context = X509Context.UserReadOnly;
            }

            if (!Path.HasExtension(exportPath))
            {
                exportPath += @".pfx";
            }

            if (File.Exists(exportPath))
            {
                File.Delete(exportPath);
            }

            certThumbprint = FormatThumbprint(certThumbprint, verbose);

            X509Store store = new X509Store(StoreName.My, Context.Location);

            store.Open(OpenFlags.ReadOnly);
            foreach (X509Certificate2 cert in store.Certificates)
            {
                if (string.Equals(certThumbprint, cert.Thumbprint, StringComparison.OrdinalIgnoreCase))
                {
                    byte[] certBytes = cert.Export(X509ContentType.Pkcs12, password);
                    File.WriteAllBytes(exportPath, certBytes);
                    X509Utils.VerifyFile(exportPath);
                    return(exportPath);
                }
            }

            throw new X509CryptoCertificateNotFoundException(certThumbprint, Context);
        }
 /// <summary>
 /// X509CryptoAgent Constructor
 /// </summary>
 /// <param name="thumbprint">The thumbprint of the encryption certificate.  The certificate must be present in the CURRENTUSER store location</param>
 /// <param name="context">The X509Context where the encryption certificate can be accessed</param>
 public X509CryptoAgent(string thumbprint, X509Context context)
 {
     Thumbprint = thumbprint.RemoveNonHexChars();
     Context    = context;
     GetRSAKeys(Thumbprint);
 }
Beispiel #26
0
 internal X509AliasNotFoundException(string thumbprint, X509Context Context)
     : base($"No {nameof(X509Alias)} exists in the {Context.Name} {nameof(X509Context)} containing an encryption certificate with thumbprint {thumbprint.InQuotes()}")
 {
 }
Beispiel #27
0
        /// <summary>
        /// Re-encrypts an encrypted file using a different encryption certificate
        /// </summary>
        /// <param name="oldThumbprint">The thumbprint of the old certificate used for prior encryption</param>
        /// <param name="newThumbprint">The thumbprint of the new certificate to be used for re-encryption</param>
        /// <param name="ciphertextFilePath">The fully-qualified path to the ciphertext file to be re-encrypted</param>
        /// <param name="OldContext">(Optional) The certificate store where the old encryption certificate resides (Default: <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>)</param>
        /// <param name="NewContext">(Optional) The certificate store where the new encryption certificate resides (Default: <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>)</param>
        /// <param name="verbose">(Optional) True enables verbose logging (Default: false)</param>
        /// <example>
        /// <code>
        /// string oldThumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
        /// string newThumbprint = @"0e7e327aab74e47a702c02d90c659da1115b29f7";
        /// string encryptedFilePath = @"C:\data\accounts.csv.ctx";
        /// <see cref="X509Utils"/>.ReEncryptFile"(oldThumbprint, newThumbprint, encryptedFilePath);
        /// </code>
        /// </example>
        public static void ReEncryptFile(string oldThumbprint, string newThumbprint, string ciphertextFilePath, X509Context OldContext = null, X509Context NewContext = null, bool verbose = false)
        {
            CheckForFile(ciphertextFilePath);

            if (OldContext == null)
            {
                OldContext = X509Context.UserReadOnly;
            }
            if (NewContext == null)
            {
                NewContext = X509Context.UserReadOnly;
            }

            byte[] hashOrig,
            hashCopy;

            string tmpCopy;

            hashOrig = Hash(ciphertextFilePath);
            tmpCopy  = string.Format(@"{0}\cryptotmp_{1}", Path.GetDirectoryName(ciphertextFilePath), Rnd(6));
            File.Copy(ciphertextFilePath, tmpCopy);
            hashCopy = Hash(tmpCopy);

            if (hashOrig.SequenceEqual(hashCopy))
            {
                File.Delete(ciphertextFilePath);
            }
            else
            {
                try { File.Delete(tmpCopy); } catch { }
                throw new Exception(string.Format("Could not back up original file \"{0}\"", ciphertextFilePath));
            }

            try
            {
                using (X509CryptoAgent oldAgent = new X509CryptoAgent(oldThumbprint.RemoveNonHexChars(), OldContext))
                {
                    byte[] data = oldAgent.DecryptFileToByteArray(tmpCopy);

                    using (X509CryptoAgent newAgent = new X509CryptoAgent(newThumbprint.RemoveNonHexChars(), NewContext))
                    {
                        newAgent.EncryptFileFromByteArray(data, ciphertextFilePath);
                    }
                }

                if (!File.Exists(ciphertextFilePath))
                {
                    throw new FileNotFoundException($"\"{ciphertextFilePath}\": File not found after cryptographic operation. Restoring original");
                }
            }
            catch (Exception ex)
            {
                if (File.Exists(ciphertextFilePath))
                {
                    if (!Hash(ciphertextFilePath).SequenceEqual(hashCopy))
                    {
                        File.Delete(ciphertextFilePath);
                        File.Copy(tmpCopy, ciphertextFilePath);
                    }
                }
                else
                {
                    File.Copy(tmpCopy, ciphertextFilePath);
                }

                throw ex;
            }
        }
Beispiel #28
0
        /// <summary>
        /// Re-encrypts a ciphertext expression using a different certificate
        /// </summary>
        /// <param name="oldThumbprint">The thumbprint of the old certificate used for prior encryption</param>
        /// <param name="newThumbprint">The thumbprint of the new certificate to be used for re-encryption</param>
        /// <param name="ciphertext">The ciphertext expression to be re-encrypted</param>
        /// <param name="OldContext">(Optional) The X509Context where the old encryption certificate resides (Default: <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>)</param>
        /// <param name="NewContext">(Optional) The X509Context where the new encryption certificate resides (Default: <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>)</param>
        /// <param name="verbose">(Optional) True enables verbose logging (Default: false)</param>
        /// <returns>The text expression re-encrypted using the new certificate</returns>
        /// <example>
        /// <code>
        /// string oldThumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
        /// string newThumbprint = @"0e7e327aab74e47a702c02d90c659da1115b29f7";
        /// string ciphertext = File.ReadAllText(@"C:\data\connectionString.txt");
        /// string updatedCiphertext = <see cref="X509Utils"/>.ReEncryptText(oldThumbprint, newThumbprint, ciphertext);
        /// File.WriteAllText(@"C:\data\connectionString.txt", updatedCiphertext);
        /// </code>
        /// </example>
        public static string ReEncryptText(string oldThumbprint, string newThumbprint, string ciphertext, X509Context OldContext = null, X509Context NewContext = null, bool verbose = false)
        {
            if (OldContext == null)
            {
                OldContext = X509Context.UserReadOnly;
            }
            if (NewContext == null)
            {
                NewContext = X509Context.UserReadOnly;
            }

            using (X509CryptoAgent oldAgent = new X509CryptoAgent(FormatThumbprint(oldThumbprint), OldContext))
            {
                using (X509CryptoAgent newAgent = new X509CryptoAgent(FormatThumbprint(newThumbprint), NewContext))
                {
                    return(newAgent.EncryptText(oldAgent.DecryptText(ciphertext)));
                }
            }
        }
Beispiel #29
0
 private X509Alias(X509Context Context)
 {
     this.Context = Context;
 }
Beispiel #30
0
        /// <summary>
        /// Decrypts the specified encrypted file
        /// </summary>
        /// <param name="thumbprint">The thumbprint of the certificate corresponding to the public key used to encrypt the file</param>
        /// <param name="ciphertextFilePath">The fully-qualified path of the encrypted file</param>
        /// <param name="plaintextFilePath">The fully-qualified path in which to write the decrypted file</param>
        /// <param name="Context">The certificate store where the encryption certificate resides</param>
        /// <param name="verbose">True enables verbose logging</param>
        /// <returns>True or false depending upon whether the file decryption succeeded</returns>
        /// <example>
        /// <code>
        /// string thumbprint = @"ccdc673c40ebb2a433300c0c8a2ba6f443da5688";
        /// <see cref="X509Context"/> certStore = <see cref="X509Context"/>.<see cref="X509Context.UserReadOnly"/>;
        /// string encryptedFilePath = @"C:\Data\accounts.csv.ctx";
        /// bool success = <see cref="X509Utils"/>.DecryptFile(thumbprint, encryptedFilePath, certStore);
        /// </code>
        /// </example>
        public static bool DecryptFile(string thumbprint, string ciphertextFilePath, string plaintextFilePath, X509Context Context, bool verbose = false)
        {
            CheckForFile(ciphertextFilePath);

            File.Delete(plaintextFilePath);

            using (X509CryptoAgent cryptoAgent = new X509CryptoAgent(FormatThumbprint(thumbprint), Context))
            {
                cryptoAgent.DecryptFile(ciphertextFilePath, plaintextFilePath);
            }

            return(File.Exists(plaintextFilePath));
        }