Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,14 @@ target_link_libraries(libzip_extract_file PRIVATE PkgConfig::LIBZIP)

add_executable(libzip_add_files src/libzip/add_files.cpp)
target_link_libraries(libzip_add_files PRIVATE PkgConfig::LIBZIP)

# create encrypted archive

add_executable(libzip_create_encrypted_archive src/libzip/create_encrypted_archive.cpp)
target_link_libraries(libzip_create_encrypted_archive PRIVATE PkgConfig::LIBZIP)


# extract encrypted file

add_executable(libzip_extract_encrypted_file src/libzip/extract_encrypted_file.cpp)
target_link_libraries(libzip_extract_encrypted_file PRIVATE PkgConfig::LIBZIP)
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ read, write and manipulate zip archives.
| [create archive](doc/create_archive.md) | :white_check_mark: | :white_check_mark: |
| [extract a single file](doc/extract_single_file.md) | :white_check_mark: | :white_check_mark: |
| [add files to an existing archive](doc/add_files.md) | :x: | :white_check_mark: |
| create encrypted archive | ? | :white_check_mark: |
| extract encrypted archive | ? | :white_check_mark: |

## Build examples

Expand Down
130 changes: 130 additions & 0 deletions src/libzip/create_encrypted_archive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-License-Identifier: Unlicense

#include <zip.h>

#include <iostream>
#include <string>
#include <vector>
#include <filesystem>

namespace
{

void print_usage()
{
std::cout << R"(libzip_create_encrypted_archive, (c) 2026 Falk Werner
Creates an encrypted archive

Usage:
libzip_create_encrypted_archive <archive> <password> <filename>...

Arguments:
archive - filename of the newly created archive
password - password used for encryption
filename - name of the file to add

Example:
libzip_create_encrypted_archive test.zip. secret README.md
)";
}

struct entry
{
std::string local_filename;
std::string archive_filename;
};

struct context
{
context(int argc, char* argv[])
{
show_help = (argc <= 3);
if (argc > 3)
{
archive_filename = argv[1];
password = argv[2];

for(int i = 3; i < argc; i++)
{
std::string const arg = argv[i];
if ((arg == "-h") || (arg == "--help"))
{
show_help = true;
break;
}

entry e = {arg, arg};
auto const pos = arg.find(':');
if (pos != std::string::npos)
{
e = { arg.substr(0, pos), arg.substr(pos +1) };
}
entries.push_back(e);
}
}
}

bool show_help;
std::string archive_filename;
std::string password;
std::vector<entry> entries;
};

int create_encrypted_archive(
std::string const & filename,
std::string const & password,
std::vector<entry> const & entries)
{
int exit_code = EXIT_SUCCESS;

auto * const archive = zip_open(filename.c_str(), ZIP_CREATE | ZIP_TRUNCATE, nullptr);
if (archive == nullptr)
{
std::cerr << "error: failed to create archive" << std::endl;
return EXIT_FAILURE;
}

for(auto const & e: entries)
{
if (!std::filesystem::is_regular_file(e.local_filename))
{
continue;
}

auto * source = zip_source_file(archive, e.local_filename.c_str(), 0,
std::filesystem::file_size(e.local_filename));
auto const i = zip_add(archive, e.archive_filename.c_str(), source);
if (i == -1)
{
std::cerr << "error: failed to add file: " << e.local_filename << std::endl;
exit_code = EXIT_FAILURE;
zip_source_free(source);
}

zip_file_set_encryption(archive, i, ZIP_EM_AES_256, password.c_str());
std::cout << e.local_filename << std::endl;
}

zip_close(archive);
return exit_code;
}

}


int main(int argc, char* argv[])
{
context ctx(argc, argv);
int exit_code = EXIT_SUCCESS;

if (!ctx.show_help)
{
exit_code = create_encrypted_archive(ctx.archive_filename, ctx.password, ctx.entries);
}
else
{
print_usage();
}

return exit_code;
}
65 changes: 65 additions & 0 deletions src/libzip/extract_encrypted_file.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: Unlicense

#include <zip.h>

#include <cstdio>
#include <iostream>
#include <string>


int main(int argc, char* argv[])
{
if (argc != 4)
{
std::cout << R"(libzip_extract_encrypted_file, (c) 2026 Falk Werner
Extract file from an encrypted archive

Usage:
libzip_extrace_encrypted_file <archive> <password> <filename>

Arguments:
archive - filename of an existing encrypted zip archive
password - password
filename - name of the file to extract
)";
}

std::string const archive_filename = argv[1];
std::string const password = argv[2];
std::string const filename = argv[3];

auto * const archive = zip_open(archive_filename.c_str(), ZIP_RDONLY, nullptr);
if (archive == nullptr)
{
std::cerr << "error: failed to open archive" << std::endl;
return EXIT_FAILURE;
}

auto const i = zip_name_locate(archive, filename.c_str(), 0);
if (i == -1)
{
std::cerr << "error: failed to find file in archive" << std::endl;
zip_close(archive);
return EXIT_FAILURE;
}

auto * const file = zip_fopen_encrypted(archive, filename.c_str(), 0, password.c_str());
if (file == nullptr)
{
std::cerr << "error: failed to open archived file" << std::endl;
zip_close(archive);
return EXIT_FAILURE;
}

char buffer[10240];
auto length = zip_fread(file, buffer, 10240);
while (0 < length)
{
fwrite(buffer, 1, length, stdout);
length = zip_fread(file, buffer, 10240);
}

zip_fclose(file);
zip_close(archive);
return EXIT_SUCCESS;
}