Archived Forum Post

Index of archived forum posts

Question:

Change Password for Existing Encrypted Zip

Sep 30 '15 at 09:44

This method doesn’t change the encryption. The same is true if I add a document to a not existent ZIP file (the first document) the newly created ZIP file overtakes the actual parameters (encrypted, PW…). If I add another document with other values e.g. a new PW, nothing changes.

    Friend Sub SetEncryption(ByVal OldPW As String, ByVal NewPW As String)
        '===== Sets or removes (if NewPW is empty) encryption from a ZIP file.

With myZIP
            If Not .OpenZip(myStoreFolder + myCurrentZIPFileName) Then
                MsgBox("No such ZIP file.")
                Exit Sub
            End If

.DecryptPassword = OldPW
            .EncryptPassword = NewPW
            .PasswordProtect = False
            If NewPW = "" Then
                .Encryption = 0
            Else
                .EncryptKeyLength = 128
                .Encryption = 4           'AES
            End If
            .FileName = myStoreFolder + myCurrentZIPFileName         'Tried also another file name, different from the source name

.WriteZipAndClose()                                      'No error here
        End With
    End Sub

Answer

The Zip file format does not have a single, central location that specifies the password and encryption properties for all files in the archive. Each file within the archive is separate and independent from others w.r.t. encryption properties. In other words, each file contained within a zip archive contains an encryption header that specifies the encryption properties, such as AES key size, salt (IV), and a password verification value.

Customarily, all files within a .zip are typically encrypted with the same encryption properties (i.e. same AES algorithm, key size, password, etc.). This information is duplicated and present within each file's header within the zip archive.

When an existing encrypted .zip is opened and re-written, the encrypted/compressed data for the existing entries is simply streamed to the output of the new .zip, with no changes. To change the password, what effectively needs to happen is that the existing entries must be decrypted/decompressed and then re-compressed/re-encrypted. This is not something that can be safely done in-memory -- it may require the use of temporary files, and for this reason Chilkat does not do it.

One way of accomplishing the task is to unzip to a temp directory, create a new Zip object instance, and then add the files from the temp directory, etc.

Another way of doing it, assuming everything is not too big for memory, is to iterate over the entries, decrypt/decompress to get the unencrypted/decompressed data, and then replace the entry's data with the unencrypted/decompressed data. Here is an example in C#:

    private void reEncryptToolStripMenuItem_Click(object sender, EventArgs e)
        {
        Chilkat.Zip zip = new Chilkat.Zip();

bool success = zip.OpenZip("c:/aaworkarea/secret.zip");
        if (!success)
        {
        textBox2.Text = zip.LastErrorText;
        return;
        }

zip.DecryptPassword = "secret";

int numEntries = zip.NumEntries;

int i;
        for (i = 0; i < numEntries; i++)
        {
        Chilkat.ZipEntry entry = zip.GetEntryByIndex(i);

if (!entry.IsDirectory)
            {
            // Decrypt/inflate and replace w/ the unencrypted data.
            byte[] fileData = entry.Inflate();
            success = entry.ReplaceData(fileData);
            if (!success)
            {
            textBox2.Text = zip.LastErrorText;
            return;
            }
            }

}

zip.EncryptPassword = "newsecret";

zip.FileName = "c:/aaworkarea/newsecret.zip";
        success = zip.WriteZipAndClose();
        if (!success)
        {
        textBox2.Text = zip.LastErrorText;
        return;
        }

textBox2.Text = "OK";
        }