/// <summary> /// Get timestamps from the signer info /// </summary> /// <param name="signer"></param> /// <returns></returns> private static IReadOnlyList <Timestamp> GetTimestamps(SignerInfo signer, string signatureFriendlyName) { var unsignedAttributes = signer.UnsignedAttributes; var timestampList = new List <Timestamp>(); foreach (var attribute in unsignedAttributes) { if (string.Equals(attribute.Oid.Value, Oids.SignatureTimeStampTokenAttribute, StringComparison.Ordinal)) { var timestampCms = new SignedCms(); timestampCms.Decode(attribute.Values[0].RawData); using (var certificates = SignatureUtility.GetTimestampCertificates( timestampCms, SigningSpecifications.V1, signatureFriendlyName)) { if (certificates == null || certificates.Count == 0) { throw new SignatureException(NuGetLogCode.NU3029, Strings.InvalidTimestampSignature); } } timestampList.Add(new Timestamp(timestampCms)); } } return(timestampList); }
private PackageVerificationResult VerifySignatureAndCountersignature( PrimarySignature signature, SignedPackageVerifierSettings settings) { var issues = new List <SignatureLog>(); var certificateExtraStore = signature.SignedCms.Certificates; var primarySignatureHasCountersignature = SignatureUtility.HasRepositoryCountersignature(signature); var status = SignatureVerificationStatus.Illegal; // Only accept untrusted root if the signature has a countersignature that we can validate against var verifySettings = new SignatureVerifySettings( treatIssuesAsErrors: !settings.AllowIllegal, allowUntrustedRoot: primarySignatureHasCountersignature, allowUnknownRevocation: settings.AllowUnknownRevocation, logOnSignatureExpired: !primarySignatureHasCountersignature); var primarySummary = VerifyValidityAndTrust(signature, settings, verifySettings, certificateExtraStore, issues); if (primarySummary != null) { status = primarySummary.Status; if (primarySignatureHasCountersignature) { if (settings.AlwaysVerifyCountersignature || ShouldFallbackToRepositoryCountersignature(primarySummary)) { var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(signature); verifySettings = new SignatureVerifySettings( treatIssuesAsErrors: !settings.AllowIllegal, allowUntrustedRoot: false, allowUnknownRevocation: settings.AllowUnknownRevocation, logOnSignatureExpired: true); var counterSummary = VerifyValidityAndTrust(countersignature, settings, verifySettings, certificateExtraStore, issues); status = counterSummary.Status; if (!Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, counterSummary.Timestamp)) { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3011, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureNotTimeValid, signature.FriendlyName))); status = SignatureVerificationStatus.Illegal; } } else if (primarySummary.Flags.HasFlag(SignatureVerificationStatusFlags.CertificateExpired)) { // We are not adding this log if the primary signature has a countersignature to check the expiration against the countersignature's timestamp. // If the countersignature shouldn't be check and the primary signature was expired, add this log. issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3011, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureNotTimeValid, signature.FriendlyName))); } } } return(new SignedPackageVerificationResult(status, signature, issues)); }
private static void VerifySigningCertificate( SignedCms signedCms, SignerInfo signerInfo, SigningSpecifications signingSpecifications) { var certificates = SignatureUtility.GetPrimarySignatureCertificates( signedCms, signerInfo, signingSpecifications); if (certificates == null || certificates.Count == 0) { ThrowForInvalidPrimarySignature(); } }
private static void VerifySigningCertificate( SignedCms signedCms, SignerInfo signerInfo, SigningSpecifications signingSpecifications) { using (var certificates = SignatureUtility.GetCertificateChain( signedCms, signerInfo, signingSpecifications, Strings.PrimarySignatureFriendlyName)) { if (certificates == null || certificates.Count == 0) { ThrowForInvalidPrimarySignature(); } } }
private PackageVerificationResult Verify( PrimarySignature signature, SignedPackageVerifierSettings settings) { var certificateExtraStore = signature.SignedCms.Certificates; var repositoryCountersignatureExists = SignatureUtility.HasRepositoryCountersignature(signature); var isRepositoryCountersignatureVerificationRequested = settings.VerificationTarget.HasFlag(VerificationTarget.Repository) && settings.SignaturePlacement.HasFlag(SignaturePlacement.Countersignature); var allowDeferralToRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists; var status = SignatureVerificationStatus.Unknown; var issues = Enumerable.Empty <SignatureLog>(); var isUntrustedRootAllowed = IsUntrustedRootAllowed(signature); var verifySettings = new SignatureVerifySettings( allowIllegal: settings.AllowIllegal, allowUntrusted: settings.AllowUntrusted || isUntrustedRootAllowed, allowUnknownRevocation: settings.AllowUnknownRevocation, reportUnknownRevocation: settings.ReportUnknownRevocation, reportUntrustedRoot: !isUntrustedRootAllowed, revocationMode: settings.RevocationMode); SignatureVerificationSummary primarySummary = null; if (settings.SignaturePlacement.HasFlag(SignaturePlacement.PrimarySignature) && VerificationUtility.IsVerificationTarget(signature.Type, settings.VerificationTarget)) { primarySummary = VerifyValidityAndTrust(signature, settings, verifySettings, certificateExtraStore); issues = issues.Concat(primarySummary.Issues); status = primarySummary.Status; } Debug.Assert(isRepositoryCountersignatureVerificationRequested != (settings.RepositoryCountersignatureVerificationBehavior == SignatureVerificationBehavior.Never)); bool shouldVerifyRepositoryCountersignature; switch (settings.RepositoryCountersignatureVerificationBehavior) { case SignatureVerificationBehavior.IfExists: shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists; break; case SignatureVerificationBehavior.IfExistsAndIsNecessary: // The repository countersignature should be evaluated if settings allow it, if a repository countersignature exists // and if either settings only allow a repository countersignature to be evaluated or the primary signature has some // validation/trust issues that may benefit from a repository countersignature fallback. shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists && (primarySummary == null || (primarySummary != null && (HasUntrustedRoot(primarySummary) || IsSignatureExpired(primarySummary)))); break; case SignatureVerificationBehavior.Always: shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested; break; case SignatureVerificationBehavior.Never: shouldVerifyRepositoryCountersignature = false; break; default: throw new NotImplementedException(); } if (shouldVerifyRepositoryCountersignature) { var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(signature); if (countersignature == null) { if (settings.RepositoryCountersignatureVerificationBehavior == SignatureVerificationBehavior.Always) { issues = issues.Concat(new[] { SignatureLog.Error(NuGetLogCode.NU3038, Strings.NoRepositoryCountersignature) }); status = SignatureVerificationStatus.Disallowed; } } else { isUntrustedRootAllowed = IsUntrustedRootAllowed(countersignature); verifySettings = new SignatureVerifySettings( allowIllegal: settings.AllowIllegal, allowUntrusted: settings.AllowUntrusted || isUntrustedRootAllowed, allowUnknownRevocation: settings.AllowUnknownRevocation, reportUnknownRevocation: settings.ReportUnknownRevocation, reportUntrustedRoot: !isUntrustedRootAllowed, revocationMode: settings.RevocationMode); var countersignatureSummary = VerifyValidityAndTrust(countersignature, settings, verifySettings, certificateExtraStore); if (primarySummary == null) { status = countersignatureSummary.Status; } else { if (countersignatureSummary.Status == SignatureVerificationStatus.Valid) { if (IsSignatureExpired(primarySummary) && HasUntrustedRoot(primarySummary)) { // Exclude the issue of the primary signature being untrusted since the repository countersignature fulfills the role of a trust anchor. issues = issues.Where(log => log.Code != NuGetLogCode.NU3018); if (countersignatureSummary.Timestamp != null && Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, countersignatureSummary.Timestamp)) { // Exclude the issue of the primary signature being expired since the repository countersignature fulfills the role of a trusted timestamp. issues = issues.Where(log => log.Code != NuGetLogCode.NU3037); status = SignatureVerificationStatus.Valid; } } else if (IsSignatureExpired(primarySummary) && countersignatureSummary.Timestamp != null && Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, countersignatureSummary.Timestamp)) { // Exclude the issue of the primary signature being expired since the repository countersignature fulfills the role of a trusted timestamp. issues = issues.Where(log => log.Code != NuGetLogCode.NU3037); status = SignatureVerificationStatus.Valid; } else if (HasUntrustedRoot(primarySummary)) { // Exclude the issue of the primary signature being untrusted since the repository countersignature fulfills the role of a trust anchor. issues = issues.Where(log => log.Code != NuGetLogCode.NU3018); status = SignatureVerificationStatus.Valid; } } // Both the primary signature and the repository countersignature were evaluated. // The overall status should be the more severe status of the two. status = (SignatureVerificationStatus)Math.Min((int)status, (int)countersignatureSummary.Status); } issues = issues.Concat(countersignatureSummary.Issues); } } return(new SignedPackageVerificationResult(status, signature, issues)); }
/// <summary> /// Add a signature to a package. /// </summary> public static async Task SignAsync(SigningOptions options, SignPackageRequest signRequest, CancellationToken token) { token.ThrowIfCancellationRequested(); Verify(signRequest, options.Logger); var tempPackageFile = new FileInfo(Path.GetTempFileName()); Stream unsignedPackageStream = null; var signaturePlacement = SignaturePlacement.PrimarySignature; try { PrimarySignature primarySignature; var isSigned = false; using (var package = new SignedPackageArchive(options.InputPackageStream, Stream.Null)) { if (await package.IsZip64Async(token)) { throw new SignatureException(NuGetLogCode.NU3006, Strings.ErrorZip64NotSupported); } primarySignature = await package.GetPrimarySignatureAsync(token); isSigned = primarySignature != null; if (signRequest.SignatureType == SignatureType.Repository && primarySignature != null) { if (primarySignature.Type == SignatureType.Repository) { throw new SignatureException(NuGetLogCode.NU3033, Strings.Error_RepositorySignatureMustNotHaveARepositoryCountersignature); } if (SignatureUtility.HasRepositoryCountersignature(primarySignature)) { throw new SignatureException(NuGetLogCode.NU3032, Strings.SignedPackagePackageAlreadyCountersigned); } signaturePlacement = SignaturePlacement.Countersignature; } if (isSigned && !options.Overwrite && signaturePlacement != SignaturePlacement.Countersignature) { throw new SignatureException(NuGetLogCode.NU3001, Strings.SignedPackageAlreadySigned); } } var inputPackageStream = options.InputPackageStream; if (isSigned) { unsignedPackageStream = tempPackageFile.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); using (var package = new SignedPackageArchive(options.InputPackageStream, unsignedPackageStream)) { await package.RemoveSignatureAsync(token); } inputPackageStream = unsignedPackageStream; } using (var package = new SignedPackageArchive(inputPackageStream, options.OutputPackageStream)) { PrimarySignature signature; if (signaturePlacement == SignaturePlacement.Countersignature) { signature = await options.SignatureProvider.CreateRepositoryCountersignatureAsync( signRequest as RepositorySignPackageRequest, primarySignature, options.Logger, token); } else { var hashAlgorithm = signRequest.SignatureHashAlgorithm; var zipArchiveHash = await package.GetArchiveHashAsync(hashAlgorithm, token); var signatureContent = GenerateSignatureContent(hashAlgorithm, zipArchiveHash); signature = await options.SignatureProvider.CreatePrimarySignatureAsync(signRequest, signatureContent, options.Logger, token); } using (var stream = new MemoryStream(signature.GetBytes())) { await package.AddSignatureAsync(stream, token); } } } finally { if (unsignedPackageStream != null && !ReferenceEquals(unsignedPackageStream, options.InputPackageStream)) { unsignedPackageStream.Dispose(); } FileUtility.Delete(tempPackageFile.FullName); } }