Excel displays "Valid partial signature" when using C# to sign Excel 2016 xlsx doc

Brian Tabone 46 Reputation points
2021-02-04T23:31:40.803+00:00

I am using .net 5 to digitally sign Excel documents with my digital signature certificate. I followed the example from

https://learn.microsoft.com/en-us/dotnet/api/system.io.packaging.packagedigitalsignaturemanager.sign?view=net-5.0#System_IO_Packaging_PackageDigitalSignatureManager_Sign_System_Collections_Generic_IEnumerable_System_Uri__System_Security_Cryptography_X509Certificates_X509Certificate_

and all seems to work without issue except that Excel shows that the while the signature is valid, it is only partial. The verbiage is

"Valid partial signature - This signature only signs a portion of the content"

When I extract the signature xml, it appears to sign all parts of the package but does not contain an idOfficeObject nor an idSignedProperties section, just the idPackageSignature . When I sign with Excel I get the idOfficeObject and idSignedProperties section.

Is there a way to sign an Excel document from C# without it showing the valid partial signature notification?

Developer technologies | C#
0 comments No comments
{count} votes

Accepted answer
  1. Timon Yang-MSFT 9,606 Reputation points
    2021-02-05T09:32:00.527+00:00

    Try this code if it works for you:

                string certFileName = "AsposeDemo.pfx";  
                string password = "aspose";  
      
                Aspose.Cells.Workbook workbook = new Aspose.Cells.Workbook("sampleDigitallySignedByCells.xlsx");  
      
                Aspose.Cells.DigitalSignatures.DigitalSignatureCollection dsCollection = new Aspose.Cells.DigitalSignatures.DigitalSignatureCollection();  
      
                System.Security.Cryptography.X509Certificates.X509Certificate2 certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(certFileName, password);  
      
                Aspose.Cells.DigitalSignatures.DigitalSignature signature = new Aspose.Cells.DigitalSignatures.DigitalSignature(certificate, "Aspose.Cells added new digital signature in existing digitally signed workbook.", DateTime.Now);  
                dsCollection.Add(signature);  
      
                workbook.AddDigitalSignature(dsCollection);  
      
                workbook.Save("outputDigitallySignedByCells.xlsx");  
                workbook.Dispose();  
    

    I used this nuget package.


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


1 additional answer

Sort by: Most helpful
  1. Brian Tabone 46 Reputation points
    2021-02-18T23:45:03.937+00:00

    I found how to fix the issue directly using the PackageDigitalSignatureManager

    The example code I used is from:

    https://learn.microsoft.com/en-us/previous-versions/dotnet/articles/aa905326(v=msdn.10)?redirectedfrom=MSDN

    And I added

    // Package part relationships must also be added otherwise you get only a partial signature  
    foreach (PackageRelationship relationship in packagePart.GetRelationships())  
    {  
        relationshipSelectors.Add(new  
        PackageRelationshipSelector(relationship.SourceUri,  
        PackageRelationshipSelectorType.Id, relationship.Id));  
    }  
      
    

    Here's the digital signature method in its entirety:

            private static bool SignOfficeDoc(string officeDocPackagePath, X509Certificate2 certificate)  
            {  
                using (var package = Package.Open(officeDocPackagePath))  
                {  
                    var signatureManager = new PackageDigitalSignatureManager(package);  
                    signatureManager.CertificateOption = CertificateEmbeddingOption.InSignaturePart;  
                    //Initialize a list to hold the part URIs to sign.  
      
                    List<Uri> partsToSign = new List<Uri>();  
      
                    //Create list of selectors for the list of relationships  
      
                    List<PackageRelationshipSelector> relationshipSelectors =  
                         new List<PackageRelationshipSelector>();  
      
                    //Add each part to the list, except relationships parts.  
                    foreach (PackagePart packagePart in package.GetParts())  
                    {  
                        if (!PackUriHelper.IsRelationshipPartUri(packagePart.Uri))  
                        {  
                            partsToSign.Add(packagePart.Uri);  
      
                            // Package part relationships must also be added otherwise you get only a partial signature  
                            foreach (PackageRelationship relationship in packagePart.GetRelationships())  
                            {  
                                relationshipSelectors.Add(new  
                                    PackageRelationshipSelector(relationship.SourceUri,  
                                    PackageRelationshipSelectorType.Id, relationship.Id));  
                            }  
                        }  
                    }  
      
                    //Create one selector for each package-level relationship, based on id  
                    foreach (PackageRelationship relationship in package.GetRelationships())  
                    {  
                        relationshipSelectors.Add(new  
                            PackageRelationshipSelector(relationship.SourceUri,  
                            PackageRelationshipSelectorType.Id, relationship.Id));  
                    }  
      
                    PackageDigitalSignature signature = signatureManager.Sign(partsToSign, certificate, relationshipSelectors);  
      
                    //After signing, close the package.  
                    //The signature will be persisted in the package.  
                    package.Close();  
                }  
      
                return true;  
            }  
             
    
    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.