GroupDocs.Signature for .NET 23.6 Release Notes

In this release, we are excited to announce support of the multi-layers DICOM files support. New product features allow to process and manage DICOM documents with new signatures, obtain file information, and provide searching for signature artifacts. This development will enhance the usability of our product in a variety of healthcare, and medical imaging applications. There are about 4 features, 2 enhancements and five bug fixes in this release.

Full list of changes in this release

KeyCategorySummary
SIGNATURENET-4559★ FeatureImplement searching DICOM image documents for signatures
SIGNATURENET-4557★ FeatureImplement obtaining DICOM image documents information
SIGNATURENET-4501★ FeatureImplement signing DICOM image documents
SIGNATURENET-4372★ FeatureImplement Searching in the Certificate documents
SIGNATURENET-4537★ EnhancementExtend DocumentResultSignature with the Error message
SIGNATURENET-4532★ EnhancementProvide signing Spreadsheets by using digital signature as container for certificates
SIGNATURENET-4548🔧 FixDigital certificate issue with signing under Linux
SIGNATURENET-4505🔧 FixSome two-pages WordProcessing documents could not be signed at trial mode
SIGNATURENET-4486🔧 FixDigital certificate for Spreadsheets has wrong format
SIGNATURENET-4481🔧 FixAspose.Word 23.1 Digitally signed .ODT document raises exception during digital signatures deletion
SIGNATURENET-4432🔧 FixDigitally signed Open Office .ODT document raises exception during digital signatures deletion

Major Features

This release includes four new DICOM image format features and two enhancements:

Implement searching DICOM image documents for signatures

🌐 The searching process within the DICOM documents does not look different than searching for single-page raster image, except for the fact that all result images will contain the page number of the layer where the signature was found.

/// <summary>
/// Search multi-layer image document for signatures.
/// This example provided for formats like DICOM
/// </summary>
using (Signature signature = new Signature("signed.dcm"))
{
    // setup search options
    QrCodeSearchOptions searchOptions = new QrCodeSearchOptions()
    {
        // enable grabbing image content feature
        ReturnContent = true,
        // specify exact image type to be returned
        ReturnContentType = FileType.PNG
    };
    // search multi-layer document
    List<QrCodeSignature> signatures = signature.Search<QrCodeSignature>(searchOptions);
    Console.WriteLine($"\nSource document ['{fileName}'] contains following QR-code signature(s).");
    // output signatures
    foreach (QrCodeSignature qrSignature in signatures)
    {
        // due to multi-layers each signature will contain the page number
        Console.Write($"Found Image signature at page {qrSignature.PageNumber} and id# {qrSignature.SignatureId}.");
        Console.WriteLine($"Location at {qrSignature.Left}-{qrSignature.Top}. Size is {qrSignature.Width}x{qrSignature.Height}.");
    }
}

Implement obtaining DICOM image documents information

🌐 How to obtain the DICOM image information - this is a functionality that provides users with easy access to vital details embedded within the DICOM files. This includes each image page information and its size.

/// <summary>
/// Obtain information from multi-layer image document.
/// This example provided for formats like DICOM
/// </summary>
using (Signature signature = new Signature("signed.dcm"))
{
    IDocumentInfo documentInfo = signature.GetDocumentInfo();
    Console.WriteLine($"Document properties {Path.GetFileName(filePath)}:");
    Console.WriteLine($" - format : {documentInfo.FileType.FileFormat}");
    Console.WriteLine($" - extension : {documentInfo.FileType.Extension}");
    Console.WriteLine($" - size : {documentInfo.Size}");
    Console.WriteLine($" - page count : {documentInfo.PageCount}");
    foreach (PageInfo pageInfo in documentInfo.Pages)
    {
        Console.WriteLine($" - page-{pageInfo.PageNumber} Width {pageInfo.Width}, Height {pageInfo.Height}");
    }
}

Implement signing DICOM image documents

🌐 Public API to sign the multilayer image documents is the same as signing any other file format. The output SignResult instance will contains the newly added signature objects with the PageNumber equal to image layer index + 1. So the PageNumber property for the multilayer images will keep values from 1 (not 0-based).

/// <summary>
/// Sign multi-layer image document.
/// </summary>
using (var signature = new Signature("sample.dcm"))
{
    var options = new QrCodeSignOptions("Patient #36363393. R: No-Issues")
    {
        // set signature position 
        Left = 10, Top = 10,
        // set signature rectangle
        Width = 200, Height = 200
    };
    // sign document to file
    SignResult signResult = signature.Sign(outputFilePath, options);
    Console.WriteLine($"\nDocument signed with {signResult.Succeeded.Count} signatures");
    Console.WriteLine("\nList of newly created signatures:");
    foreach (BaseSignature temp in signResult.Succeeded)
    {
        Console.WriteLine($"{temp.SignatureType} at page #{temp.PageNumber}: Id:{temp.SignatureId}.");
    }
}

Implement Searching in the Certificate documents

🌐 In this release, we’ve introduced new search options CertificateSearchOptions to provide search capabilities for certificates. Now, users can quickly locate critical information within their certificates by searching for particular data. Example below demonstrates how to search if certificate contain specific string from the serial number.

/// <summary>
/// Search if certificate contain specific string from the serial number.
/// </summary>
using (Signature signature = new Signature(certificatePath, loadOptions))
{
    CertificateSearchOptions options = new CertificateSearchOptions()
    {
        // check the serial number
        Text = "AAD0D15C628A",
        // find exact math
        MatchType = TextMatchType.Contains,
    };

    // search for certificate data
    List<MetadataSignature> result = signature.Search<MetadataSignature>(options);
    if (result.Count>0)
    {
        Console.WriteLine("\nCertificate contains following search results");
        foreach (MetadataSignature temp in result)
        {
            Console.WriteLine($"\t\t-{temp.Name} - {temp.Value}");
        }
    }
    else
    {
        Helper.WriteError("\nCertificate failed search process.");
    }
}

Extend DocumentResultSignature with the Error message

🌐 For the archive document processing, when the SignResult contains list of succeeded and failed DocumentResultSignature elements we added new property to monitor the error. Following example shows how to analyze this variable.

/// <summary>
/// Support Succeeded and Failed list as result of processing archives
/// </summary>
using (var signature = new Signature("sample.zip"))
{
    // create sign options
    var options = new TextSignOptions("signed!")
    {
        // set signature position
        Left = 100,
        Top = 100
    };
    // sign archive to new zip file
    SignResult result = signature.Sign("output.zip", options);
    // analyze the failed documents
    foreach (DocumentResultSignature document in result.Failed)
    {
        Console.WriteLine($"Document {document.FileName} processed with error: {document.ErrorMessage}");
    }
}