I ended up making the Zip file "by hand" and compressing the blocks individually to calculate their hash.
#include <zlib.h>
#define BLOCK_SIZE 65536
z_stream strm;
// Using init2 to avold the zlib header
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
int step = 0.
// len is the length of the whole input file
while (len - step > 0) {
// Get the size of this block (either 64k or the remaining of the file if less)
long block_size = (len - step) > BLOCK_SIZE ? BLOCK_SIZE : (len - step);
// strm_in is the input buffer for the compression
// skipped the buffer allocation for simplicity
for (int i = 0; i < block_size; i++) {
strm_in[i] = input_file_buffer[step + i];
}
// Calculate the hash (out of the scope for this question)
// Store in a particular structure for reference later
BlockData bd;
bd.hash = make_block_hash(strm_in, block_size);
// Update the zlib stream info
// also skipped the out buffer allocation in this sample
strm.avail_in = block_size;
strm.avail_out = out_buffer_size;
strm.next_in = strm_in;
strm.next_out = strm_out;
// Save the total bytes for comparison later
int total_out_before = strm.total_out;
// Compress (assume the out buffer size will be always enough)
deflate(&strm, Z_FULL_FLUSH); // A Full flush here is needed for the APPX format
// Save the compressed block in the size
compressed_file->save_buffer(strm_out, strm.total_out - total_out_before);
// Save the size of the compressed block
bd.compressed_size = strm.total_out - total_out_before;
// Store the block data in a list
blocks_info->push(bd);
// Move to the next block
step += block_size;
}
// End the compressed stream
strm.avail_in = 0;
strm.avail_out = out_buffer_size;
strm.next_in = strm_in;
strm.next_out = strm_out;
int total_out_before = strm.total_out;
// Finish the stream
deflate(&strm, Z_FINISH);
// Save the compression tail to the file
compressed_file->save_buffer(strm_out, strm.total_out - total_out_before);
// Clean up
deflateEnd(&strm);
After going all of this trouble I found a cross-platform open source tool that package and sign Windows store apps. Might be helpful for other people and also for me who thought signing outside of Windows would be impossible.