https://github.com/falk-werner/zipsign
Sign and verify ZIP archives
https://github.com/falk-werner/zipsign
cms openssl sign signature zip
Last synced: 8 months ago
JSON representation
Sign and verify ZIP archives
- Host: GitHub
- URL: https://github.com/falk-werner/zipsign
- Owner: falk-werner
- License: mpl-2.0
- Created: 2019-11-17T17:40:28.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2025-08-27T18:31:42.000Z (10 months ago)
- Last Synced: 2025-08-28T03:24:20.200Z (10 months ago)
- Topics: cms, openssl, sign, signature, zip
- Language: C++
- Size: 301 KB
- Stars: 40
- Watchers: 0
- Forks: 14
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
[](https://github.com/falk-werner/zipsign/actions/workflows/build-ubuntu.yml)
[](https://github.com/falk-werner/zipsign/actions/workflows/build-windows.yml)
[](https://github.com/falk-werner/zipsign/actions/workflows/build-maxos.yml)
[](https://snapcraft.io/zipsign)
# zipsign
Sign and verify ZIP archives.
## tl;dr
- create private key and certificate for signing
`openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes`
- create a zip archive
`echo 42 > answer.txt`
`zip -r archive.zip answer.txt`
- sign the archive
`zipsign sign -f archive.zip -p key.pem -c cert.pem`
- verify signature of the archive
`zipsign verify -f archive.zip -c cert.pem`
## Command line options
### Sign
Sign an archive.
zipsign sign -f -p -c [-i ...]
| Short | Long | Argument | Description |
| ----- | ------------------- | ----------- | -------------------------------------------------------- |
| -f | --file | archive.zip | Required. ZIP file to sign. |
| -p | --private-key | key.pem | Required. Filename of signers private key. |
| -c | --certificate | cert.pem | Required. Filename of signers certificate. |
| -i | --intermediate | inter.pem | Optional. Filename of intermediate certifiacte to embed. |
| -e | --embed-certificate | _none_ | Optional. Embed signers certificate in signature. |
| -v | --verbose | _none_ | Optional. Enable additional output. |
During signing the ZIP file will be altered (ZIP comment will be re-written).
It is possible to specifify none, one or more intermediate certificates, that will be embedded in
the signature. Embedding intermediate certificates are used to close then chain of trust for later
verfication.
It is also possible to specify one or more signers by adding private key and certificate pairs.
_Note_: It is recommended to embed signers certificates when using multiple signers.
### Verify
Verfiy an archive.
zipsign verify -f -c [-k ]
| Short | Long | Argument | Description |
| ----- | ------------- | ----------- | ------------------------------------------ |
| -f | --file | archive.zip | Required. ZIP file to verify. |
| -c | --certificate | cert.pem | Required. Filename of signers certificate. |
| -k | --keyring | keyring.pem | Optional. Filename of PKI. |
| -v | --verbose | _none_ | Optional. Enable additional output. |
If the archive is signed by multiple signers, multiple certificates can be
specified for validation.
_Note_: Verfication is done only against the given certificates. Other signers are
ignored, even if the archive is signed by multiple signers.
_Note_: Only one keyring can be specified.
#### Return Codes
| Return Code | Description |
| ----------- | ----------- |
| 0 | Verification succeeded |
| 1 | General error |
| 2 | Error - signature is missing |
| 3 | Error - invalid certificate chain |
| 4 | Error - invalid signature |
### Info
Prints signature of ZIP archive in human readable form.
zipsign info -f
| Short | Long | Argument | Description |
| ----- | ------------- | ----------- | ------------------------------------------ |
| -f | --file | archive.zip | Required. ZIP file to print info. |
## How it works
[ZIP file format](https://en.wikipedia.org/wiki/Zip_(file_format)) specifies a comment field,
which is located at the very end of the archive.
This allows to create a [CMS](https://en.wikipedia.org/wiki/Cryptographic_Message_Syntax) signature
over the full archive (excluding the comment) and stores it Base64-encoded as new comment.
For verification, the comment is read from the archive and verified against archives contents.
## Signature format
ZipSign used the following format for the signature
ZipSign=data:application/cms;base64,
The signature data consists of base64 encoded PEM data.
To print the signature from a previously signed ZIP archive, one can use the following command.
> unzip -z archive.zip
Archive: archive.zip
ZipSign=data:application/cms;base64,MIIDow...
## Sign and verify using keyring (PKI)
Verification using a PKI is supported via `--keyring` option during validation.
Setup a CA suitable for signing is a complex topic. A good starting point might
be the PKI tutorial at
[https://pki-tutorial.readthedocs.io/en/latest/](https://pki-tutorial.readthedocs.io/en/latest/).
The test directory contains a bash script [create-pki.sh](test/openssl/create-pki.sh), which
creates a small PKI used within unit tests.
# sign archive alice key and certificate
zipsign sign -f archive.zip -p certs/alice.key -c certs/alice.crt
# verify archive using keyring
zipsign verify -f archive.zip -c certs/alice.crt -k keyring.pem
## Include intermediate certificates
To complete chain of trust, on or more intermediate certificates can be specified.
# sign archive with alice's key and certificate, add signing CA as intermediate
zipsign sign -f archive.zip -p certs/alice.key -c certs/alice.crt -i ca/signing-ca.crt
# verify archive using root CA as keyring
zipsign verify -f archive.zip -c certs/alice.crt -k ca/root-ca.crt
## Multiple signers
An archive can be signed by multiple signers.
This might come in handy during certiface changes, e.g. when one certificate will expire
shortly and the new one should be used simultaniously.
To sign an archive with multiple signers, you can specify one certificate and one private
key per signer. The certificates should be embedded in the archives signature, so they
can be located during verification.
zipsign sign -f archive.zip \
-p certs/alice.key -c certs/alice.cert \
-p self-signed/key.pem -c self-signed/cert.pem \
-e
During verification, you can choose the proper signer (or both).
# verify against self signed certificate
zipsign verfiy -f archive.zip -c self-signed/cert.pem
# verify against alice's certificates
zipsign verify -f archive.zip -c certs/alice.crt -k keyring.pem
# verify against both certificates
zipsign verify -f archive.zip \
-c self-signed/cert.pem \
-c certs/alice.crt -k keyring.pem
## Known Limitations
- ZIP comments are limited to a maximum of 64 KBytes.
CMS allows to include signer certificates, intermediate certificates as well as multiple signatures.
When overused, this might not fit into the comment.
# Build
To build the project, cmake is used.
mkdir build
cd build
cmake ..
make
sudo make install
## Build using Docker
There are some dockerfiles provided in [docker](docker) subdirectory.
docker build --rm --build-arg "USER_ID=`id -u`" --tag zipsign-ubuntu -f docker/ubuntu.dockerfile .
To run the docker container, use
docker run --rm --user="`id -u`" -it zipsign-ubuntu
## Build snap
To build the snap, install [snapcraft](https://snapcraft.io/docs/installing-snapcraft) and run the following command:
```
snapcraft
```
## Dependencies
- [OpenSSL>=3.0](https://www.openssl.org/) (libssl-dev)
- [Google Test](https://github.com/google/googletest) *(Test only)*
## External references
- [ZIP file format](https://en.wikipedia.org/wiki/Zip_(file_format))
- [CMS](https://en.wikipedia.org/wiki/Cryptographic_Message_Syntax)
- [PKI tutorial](https://pki-tutorial.readthedocs.io/en/latest/)