private static X509Certificate2Collection LoadCertificateFromStore(CertificateSourceOptions options) { X509Certificate2Collection resultCollection = null; var store = new X509Store(options.StoreName, options.StoreLocation); OpenStore(store); // Passing true for validOnly seems like a good idea; it would filter out invalid certificates. // However, "invalid certificates" is a broad category that includes untrusted self-issued certificates. // Untrusted self-issued certificates are permitted at signing time, so we must perform certificate // validity checks ourselves. const bool validOnly = false; if (!string.IsNullOrEmpty(options.Fingerprint)) { resultCollection = store.Certificates.Find(X509FindType.FindByThumbprint, options.Fingerprint, validOnly); } else if (!string.IsNullOrEmpty(options.SubjectName)) { resultCollection = store.Certificates.Find(X509FindType.FindBySubjectName, options.SubjectName, validOnly); } #if IS_DESKTOP store.Close(); #endif resultCollection = resultCollection ?? new X509Certificate2Collection(); resultCollection = GetValidCertificates(resultCollection); return(resultCollection); }
private static async Task <X509Certificate2> GetCertificateAsync(SignArgs signArgs) { var certFindOptions = new CertificateSourceOptions() { CertificatePath = signArgs.CertificatePath, CertificatePassword = signArgs.CertificatePassword, Fingerprint = signArgs.CertificateFingerprint, StoreLocation = signArgs.CertificateStoreLocation, StoreName = signArgs.CertificateStoreName, SubjectName = signArgs.CertificateSubjectName, NonInteractive = signArgs.NonInteractive, PasswordProvider = signArgs.PasswordProvider, Token = signArgs.Token }; // get matching certificates var matchingCertCollection = await CertificateProvider.GetCertificatesAsync(certFindOptions); if (matchingCertCollection.Count > 1) { #if IS_DESKTOP if (signArgs.NonInteractive || !RuntimeEnvironmentHelper.IsWindows) { // if on non-windows os or in non interactive mode - display the certs and error out signArgs.Logger.LogInformation(CertificateUtility.X509Certificate2CollectionToString(matchingCertCollection, HashAlgorithmName.SHA256)); throw new SignCommandException( LogMessage.CreateError(NuGetLogCode.NU3001, string.Format(Strings.SignCommandMultipleCertException, nameof(SignArgs.CertificateFingerprint)))); } else { // Else launch UI to select matchingCertCollection = X509Certificate2UI.SelectFromCollection( FilterCodeSigningCertificates(matchingCertCollection), Strings.SignCommandDialogTitle, Strings.SignCommandDialogMessage, X509SelectionFlag.SingleSelection); } #else // if on non-windows os or in non interactive mode - display and error out signArgs.Logger.LogError(CertificateUtility.X509Certificate2CollectionToString(matchingCertCollection, HashAlgorithmName.SHA256)); throw new SignCommandException( LogMessage.CreateError(NuGetLogCode.NU3001, string.Format(Strings.SignCommandMultipleCertException, nameof(SignArgs.CertificateFingerprint)))); #endif } if (matchingCertCollection.Count == 0) { throw new SignCommandException( LogMessage.CreateError(NuGetLogCode.NU3001, Strings.SignCommandNoCertException)); } return(matchingCertCollection[0]); }
/// <summary> /// Looks for X509Certificates using the CertificateSourceOptions. /// Throws an InvalidOperationException if the option specifies a CertificateFilePath with invalid password. /// </summary> /// <param name="options">CertificateSourceOptions to be used while searching for the certificates.</param> /// <returns>An X509Certificate2Collection object containing matching certificates. /// If no matching certificates are found then it returns an empty collection.</returns> public static async Task <X509Certificate2Collection> GetCertificatesAsync(CertificateSourceOptions options) { // check certificate path var resultCollection = new X509Certificate2Collection(); if (!string.IsNullOrEmpty(options.CertificatePath)) { try { var cert = await LoadCertificateFromFileAsync(options); resultCollection = new X509Certificate2Collection(cert); } catch (CryptographicException ex) { switch (ex.HResult) { case ERROR_INVALID_PASSWORD_HRESULT: case OPENSSL_PKCS12_R_MAC_VERIFY_FAILURE: throw new SignCommandException( LogMessage.CreateError(NuGetLogCode.NU3001, string.Format(CultureInfo.CurrentCulture, Strings.SignCommandInvalidPasswordException, options.CertificatePath, nameof(options.CertificatePassword)))); case ERROR_FILE_NOT_FOUND_HRESULT: case OPENSSL_BIO_R_NO_SUCH_FILE: throw new SignCommandException( LogMessage.CreateError(NuGetLogCode.NU3001, string.Format(CultureInfo.CurrentCulture, Strings.SignCommandCertificateFileNotFound, options.CertificatePath))); case CRYPT_E_NO_MATCH_HRESULT: case OPENSSL_ERR_R_NESTED_ASN1_ERROR: throw new SignCommandException( LogMessage.CreateError(NuGetLogCode.NU3001, string.Format(CultureInfo.CurrentCulture, Strings.SignCommandInvalidCertException, options.CertificatePath))); default: throw; } } } else { resultCollection = LoadCertificateFromStore(options); } return(resultCollection); }
private static X509Certificate2Collection LoadCertificateFromStore(CertificateSourceOptions options) { var resultCollection = new X509Certificate2Collection(); var store = new X509Store(options.StoreName, options.StoreLocation); OpenStore(store); if (!string.IsNullOrEmpty(options.Fingerprint)) { resultCollection = store.Certificates.Find(X509FindType.FindByThumbprint, options.Fingerprint, validOnly: true); } else if (!string.IsNullOrEmpty(options.SubjectName)) { resultCollection = store.Certificates.Find(X509FindType.FindBySubjectName, options.SubjectName, validOnly: true); } #if IS_DESKTOP store.Close(); #endif return(resultCollection); }
private static async Task <X509Certificate2> LoadCertificateFromFileAsync(CertificateSourceOptions options) { X509Certificate2 cert; if (!string.IsNullOrEmpty(options.CertificatePassword)) { cert = new X509Certificate2(options.CertificatePath, options.CertificatePassword); // use the password if the user provided it. } else { #if IS_DESKTOP try { cert = new X509Certificate2(options.CertificatePath); } catch (CryptographicException ex) { // prompt user for password if needed if (ex.HResult == ERROR_INVALID_PASSWORD_HRESULT && !options.NonInteractive) { using (var password = await options.PasswordProvider.GetPassword(options.CertificatePath, options.Token)) { cert = new X509Certificate2(options.CertificatePath, password); } } else { throw; } } #else cert = new X509Certificate2(options.CertificatePath); #endif } return(cert); }