示例#1
0
        private static void WriteGpgFormatSignature(X509Certificate2 certificate, bool isDetached)
        {
            const int signatureCode = 0; // GPGSM uses 0 as well.
            var       signatureType = isDetached ? "D" : "S";

            var(algorithmCode, hashCode) = CertificateHelper.ToPgpPublicKeyAlgorithmCode(certificate);
            GpgOutputHelper.WriteLine($"{SignatureCreated} {signatureType} {algorithmCode} {hashCode} {signatureCode} {DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture)} {certificate.Thumbprint}");
        }
示例#2
0
        /// <summary>
        /// Write out the format in the GPG format.
        /// </summary>
        /// <param name="goodSignature">If this is a good signature or not.</param>
        /// <param name="certificates">The certificates to write.</param>
        private static void WriteGpgCertificateData(bool goodSignature, X509Certificate2Collection certificates)
        {
            var type = goodSignature ? GoodSignature : BadSignature;

            foreach (var certificate in certificates)
            {
                GpgOutputHelper.WriteLine($"{type} {certificate.Thumbprint} {certificate.Subject}");
            }
        }
示例#3
0
        /// <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);
        }
示例#4
0
        public static int Do(string[] fileNames)
        {
            GpgOutputHelper.WriteLine(NewSig);

            if (fileNames.Length < 2)
            {
                VerifyAttached(fileNames.FirstOrDefault());
            }
            else
            {
                VerifyDetached(fileNames);
            }

            return(0);
        }
示例#5
0
        /// <summary>
        /// Common code for both the attached/detached cases. It will verify that the signatures are valid for the data.
        /// </summary>
        /// <param name="signedCms">The signed CMS which we will validate.</param>
        /// <param name="body">The bytes we want to validate against.</param>
        /// <param name="verifySignatureOnly">If we should verify the signature only. Useful for testing only.</param>
        internal static void VerifySignedData(SignedCms signedCms, byte[] body, bool verifySignatureOnly = false)
        {
            try
            {
                signedCms.Decode(body);

                signedCms.CheckSignature(verifySignatureOnly);

                if (signedCms.SignerInfos.Count == 0)
                {
                    throw new SignClientException(Resources.InvalidSigningInfo);
                }

                var issuedCertificate = signedCms.SignerInfos[0].Certificate;

                foreach (var signedInfo in signedCms.SignerInfos)
                {
                    if (TimeStamper.CheckRFC3161Timestamp(signedInfo, issuedCertificate.NotBefore, issuedCertificate.NotAfter) == false)
                    {
                        throw new SignClientException(Resources.InvalidTimestamp);
                    }
                }

                WriteGpgCertificateData(true, signedCms.Certificates);
                WriteSigningInformation(issuedCertificate, true, signedCms);

                GpgOutputHelper.WriteLine($"{FullyTrusted} 0 shell"); // This indicates we fully trust using the x509 model.
            }
            catch (Exception)
            {
                if (signedCms.Certificates.Count == 0)
                {
                    GpgOutputHelper.WriteLine(ErrorSignature);
                }
                else
                {
                    var issuedCertificate = signedCms.SignerInfos[0].Certificate;
                    WriteGpgCertificateData(false, signedCms.Certificates);
                    WriteSigningInformation(issuedCertificate, false, signedCms);
                }

                throw;
            }
        }