Decrypting a Word document produces a different file depending on which time zone I run the code in

If I take an encrypted Word document, and then decrypt it using Aspose, I think it’s reasonable to expect Aspose to produce the same file every time.

However, this is not the case.

Test program:

    private final Path dir = Paths.get("/Users/Daniel/Downloads/decryption time");

    @Test
    public void test1() throws Exception
    {
        System.setSecurityManager(null);

        DateTimeZone zone = DateTimeZone.forID("Australia/Sydney");
        System.out.println("Time zone: " + zone);
        DateTimeZone.setDefault(zone);
        TimeZone.setDefault(zone.toTimeZone());

        try (InputStream stream = Files.newInputStream(dir.resolve("encrypted.doc")))
        {
            Document asposeDocument = new Document(stream, new LoadOptions("password"));
            System.out.println("Created time: " + asposeDocument.getBuiltInDocumentProperties().getCreatedTime());
            asposeDocument.unprotect();

            Path decryptedFile = dir.resolve("decrypted-sydney.doc");
            asposeDocument.save(decryptedFile.toString());

            System.out.println("File digest: " + Arrays.toString(MessageDigest.getInstance("MD5").digest(Files.readAllBytes(decryptedFile))));
        }
    }

    @Test
    public void test2() throws Exception
    {
        System.setSecurityManager(null);

        DateTimeZone zone = DateTimeZone.forID("Asia/Tokyo");
        System.out.println("Time zone: " + zone);
        DateTimeZone.setDefault(zone);
        TimeZone.setDefault(zone.toTimeZone());

        try (InputStream stream = Files.newInputStream(dir.resolve("encrypted.doc")))
        {
            Document asposeDocument = new Document(stream, new LoadOptions("password"));
            System.out.println("Created time: " + asposeDocument.getBuiltInDocumentProperties().getCreatedTime());
            asposeDocument.unprotect();

            Path decryptedFile = dir.resolve("decrypted-tokyo.doc");
            asposeDocument.save(decryptedFile.toString());

            System.out.println("File digest: " + Arrays.toString(MessageDigest.getInstance("MD5").digest(Files.readAllBytes(decryptedFile))));
        }
    }

When I run test1:

Time zone: Australia/Sydney
Created time: Mon Jul 04 15:03:00 AEST 2016
File digest: [33, -19, -22, 81, 59, 112, -94, 44, 117, 111, 92, 98, 7, 45, -68, 7]

When I run test2:

Time zone: Asia/Tokyo
Created time: Mon Jul 04 14:03:00 JST 2016
File digest: [-71, 37, 3, 34, 117, 100, -21, -104, -122, -64, -40, 35, 116, -106, -69, 61]

The difference in the files shows Aspose stamping in two date values:

bucket:decryption time daniel$ diff decrypted-sydney.doc.txt decrypted-tokyo.doc.txt 
3522c3522
< 0000e030  f0 d0 02 00 00 68 01 00  00 00 00 c3 23 47 27 c5  |.....h......#G'.|
---
> 0000e030  f0 d0 02 00 00 68 01 00  00 00 00 83 23 47 27 85  |.....h......#G'.|

(The next line starts with 23 47 27.)

Decoding the values, we see that in Sydney, it is using Mon Jul 04 2016 15:03:10 for creation time and Mon Jul 04 2016 15:05:00 for last modified, but for Tokyo, it is using Mon Jul 04 2016 14:03:00 for creation time and Mon Jul 04 2016 14:05:00 for last modified.

I believe these two values should have the same hour value, because the file itself would have stored the local time, not the UTC time. So Aspose must be either reading the wrong value when reading the date from the original, or writing the wrong data when writing the date to the destination.

I wasn’t able to check stuff any further than that.

@nuix

Thanks for your inquiry. I have tested the scenario with a sample encrypted file using Aspose.Words for Java 17.6. I am getting same digest for different timezone settings. We will appreciate it if you please use latest version of Aspose.Words for java for encrypting the Word document, decrypting and share the results.

Created time: Tue Mar 07 07:41:00 AEDT 2017
File digest: [6, -37, -128, -103, -82, 54, 46, 85, 96, -74, 80, 35, 2, -86, 6, 21]
Created time: Tue Mar 07 05:41:00 JST 2017
File digest: [6, -37, -128, -103, -82, 54, 46, 85, 96, -74, 80, 35, 2, -86, 6, 21]

Best Regards,

I retried on 17.6 with the same document and same code.

Time zone: Australia/Sydney
Created time: Mon Jul 04 15:03:00 AEST 2016
File digest: [36, -115, 14, -12, -46, -37, -13, -50, 5, 19, -59, -33, -35, -65, -43, -9]

Time zone: Asia/Tokyo
Created time: Mon Jul 04 14:03:00 JST 2016
File digest: [-104, -85, 81, 112, 84, -29, 123, -92, -59, 17, -25, -87, -40, -36, -19, -76]

So the two digests are still different, but different to the digests we had in 17.2.

Next round of investigation:

First, I made a new sample encrypted document with a known creation time:

    @Test
    public void makeDocument() throws Exception
    {
        System.setSecurityManager(null);

        Document document = new Document();
        // Creating in default zone on assumption that that's what Aspose should be using, but really their date should
        // take a LocalDateTime instead.
        document.getBuiltInDocumentProperties().setCreatedTime(new DateTime(2001, 1, 1, 0, 0, 0, DateTimeZone.getDefault()).toDate());

        DocumentBuilder builder = new DocumentBuilder(document);
        builder.writeln("Hello World!");

        document.protect(ProtectionType.ALL, "password");
        document.save(dir.resolve("encrypted.doc").toString());
    }

I’ll attach the document in case mine differs: encrypted.doc.zip (1.9 KB)

Run test1 (this run as well is using Aspose.Words 17.6):

Time zone: Australia/Sydney
Created time: Mon Jan 01 11:00:00 AEDT 2001
File digest: [19, -36, -54, 115, 51, -6, 79, 127, -105, 50, 39, -105, 22, 12, 124, 26]

It erroneously came out as 11:00 even though I had set 00:00, so I’m guessing the bug occurs when reading the value.

Run test2:

Time zone: Asia/Tokyo
Created time: Mon Jan 01 09:00:00 JST 2001
File digest: [72, -70, -79, 120, -57, -116, -13, -109, -103, 83, 97, -23, 10, 36, 80, -96]

Same deal here - comes out as 09:00, but I would expect 00:00 since the document is not storing the zone.

Looks like it might also happen even if you just load the document:

    @Test
    public void testWithoutProtection() throws Exception
    {
        System.setSecurityManager(null);

        Document document = new Document();
        // Creating in default zone on assumption that that's what Aspose should be using, but really their date should
        // take a LocalDateTime instead.
        document.getBuiltInDocumentProperties().setCreatedTime(new DateTime(2001, 1, 1, 0, 0, 0, DateTimeZone.getDefault()).toDate());
        System.out.println("Created time before saving: " + document.getBuiltInDocumentProperties().getCreatedTime());

        DocumentBuilder builder = new DocumentBuilder(document);
        builder.writeln("Hello World!");

        Path docFile = dir.resolve("delete-me.doc");
        document.save(docFile.toString());
        System.out.println("Created time after saving: " + document.getBuiltInDocumentProperties().getCreatedTime());

        Document document2 = new Document(docFile.toString());
        System.out.println("Created time after loading again: " + document2.getBuiltInDocumentProperties().getCreatedTime());
    }

Output:

Created time before saving: Mon Jan 01 00:00:00 AEDT 2001
Created time after saving: Mon Jan 01 00:00:00 AEDT 2001
Created time after loading again: Mon Jan 01 11:00:00 AEDT 2001

@nuix

Thanks for sharing additional information. Please also confirm which Jar you are using for DateTime, DateTimeZone etc or you can share your Java file. It will help us to investigate and address your issue exactly.

We are sorry for the inconvenience.

Best Regards,

DateTime is from Joda Time 2.9.9:

https://mvnrepository.com/artifact/joda-time/joda-time/2.9.9

It’s probably possible to replace it with ZonedDateTime in the Java standard library as well, we just haven’t migrated our code to use that stuff yet.

@nuix

Thanks for sharing additional information. We have logged a ticket WORDSJAVA-1615 in our issue tracking system for further investigation and rectification. We will keep you updated about the issue resolution progress within this forum thread.

We are sorry for the inconvenience.

Best Regards,

@nuix

Thanks for your patience. Please note we have investigated the issue and found it is not a bug. Please consider following points when working with time in Aspose.Words for Java.

  1. document.getBuiltInDocumentProperties().setCreatedTime() “Gets or sets date of the document creation in UTC.” - the quote from javadoc.
  2. To set time zone for Aspose.Word application is better to use CurrentThreadSettings.setTimeZone(TimeZone).

I can verify that setting the value using CurrentThreadSettings.getTimeZoneSettings().set(TimeZone) does fix the problem.

I really worry about this kind of API, though. If I have to manipulate two different documents on one thread, I have to switch it back and forth all the time. And it’s very easy to forget to put the calls in for new code.

If a setting like this could be added per-document, that would be much easier to use correctly.

@nuix

Thanks for your feedback. It is good to know that you have managed to resolve the issue with above suggestion.

We have also shared your concern with the product team and will notify you as soon as we get a feedback.

@nuix,

Thanks for your patience. To set the property “from different timezones” you need to simply follow these steps. However, if still there is any difference in your requirements and our understanding then please share you complete use case here. We will look into it and will guide you accordingly.

  1. create desired DateTime in desired timezone
  2. convert this DateTime to UTC Date
  3. assign this Date to BuiltInDocumentProperties.CreatedTime.