1. GroupDocs Documentation
  2. /
  3. GroupDocs.Comparison Product Family
  4. /
  5. GroupDocs.Comparison for .NET
  6. /
  7. Use Cases
  8. /
  9. Comparing Password-Protected Documents in .NET - Five Approaches Compared

Comparing Password-Protected Documents in .NET - Five Approaches Compared

Introduction

A password on a document changes three things about comparing it, and none of them are obvious from the plaintext examples. Each document carries its own protection, so a single password field cannot describe two encrypted files. The result document has its own protection state, independent of the inputs, and the default leaves it unprotected. And the failure for a missing password does not arrive where most developers place their try block.

This guide compares five approaches to comparing password-protected documents with GroupDocs.Comparison for .NET. Each is evaluated on:

  • Implementation complexity
  • Use case suitability
  • What protects the result
  • Format coverage

Prerequisites:

  • .NET 8.0 SDK or later, with GroupDocs.Comparison 26.9.0 from NuGet
  • Two encrypted documents of the same format and their passwords
Note
Complete Source Code: All examples are available in our GitHub repository. Clone, run, and customize for your needs.

Quick Decision Matrix

ScenarioRecommended MethodWhy
One marked-up file, protection preservedInline with PasswordSaveOption.SourceResult reuses the source password automatically
Parallel reading of original and revisionSide-by-side PDF modeTwo columns survive printing and page-by-page sign-off
Reviewer accepts or rejects each editWord revisions modeChanges become native Word revisions
Diff goes to people without either passwordPasswordSaveOption.UserIssues a new password for the result only
Passwords come from user inputGuard the Compare callThat is the only place a bad password throws

Detailed Method Analysis

Method 1: Inline PDF comparison

Overview: Opens two encrypted PDFs, each with its own password, and writes one result file with insertions and deletions marked in place. This is the baseline that the other approaches modify.

How It Works

The source password goes into a LoadOptions passed to the Comparer constructor. The target password goes into a second LoadOptions passed to Add. PdfCompareOptions.DisplayMode set to Inline merges the changes into the text, and PasswordSaveOption.Source reuses the source document’s password on the output rather than leaving it open.

When to Use

  • ✅ One deliverable that a reviewer reads top to bottom
  • ✅ The result must stay at least as protected as the inputs
  • ✅ Both documents are PDFs
  • ❌ Not recommended for: reviewers who need to accept or reject edits individually

Implementation

var options = new PdfCompareOptions
{
    DisplayMode = PdfCompareOptions.ComparisonDisplayMode.Inline,
    PasswordSaveOption = PasswordSaveOption.Source
};

using var comparer = new Comparer(sourcePath,
    new LoadOptions { Password = SourcePassword });
comparer.Add(targetPath, new LoadOptions { Password = TargetPassword });
comparer.Compare(outputPath, options);

Method 2: Side-by-side PDF comparison

Overview: The same two encrypted PDFs rendered as parallel columns instead of merged markup. The loading code does not change at all.

How It Works

Only DisplayMode differs from Method 1. That is the substantive point: protection lives entirely in LoadOptions, so the full set of comparison options stays available on encrypted input. PdfCompareOptions also offers Interleaved alongside Inline and SideBySide.

When to Use

  • ✅ Reviewers compare versions visually, page by page
  • ✅ The output will be printed or signed off in sections
  • ✅ Changes are dense enough that inline markup obscures the text
  • ❌ Not recommended for: narrow display surfaces where two columns do not fit

Implementation

var options = new PdfCompareOptions
{
    DisplayMode = PdfCompareOptions.ComparisonDisplayMode.SideBySide,
    PasswordSaveOption = PasswordSaveOption.Source
};

using var comparer = new Comparer(sourcePath,
    new LoadOptions { Password = SourcePassword });
comparer.Add(targetPath, new LoadOptions { Password = TargetPassword });
comparer.Compare(outputPath, options);

Method 3: Word revisions comparison

Overview: Compares two encrypted DOCX files and records every difference as a native Word revision, so the reviewer can accept or reject each one in Word.

How It Works

The loading code is identical to the PDF methods, because LoadOptions.Password is format-agnostic — the same property unlocks PDF, DOCX, XLSX and PPTX. What changes is the options class. WordCompareOptions exposes ComparisonDisplayMode.Revisions, which writes tracked changes rather than baking markup into the text. Note that this enum is distinct from the identically named one on PdfCompareOptions and carries different values.

When to Use

  • ✅ The reviewer works in Word and wants per-change control
  • ✅ The document continues through an editorial workflow after comparison
  • ✅ Encrypted DOCX support is being added to code that already handles PDFs
  • ❌ Not recommended for: read-only distribution, where revisions can be toggled off

Implementation

var options = new WordCompareOptions
{
    DisplayMode = WordCompareOptions.ComparisonDisplayMode.Revisions,
    PasswordSaveOption = PasswordSaveOption.Source
};

using var comparer = new Comparer(sourcePath,
    new LoadOptions { Password = SourcePassword });
comparer.Add(targetPath, new LoadOptions { Password = TargetPassword });
comparer.Compare(outputPath, options);

Method 4: Protecting the result with a new password

Overview: Compares two encrypted PDFs and protects the output with a third password belonging to neither input, so the diff can circulate without exposing either original.

How It Works

PasswordSaveOption.User tells GroupDocs.Comparison to ignore both input passwords and take the one from SaveOptions.Password. Both option objects are passed to the three-argument Compare overload. Setting SaveOptions.Password on its own has no effect: the enum value is what activates the save-side password.

When to Use

  • ✅ The comparison goes to a wider audience than the source documents
  • ✅ Audit or compliance rules require the diff to be encrypted at rest
  • ✅ Input passwords must not be shared onward
  • ❌ Not recommended for: internal runs where recipients already hold both passwords

Implementation

var compareOptions = new PdfCompareOptions
{
    DisplayMode = PdfCompareOptions.ComparisonDisplayMode.Inline,
    PasswordSaveOption = PasswordSaveOption.User
};
var saveOptions = new SaveOptions { Password = "5678" };

using var comparer = new Comparer(sourcePath,
    new LoadOptions { Password = SourcePassword });
comparer.Add(targetPath, new LoadOptions { Password = TargetPassword });
comparer.Compare(outputPath, saveOptions, compareOptions);

Method 5: Handling the deferred failure

Overview: Shows when a missing or wrong password actually throws.

How It Works

Constructing a Comparer over an encrypted file with no LoadOptions succeeds. So does Add. Both only record paths. The documents are opened when Compare runs, and that is where PasswordProtectedFileException with the message Password is missing is thrown. A wrong password behaves the same way: the constructor accepts it without complaint and the failure surfaces at Compare.

When to Use

  • ✅ Passwords come from user input or a credential store and may be wrong
  • ✅ A batch pipeline needs to report which documents failed and why
  • ✅ Existing error handling wraps construction and never fires
  • ❌ Not recommended for: skipping validation entirely on trusted internal input

Implementation

try
{
    using var comparer = new Comparer(sourcePath);
    comparer.Add(targetPath);
    comparer.Compare(outputPath);
}
catch (PasswordProtectedFileException ex)
{
    Console.WriteLine($"Password rejected at Compare: {ex.Message}");
}

Side-by-Side Feature Comparison

FeatureInline PDFSide-by-side PDFWord revisionsNew password
FormatsPDFPDFDOCX, PPTX, ODPAny supported
Result protectionSource passwordSource passwordSource passwordNew password
Options classPdfCompareOptionsPdfCompareOptionsWordCompareOptionsEither
Per-change actionsNoNoYes, in WordNo
Extra settingsNoneNoneNoneSaveOptions

Best Practices and Recommendations

For user-supplied passwords

Wrap the Compare call, not the constructor. Catch PasswordProtectedFileException and report which document path failed, because a multi-target comparison gives no other indication of which password was wrong.

For compliance-sensitive output

Set PasswordSaveOption explicitly on every comparison, even when the intended value is the default. The default is None, and a comparison of two encrypted documents that writes an unprotected result is easy to miss in review.

Common Pitfalls and How to Avoid Them

  1. One LoadOptions for every document

    • Problem: Options passed to the constructor apply to the source only; the target has no password and the comparison fails at Compare.
    • Solution: Build a separate LoadOptions for each Add call.
  2. An unprotected result from protected inputs

    • Problem: PasswordSaveOption defaults to None, so the output of two encrypted documents is written with no password at all.
    • Solution: Set Source, Target or User explicitly.
  3. Unqualified ComparisonDisplayMode

    • Problem: Both PdfCompareOptions and WordCompareOptions declare a nested enum of that name with different values, so the bare name does not compile.
    • Solution: Write PdfCompareOptions.ComparisonDisplayMode.Inline or WordCompareOptions.ComparisonDisplayMode.Revisions.

Do the source and target need the same password?

No. Each document is unlocked by its own LoadOptions instance, so the two passwords are entirely independent. The examples above use different passwords for the source and the target on purpose, because a single shared password hides the fact that the constructor’s options never reach the targets. Pass one LoadOptions per document and mixed passwords stop being a special case.

FAQ

Q: What protects the comparison result? A: Whatever PasswordSaveOption names. None leaves it unprotected, Source and Target reuse an input password, and User takes the value from SaveOptions.Password. The default is None, so protected inputs do not imply a protected result.

Q: Can I combine these approaches? A: Yes. Display mode and result protection are independent settings, so a side-by-side comparison can carry a new user password. The only pairing requirement is PasswordSaveOption.User together with SaveOptions.Password.

Q: Why doesn’t my try/catch around the constructor fire? A: Because the constructor does not open the document. It records the path, as does Add. Both documents are read when Compare executes, so that is where PasswordProtectedFileException is raised for a missing or wrong password.

Q: Are there licensing considerations? A: Unlicensed runs work but watermark the output. A free temporary licence removes evaluation limits for testing.

Conclusion

Password handling in GroupDocs.Comparison reduces to three decisions. Give every document its own LoadOptions.Password. Choose the result’s protection with PasswordSaveOption rather than accepting the None default. And guard Compare, because that is where a bad password is detected. Once those are in place, encrypted documents behave like any other input and the full comparison feature set applies.

Next Steps:

See Also

Close
Loading

Analyzing your prompt, please hold on...

An error occurred while retrieving the results. Please refresh the page and try again.