1

I would like to encrypt a zip file using OpenPGP.js (https://browserpgp.github.io/). All processing needs to be done on the client-side, without involvement of Node.js. Using the javascript-based browserpgp.js, encryption of plaintext file is easy, but encryption of zip files are challenging. I am attaching the code I use to encrypt the zip file. Since, the contents of zip file are not text, so I have used guides for working with binary data from https://github.com/openpgpjs/openpgpjs. I believe the resulting file after encryption of a zip file should be in raw/binary format, and the resulting file saved from the following encryption code is in binary. However, I verified it and its cannot be decrypted.

I am using the Kleopatra desktop OpenPGP tool (https://www.openpgp.org/software/kleopatra/) to verify if the resulting encrypted file. Using the tool, I tested to see if I can decrypt the encrypted file using my private key. The resulting binary file cannot be decrypted using the Kleopatra tool. So I was wondering what is wrong with this code, as the resulting file should be decryptable using Kleopatra.

You can create two public keys using the tool here: https://browserpgp.github.io

function openpgp_encryptZIPFile(){  
  var zip = new JSZip();
  zip.file("Hello.txt", "Hello World\n");
  var img = zip.folder("images");
  zip.generateAsync({type:"blob"})
  .then(function(content) {
      console.log('contents: ' + content);     
      encryptedZipFile = OpenPGPEncryptDataZipFile(content);
  });  
}

async function OpenPGPEncryptDataZipFile(zipBlob) 
{    
  //This is my public key
  const key1 = `somekey1`;  //you would have to put a public key here 
    //This is the testuser public key
  const key2 = `somekey2`; //you would have to put another public key here 
  const publicKeysArmored = [key1, key2];
  //create a combined key
  const publicKeys = await Promise.all(publicKeysArmored.map(armoredKey => openpgp.readKey({ armoredKey }))); 
    
  var binaryData = new Uint8Array(zipBlob);  
  
  //https://github.com/openpgpjs/openpgpjs/blob/main/README.md
  //For OpenPGP.js v4 syntax is:  const message = openpgp.Message.fromBinary(binaryData); 
  //For OpenPGP.js v5 syntax is:  const message2 = await openpgp.createMessage({ binary: binaryData });
  //`const {data: encrypted}' OR `const { message }' OR just `const encrypted'
  const  encrypted  = await openpgp.encrypt({
  message: await openpgp.createMessage({ binary: binaryData }),      
     encryptionKeys: publicKeys,
     //signingKeys: privateKey // optional
     format: 'binary'
  });
  console.log('encrypted: ' + encrypted);
  var encryptedBlob = new Blob([encrypted],{type: 'text/plain'});    
  //var encryptedBlob = new Blob([encrypted], {type: "octet/stream"});
  saveAs(encryptedBlob, 'test.zip.enc' ); 
}

1 Answer 1

0

Someone from OpenPGPjs github repo answered this

new Uint8Array(zipBlob) most likely doesn't do what you think it does. Perhaps try new Uint8Array(await zipBlob.arrayBuffer()), or just ask JSZip for a Uint8Array instead of a Blob in the first place.

Also, octet/stream is not a valid MIME type. Perhaps you meant application/octet-stream?

So I changed new Uint8Array(zipBlob) to new Uint8Array(await zipBlob.arrayBuffer()) and it worked.

https://github.com/openpgpjs/openpgpjs/discussions/1535

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.