GroupDocs.Signature for Java 26.10 Release Notes

Full list of changes in this release

IDSummaryCategory
SIGNATURENET-5950, SIGNATURENET-6000, SIGNATURENET-6001External resources referenced by a document are no longer loaded by default; new LoadOptions settings control itFeature
SIGNATURENET-5995Signing with an expired or not yet valid certificate is rejected unless DigitalSignOptions allows itFeature
SIGNATURENET-5634Word documents keep their OOXML compliance when saved; WordProcessingSaveOptions can set itFeature
SIGNATURENET-5976PDF digital signatures use SHA-256 by default and honour HashAlgorithmFeature
SIGNATURENET-5978Verify checks PDF digital signatures cryptographically; a document changed after signing is not validFeature
SIGNATURENET-5997PDF verification honours SubjectName, IssuerName and the signing time windowFeature
SIGNATURENET-6003Certificate verification checks Expired, issuer, subject, serial number, thumbprint and the chainFeature
SIGNATUREJAVALoadOptions.setFileType, Signature.search(Predicate) and VerificationResult.getFailed(), as in .NETFeature
SIGNATURENET-6004SignatureSettings.setLogLevel takes effect; with the default level the logger now receives messagesFix
SIGNATUREJAVA-2903Barcode and QR-code signing no longer fails with The image size can not be 0! on Java 11 and laterFix
SIGNATURENET-5208A custom PDF signer (ICustomSignHash) is called, and the signature it produces verifiesFix
SIGNATURENET-5998The time-stamp server receives credentials when only the user name or only the password is setFix
SIGNATURENET-6005A VerifyOptions object used for several documents reports only the current documentFix
SIGNATURENET-6006A DigitalSignOptions object used for several presentations signs each one with its own settingsFix
SIGNATURENET-6002Spreadsheets with a linked picture that has no image data no longer fail search and verificationFix
SIGNATUREJAVASearch and verification of archives workFix
SIGNATUREJAVACertificates whose key entry has a name are accepted for presentations, spreadsheets and VBA projectsFix
SIGNATUREJAVASaving a signed document as images no longer produces empty pagesFix
SIGNATUREJAVAImage save options (JPEG quality, PNG, GIF and TIFF settings) are appliedFix
SIGNATUREJAVAReturnContentType is honoured; FileType.equals compares the typesFix
SIGNATUREJAVAQR-code search in multi-layer images with ReturnContent returns the codes foundFix
SIGNATUREJAVABarcodeTypes.GS1CompositeBar has a default text that Aspose.BarCode acceptsFix
SIGNATUREJAVAPassing options of the wrong type reports the validation error instead of a FormatExceptionFix
SIGNATUREJAVAArchives are checked for excessive size and compression while they are expandedUpdate
SIGNATURENET-5825Trial limits: signing an archive is no longer limited by the number of documents in itUpdate
SIGNATUREJAVA-2908Aspose libraries updated; BarcodeTypes.Code39, Code39FullASCII and Code93 replace the Standard/Extended typesUpdate
SIGNATUREJAVA-2905The jar declares Automatic-Module-Name, ships its third-party licences and is signed with detached PGP signaturesUpdate
SIGNATUREJAVA-2906Published POM: product name and description, licence, developers, organisation and scmUpdate
SIGNATUREJAVA-2925The license agreement and links in the distribution package point at addresses that existUpdate

Behaviour changes to check before upgrading

Several changes alter what existing code observes. Each is described in its own section below.

  • External resources are not loaded unless LoadOptions.setSkipExternalResources(false) is set.
  • Signing with an expired or not yet valid certificate throws GroupDocsSignatureException. Set DigitalSignOptions.setAllowExpired(true) or setAllowNotYetValid(true) to sign anyway.
  • PDF digital signatures are created with SHA-256 (adbe.pkcs7.detached) instead of SHA-1.
  • Verifying a PDF with DigitalVerifyOptions reports a signature as valid only if it verifies cryptographically, and applies SubjectName, IssuerName, SignDateTimeFrom and SignDateTimeTo.
  • With the default LogLevel.All, a logger passed in SignatureSettings now receives errors, warnings and trace messages. Before, nothing was logged.
  • An archive with more than 10,000 entries, more than 1 GB of content or an entry compressed more than 100 times is rejected.
  • The jar is no longer signed with jarsigner; detached .asc PGP signatures are published next to it.

Feature — control over loading external resources

A document can reference resources outside itself — for example an image given by a remote URL, a picture linked to a file, or a style sheet referenced from an SVG. Opening it used to make the library fetch that address. External resources are now skipped by default, and two LoadOptions settings control the behaviour:

  • setSkipExternalResources(boolean) — true by default; set false to load external resources.
  • setWhitelistedResources(List<String>) — address fragments that are still loaded while resources are skipped. A fragment matches when the address contains it, ignoring case.
LoadOptions loadOptions = new LoadOptions();
loadOptions.setSkipExternalResources(true);
loadOptions.setWhitelistedResources(Arrays.asList("cdn.example.com/logo.png"));

Signature signature = new Signature("contract.docx", loadOptions);
try {
    signature.sign("contract_signed.docx", new TextSignOptions("John Smith"));
} finally {
    signature.dispose();
}

Scope.

  • Applies to Word, presentation, spreadsheet and SVG documents. Spreadsheets previously ignored the setting.
  • For SVG images, external href references, CSS @import and url() references, external style sheet instructions and the DOCTYPE are removed before the image is read, and external entities are never read. A malformed SVG is rejected while resources are skipped. (SIGNATURENET-6001)
  • Documents inside an archive get the archive’s settings. (SIGNATURENET-6000)
  • LoadOptions.setLoadExternalResources is deprecated and is now the inverse of setSkipExternalResources, so its default changes from true to false. (SIGNATURENET-5950)

Feature — expired and not yet valid signing certificates

Signing used to accept any certificate. A digital signature made with a certificate whose validity period has ended, or has not started, is now rejected before the document is loaded. The message names the certificate by subject and thumbprint, gives the date in UTC and the property that allows it.

DigitalSignOptions options = new DigitalSignOptions("certificate.pfx");
options.setPassword("1234567890");
options.setAllowExpired(true);       // sign anyway; a warning is logged
options.setAllowNotYetValid(false);  // the default

Signature signature = new Signature("contract.pdf");
try {
    signature.sign("contract_signed.pdf", options);
} finally {
    signature.dispose();
}

Scope.

  • Behaviour change: both settings are false by default.
  • Applies to digital signatures of every document type, and to the certificate of a VBA project in a spreadsheet. Images, certificate files and archives themselves are not checked; documents inside an archive are. (SIGNATURENET-5995)

Feature — OOXML compliance of Word documents

A Word document saved after signing now keeps the OOXML compliance it was loaded with (ECMA-376, Transitional or Strict). WordProcessingSaveOptions.setOoxmlCompliance sets another one:

WordProcessingSaveOptions saveOptions = new WordProcessingSaveOptions();
saveOptions.setOoxmlCompliance(OoxmlCompliance.Strict);

Signature signature = new Signature("contract.docx");
try {
    signature.sign("contract_signed.docx", new TextSignOptions("John Smith"), saveOptions);
} finally {
    signature.dispose();
}

The setting applies to OOXML output formats only and can be combined with a password. (SIGNATURENET-5634)

Feature — SHA-256 PDF digital signatures and HashAlgorithm

PDF digital signatures were created as adbe.pkcs7.sha1, whose digest is fixed at SHA-1, and SignOptions.setHashAlgorithm was ignored. They are now created as adbe.pkcs7.detached with SHA-256, and HashAlgorithm selects another digest. The time stamp, when one is requested, uses the same digest.

DigitalSignOptions options = new DigitalSignOptions("certificate.pfx");
options.setPassword("1234567890");
options.setHashAlgorithm(HashAlgorithm.Sha512);  // HashAlgorithm.Auto gives SHA-256

Scope.

  • Behaviour change: new PDF signatures use SHA-256 unless another algorithm is set.
  • Applies to certificates given as a file, a stream or a DigitalSignature.
  • Setting HashAlgorithm on a PDF signature that is not digital has no effect, and a warning is logged. (SIGNATURENET-5976)

Feature — cryptographic verification of PDF digital signatures

Verifying a PDF with DigitalVerifyOptions compared only the criteria that were set. With no criteria, any PDF containing a signature field was reported as valid, even after the document was changed. Each signature is now verified first, and is valid only if that check passes. A signature that cannot be verified — for example a malformed one — counts as not valid instead of stopping the verification of the whole document.

The criteria that were accepted and ignored for PDF are now applied, as they already were for Word documents:

  • setSubjectName and setIssuerName — the subject or issuer of the signing certificate must contain the value (case-sensitive);
  • setSignDateTimeFrom and setSignDateTimeTo — the signing time must lie in the window, compared in whole seconds.
DigitalVerifyOptions options = new DigitalVerifyOptions();
options.setSubjectName("John Smith");

Signature signature = new Signature("contract_signed.pdf");
try {
    VerificationResult result = signature.verify(options);
    System.out.println(result.isValid());  // false if the document was changed after signing
} finally {
    signature.dispose();
}

Scope.

  • Behaviour change: documents that used to verify may now report not valid, when they were changed after signing or do not match these criteria. (SIGNATURENET-5978, SIGNATURENET-5997)

Feature — certificate verification

Verifying a certificate file with CertificateVerifyOptions computed nothing — every check was missing. It now applies:

  • setExpired(boolean) — whether the certificate’s validity period has ended, compared in UTC;
  • setIssuer, setSubject, setSerialNumber and setThumbprint, with the option’s MatchType. Serial number and thumbprint use the upper-case hexadecimal form of .NET;
  • setPerformChainValidation(true) — builds a certificate path to the Java trust store. Unlike .NET, revocation is not checked.

(SIGNATURENET-6003)

Feature — public API from .NET

  • LoadOptions.setFileType(FileType) and the LoadOptions(FileType) constructor give the document type instead of detecting it from the content.
  • Signature.search(Predicate<BaseSignature>) searches text, image, digital, barcode, QR-code and metadata signatures and returns those that match the predicate.
  • VerificationResult.getFailed() is public. As in .NET it is not filled yet and stays empty.
Signature signature = new Signature(stream, new LoadOptions(FileType.PDF));
try {
    List<BaseSignature> signatures = signature.search(s -> s.getPageNumber() == 1);
} finally {
    signature.dispose();
}

Fix — LogLevel had no effect

The level was compared for equality instead of as a set of flags, so with the default LogLevel.All nothing was logged at all, and combined values such as LogLevel.Error | LogLevel.Warning never matched. Warnings logged with an exception also printed a literal placeholder instead of the exception message.

SignatureSettings settings = new SignatureSettings(new ConsoleLogger());
settings.setLogLevel(LogLevel.Error | LogLevel.Warning);

Signature signature = new Signature("contract.pdf", settings);

Scope.

  • Behaviour change: a logger passed in SignatureSettings now receives messages with the default level. Set LogLevel.None or a narrower level to reduce them. (SIGNATURENET-6004)

Fix — empty barcode and QR-code images on Java 11 and later

Signing presentations and spreadsheets with BarcodeSignOptions or QrCodeSignOptions failed with

Cannot open an image. The image size can not be 0!

The signature image was written as JPEG, which the JPEG writer of Java 11 and later refuses for images with transparency, so the image stayed empty. Java 8 was not affected, which made the failure look specific to Linux or Docker. The image is now written as PNG, and an image that cannot be encoded raises an error instead of producing an empty one. (SIGNATUREJAVA-2903)

Fix — custom PDF signer

A custom signer set with DigitalSignOptions.setCustomSignHash was never called. The built-in ICustomSignHash implementations also hashed the digest a second time, so their signatures did not verify. The signer is now called with the digest that was actually used, and the signatures verify. (SIGNATURENET-5208)

Fix — time-stamp server credentials

Credentials were sent to the time-stamp server only when both the user name and the password were set. A server that needs only a user name, or a token in the user name, got an unauthenticated request. They are now sent when either part is set. (SIGNATURENET-5998)

Fix — reused options

  • A VerifyOptions object used for several verify calls kept the signatures of the documents verified earlier, so the result of a later call included them. Each call now starts afresh. (SIGNATURENET-6005)
  • A DigitalSignOptions object used for several presentations signed the later ones with the first certificate and comment. (SIGNATURENET-6006)

Fix — archives

Search of an archive failed with a NullPointerException, and verification of an archive always failed because each document inside it was read as an empty stream. Both work now, and the verification result of an archive lists the signatures of all its documents.

Fix — other fixes

  • Spreadsheets with a picture linked to an external file no longer fail QR-code and barcode search and verification with a NullPointerException; such pictures are skipped. (SIGNATURENET-6002)
  • Certificates whose key entry has a name — most PFX files — were rejected with certificate doesn't contain private key when signing presentations, spreadsheets and VBA projects.
  • Saving a signed document as images produced empty pages (Unsupported file format), which also broke updating and deleting image signatures. On Java 11 and later, images with transparency found in Word documents, and presentation previews in JPEG or BMP, are no longer written empty.
  • JpegSaveOptions, PngSaveOptions, GifSaveOptions and TiffSaveOptions settings such as the JPEG quality were ignored. They are applied now, and the signature information stored in the image metadata is kept.
  • FileType.equals returned true for any two file types, so ReturnContent was written as PNG whatever ReturnContentType was set to.
  • QR-code search in multi-layer images with ReturnContent failed and returned no codes.
  • The default text of BarcodeTypes.GS1CompositeBar used / between the linear and the 2D component, which Aspose.BarCode rejects; it now uses |.
  • Passing options of the wrong type, for example ImageDigitalVerifyOptions for a PDF, failed with FormatException: Index (zero based) must be greater than or equal to zero instead of naming the expected options type.

Update — archive expansion limits

The entries of zip and tar archives were expanded without any limit, so a small archive could expand to an amount of data that exhausts memory. Archives are now checked while they are expanded: at most 10,000 entries, 1 GB in total, and no entry larger than 1 MB compressed more than 100 times. A larger archive fails with GroupDocsSignatureException, whose cause is com.groupdocs.signature.exception.ArchiveSecurityException.

Scope.

  • Behaviour change: archives beyond these limits are rejected.

Update — trial limits

In evaluation mode, signing an archive is no longer limited by the number of documents in it; the page limit still applies to each document. The limit on the number of documents is checked for search, verification, preview and document information. Archives and multi-layer images were also limited to two documents with the wrong message; they now get their own limit and message. (SIGNATURENET-5825)

Update — Aspose libraries and barcode types

The Aspose libraries are updated to the versions used by GroupDocs.Total: Aspose.Words 26.8, Aspose.PDF 26.8.1, Aspose.Cells 26.9, Aspose.Slides 26.9, Aspose.BarCode 26.6, Aspose.Imaging 25.12 and others.

Aspose.BarCode merged the Standard and Extended variants of Code 39 and Code 93. BarcodeTypes.Code39, Code39FullASCII and Code93 are new, as in .NET. Code39Standard, Code39Extended, Code93Standard and Code93Extended remain as deprecated aliases, so existing code compiles and barcodes signed with the old names are still recognised. (SIGNATUREJAVA-2908)

Update — published artifact

  • The manifest declares Automatic-Module-Name: com.groupdocs.signature, so on Java 9 and later the jar resolves as a named automatic module. The copyright year is set at build time.
  • META-INF/ThirdPartyLicenses-BouncyCastle.txt carries the licence of the Bouncy Castle library the jar redistributes, and META-INF/ThirdPartyLicenses-GroupDocs.Signature.txt lists the redistributed components.
  • The jar is no longer signed with jarsigner, whose certificate had expired. Detached PGP signatures (.asc) of the jar, the POM and the javadoc jar are published next to them.
  • The public fields MeCard.auto_Name and the Signatures and Actions fields of DocumentMetaInfoContext are private; use MeCard.getName() and setName().

(SIGNATUREJAVA-2905)

The published POM carries the product name GroupDocs.Signature for Java, a short description, and declares <licenses>, <developers>, <organization> and <scm>. This is what dependency indexes such as MVNRepository display. The license agreement in the distribution package now opens the GroupDocs License Agreement, and the product page, documentation and examples links in readme.txt and the package shortcuts were updated the same way. Metadata and package contents only — no code, behaviour or API changed. (SIGNATUREJAVA-2906, SIGNATUREJAVA-2925)

Resources