/// <summary> /// Write out in user friendly format information about the signing. /// </summary> /// <param name="issuedCertificate">The issued certificate.</param> /// <param name="goodSignature">If this is a good signature or not.</param> /// <param name="signedCms">The information about the signing.</param> private static void WriteSigningInformation(X509Certificate2 issuedCertificate, bool goodSignature, SignedCms signedCms) { InfoOutputHelper.WriteLine($"Signature made using certificate ID 0x{issuedCertificate.Thumbprint}"); foreach (var signerInfo in signedCms.SignerInfos) { foreach (var attributeObject in signerInfo.SignedAttributes) { if (attributeObject.Values[0] is Pkcs9SigningTime signingTime) { InfoOutputHelper.WriteLine($"Signature made at {signingTime.SigningTime.ToString("O", CultureInfo.InvariantCulture)}"); } } } InfoOutputHelper.WriteLine($"Signature issued by '{issuedCertificate.Issuer}'"); if (goodSignature) { InfoOutputHelper.WriteLine($"Good signature from '{issuedCertificate.Subject}'"); } else { InfoOutputHelper.WriteLine($"Bad signature from '{issuedCertificate.Subject}'"); } }
/// <summary> /// Performs a signing operation. /// </summary> /// <param name="certificate">The certificate to use for signing.</param> /// <param name="bytes">The bytes to sign.</param> /// <param name="timeStampAuthority">A optional RFC3161 timestamp authority to sign against.</param> /// <param name="isDetached">If we should be producing detached results.</param> /// <param name="useArmor">If we should encode in PEM format.</param> /// <param name="includeOption">The certificate include options, if we should just include end certificates, or intermediate/root certificates as well.</param> /// <returns>0 if the operation was successful, 1 otherwise.</returns> internal static async Task <int> PerformSign(X509Certificate2 certificate, byte[] bytes, Uri timeStampAuthority, bool isDetached, bool useArmor, X509IncludeOption includeOption) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate), Resources.InvalidCertificate); } if (!certificate.HasPrivateKey) { throw new ArgumentException($"The certificate {certificate.Thumbprint} has a invalid signing key.", nameof(certificate)); } if (bytes == null) { throw new ArgumentNullException(nameof(bytes), Resources.NothingToEncrypt); } // Git is looking for "\n[GNUPG:] SIG_CREATED ", meaning we need to print a // line before SIG_CREATED. BEGIN_SIGNING seems appropriate. GPG emits this, // though GPGSM does not. GpgOutputHelper.WriteLine(BeginSigning); var contentInfo = new ContentInfo(bytes); var cms = new SignedCms(contentInfo, isDetached); var signer = new CmsSigner(certificate) { IncludeOption = includeOption }; signer.SignedAttributes.Add(new Pkcs9SigningTime()); cms.ComputeSignature(signer, false); // If we are provided with a authority, add the timestamp certificate into our unsigned attributes. if (timeStampAuthority != null) { InfoOutputHelper.WriteLine("Stamping with RFC 3161 Time Stamp Authority: " + timeStampAuthority); await TimeStamper.GetAndSetRfc3161Timestamp(cms, timeStampAuthority).ConfigureAwait(false); } var encoding = cms.Encode(); // Write out the signature in GPG expected format. WriteGpgFormatSignature(certificate, isDetached); KeyOutputHelper.Write(encoding, useArmor); InfoOutputHelper.WriteLine("Finished signing"); GpgOutputHelper.Flush(); InfoOutputHelper.Flush(); return(0); }
private static async Task <int> OnExecuteAsync(Options options) { if (!options.ListKeys && !options.Sign && !options.VerifySignature) { throw new Exception(Resources.ValidCommandAction); } GpgOutputHelper.FileDescriptor = options.StatusFileDescriptor; try { int result = 1; if (options.ListKeys) { result = await ListKeysAction.Do().ConfigureAwait(false); } if (options.Sign) { result = await SignAction.Do(options.FileNames.FirstOrDefault(), options.LocalUser, options.GetTimestampAuthorityUri(), options.DetachedSign, options.Armor, options.IncludeOption).ConfigureAwait(false); } if (options.VerifySignature) { result = VerifyAction.Do(options.FileNames.ToArray()); } if (result == 1) { throw new Exception(Resources.ValidCommandAction); } return(result); } catch (SignClientException ex) { InfoOutputHelper.WriteLine(ex.ToString()); TelemetryHelper.Client?.TrackException(ex); } catch (Exception ex) { InfoOutputHelper.WriteLine(ex.ToString()); // Don't pass the exception in the generic case, due to it might contain personal information. TelemetryHelper.Client?.TrackTrace(ex.GetType().FullName, SeverityLevel.Critical); } return(1); }
private static async Task <int> OnExecuteAsync(Options options) { if (!options.ListKeys && !options.Sign && !options.VerifySignature) { throw new Exception(Resources.ValidCommandAction); } GpgOutputHelper.FileDescriptor = options.StatusFileDescriptor; try { int result = 1; if (options.ListKeys) { result = await ListKeysAction.Do().ConfigureAwait(false); } if (options.Sign) { result = await SignAction.Do(options.FileNames.FirstOrDefault(), options.LocalUser, options.GetTimestampAuthorityUri(), options.DetachedSign, options.Armor, options.IncludeOption).ConfigureAwait(false); } if (options.VerifySignature) { result = VerifyAction.Do(options.FileNames.ToArray()); } if (result == 1) { throw new Exception(Resources.ValidCommandAction); } return(result); } catch (SignClientException ex) { InfoOutputHelper.WriteLine(ex.ToString()); } catch (Exception ex) { InfoOutputHelper.WriteLine(ex.ToString()); } return(1); }