0

I need to zip a payload (a dataweave script outputting CSV) with a password using Mule 4 with encryption AES256.

I've checked the Compression Module of Mule 4 and it doesnt support passwords, I've tried using it in combination of the Cryptography Module but it either ends up encrypting the CSV in the zip, or encrypting the zip.

I need the solution to be able to run in Cloudhub too.

Any ideas?

Cheers, Steve

Steve
  • 445
  • 1
  • 8
  • 18

2 Answers2

1

Just encrypting the files will not work because the Zip format expects an encryption header for encrypted files.

Mule Compression module uses the Apache Commons Compress library to implement Zip files, which doesn't currently support Zip encrypted files.

You can try to either implement your own module or extend the existing Compression module to support encryption. You can also just call a Java class to do it, but it will not be as reusable in Mule applications.

One library that can be used to implement encrypted Zip files is Zip4j but there might be others. Since it is a Java implementation it should work in any platform.

aled
  • 21,330
  • 3
  • 27
  • 34
  • Thanks Aled, I was looking at Zip4j (which is a library I've used in the past for a native java app), do you have any examples on how to use it in Mule? – Steve Jul 07 '21 at 21:46
  • You can just create a Java class in your Mule 4 project to wrap the use of Zip4j, which would be like much you are used to, then call from a flow using the Java Module (https://docs.mulesoft.com/java-module/1.2/). Depending on what you are trying to do, I guess you should try to return a stream to the file contents to be used next in the flow as the payload. There are several examples of using Zip4j in Java code if you need them. Calling Java code doesn't require any specific coding with the Java module. If you want to package it in your own module for reuse you'll need to learn the Mule SDK. – aled Jul 07 '21 at 23:10
  • Yeah that's what I've been playing around with this morning and got it "working" locally... currently having to use the Write component of the CSV to disk for Zip4J to pick it up... Just uploading to Cloudhub now to see how nicely it plays in there. – Steve Jul 08 '21 at 03:07
0

My solution:

       <java:invoke-static doc:name="Invoke static" doc:id="6244c876-c938-4541-a8aa-a94d2198aa28" class="au.com.test.PasswordProtectedZip" method="zip(String, String)">

            <java:args ><![CDATA[#[{

 "fileName": p('file.path') ++ vars.fileName,

 "password": p('secure::encryption.password')

}]]]></java:args>

       </java:invoke-static>

The Java Class:

package au.com.test;

import java.io.File;

import java.io.IOException;

import java.util.Arrays;

import java.util.List;

import net.lingala.zip4j.ZipFile;

import net.lingala.zip4j.model.ZipParameters;

import net.lingala.zip4j.model.enums.AesKeyStrength;

import net.lingala.zip4j.model.enums.EncryptionMethod;

public class PasswordProtectedZip {

 public static File zip(String fileName, String password) {

       System.out.println("Zipping " + fileName);

       File file = null;

       try {

            ZipParameters zipParameters = new ZipParameters();

            zipParameters.setEncryptFiles(true);

            zipParameters.setEncryptionMethod(EncryptionMethod.AES);

            zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);



            List<File> filesToAdd = Arrays.asList(new File(fileName));



            ZipFile zipFile = new ZipFile(fileName + ".zip", password.toCharArray());

            zipFile.addFiles(filesToAdd, zipParameters);

            file = zipFile.getFile();

            System.out.println("file = " + file.getAbsolutePath());

            zipFile.close();

       } catch (Exception e) {

            e.printStackTrace();

       }



       return file;

 }

}

And the deps in the pom.xml:

    <dependency>
        <groupId>net.lingala.zip4j</groupId>
        <artifactId>zip4j</artifactId>
        <version>1.3.1</version>
    </dependency>
Steve
  • 445
  • 1
  • 8
  • 18